summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nv50_pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_pm.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv50_pm.c249
1 files changed, 109 insertions, 140 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c
index d020ed4979b4..c4a65039b1ca 100644
--- a/drivers/gpu/drm/nouveau/nv50_pm.c
+++ b/drivers/gpu/drm/nouveau/nv50_pm.c
@@ -22,14 +22,20 @@
* Authors: Ben Skeggs
*/
-#include "drmP.h"
-#include "nouveau_drv.h"
+#include <drm/drmP.h>
+#include "nouveau_drm.h"
#include "nouveau_bios.h"
#include "nouveau_hw.h"
#include "nouveau_pm.h"
#include "nouveau_hwsq.h"
+
#include "nv50_display.h"
+#include <subdev/bios/pll.h>
+#include <subdev/clock.h>
+#include <subdev/timer.h>
+#include <subdev/fb.h>
+
enum clk_src {
clk_src_crystal,
clk_src_href,
@@ -49,19 +55,20 @@ static u32 read_clk(struct drm_device *, enum clk_src);
static u32
read_div(struct drm_device *dev)
{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_device *device = nouveau_dev(dev);
+ struct nouveau_drm *drm = nouveau_drm(dev);
- switch (dev_priv->chipset) {
+ switch (nv_device(drm->device)->chipset) {
case 0x50: /* it exists, but only has bit 31, not the dividers.. */
case 0x84:
case 0x86:
case 0x98:
case 0xa0:
- return nv_rd32(dev, 0x004700);
+ return nv_rd32(device, 0x004700);
case 0x92:
case 0x94:
case 0x96:
- return nv_rd32(dev, 0x004800);
+ return nv_rd32(device, 0x004800);
default:
return 0x00000000;
}
@@ -70,12 +77,13 @@ read_div(struct drm_device *dev)
static u32
read_pll_src(struct drm_device *dev, u32 base)
{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_device *device = nouveau_dev(dev);
+ struct nouveau_drm *drm = nouveau_drm(dev);
u32 coef, ref = read_clk(dev, clk_src_crystal);
- u32 rsel = nv_rd32(dev, 0x00e18c);
+ u32 rsel = nv_rd32(device, 0x00e18c);
int P, N, M, id;
- switch (dev_priv->chipset) {
+ switch (nv_device(drm->device)->chipset) {
case 0x50:
case 0xa0:
switch (base) {
@@ -84,11 +92,11 @@ read_pll_src(struct drm_device *dev, u32 base)
case 0x4008: id = !!(rsel & 0x00000008); break;
case 0x4030: id = 0; break;
default:
- NV_ERROR(dev, "ref: bad pll 0x%06x\n", base);
+ NV_ERROR(drm, "ref: bad pll 0x%06x\n", base);
return 0;
}
- coef = nv_rd32(dev, 0x00e81c + (id * 0x0c));
+ coef = nv_rd32(device, 0x00e81c + (id * 0x0c));
ref *= (coef & 0x01000000) ? 2 : 4;
P = (coef & 0x00070000) >> 16;
N = ((coef & 0x0000ff00) >> 8) + 1;
@@ -97,7 +105,7 @@ read_pll_src(struct drm_device *dev, u32 base)
case 0x84:
case 0x86:
case 0x92:
- coef = nv_rd32(dev, 0x00e81c);
+ coef = nv_rd32(device, 0x00e81c);
P = (coef & 0x00070000) >> 16;
N = (coef & 0x0000ff00) >> 8;
M = (coef & 0x000000ff) >> 0;
@@ -105,14 +113,14 @@ read_pll_src(struct drm_device *dev, u32 base)
case 0x94:
case 0x96:
case 0x98:
- rsel = nv_rd32(dev, 0x00c050);
+ rsel = nv_rd32(device, 0x00c050);
switch (base) {
case 0x4020: rsel = (rsel & 0x00000003) >> 0; break;
case 0x4008: rsel = (rsel & 0x0000000c) >> 2; break;
case 0x4028: rsel = (rsel & 0x00001800) >> 11; break;
case 0x4030: rsel = 3; break;
default:
- NV_ERROR(dev, "ref: bad pll 0x%06x\n", base);
+ NV_ERROR(drm, "ref: bad pll 0x%06x\n", base);
return 0;
}
@@ -123,8 +131,8 @@ read_pll_src(struct drm_device *dev, u32 base)
case 3: id = 0; break;
}
- coef = nv_rd32(dev, 0x00e81c + (id * 0x28));
- P = (nv_rd32(dev, 0x00e824 + (id * 0x28)) >> 16) & 7;
+ coef = nv_rd32(device, 0x00e81c + (id * 0x28));
+ P = (nv_rd32(device, 0x00e824 + (id * 0x28)) >> 16) & 7;
P += (coef & 0x00070000) >> 16;
N = (coef & 0x0000ff00) >> 8;
M = (coef & 0x000000ff) >> 0;
@@ -141,7 +149,9 @@ read_pll_src(struct drm_device *dev, u32 base)
static u32
read_pll_ref(struct drm_device *dev, u32 base)
{
- u32 src, mast = nv_rd32(dev, 0x00c040);
+ struct nouveau_device *device = nouveau_dev(dev);
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ u32 src, mast = nv_rd32(device, 0x00c040);
switch (base) {
case 0x004028:
@@ -159,7 +169,7 @@ read_pll_ref(struct drm_device *dev, u32 base)
case 0x00e810:
return read_clk(dev, clk_src_crystal);
default:
- NV_ERROR(dev, "bad pll 0x%06x\n", base);
+ NV_ERROR(drm, "bad pll 0x%06x\n", base);
return 0;
}
@@ -171,17 +181,18 @@ read_pll_ref(struct drm_device *dev, u32 base)
static u32
read_pll(struct drm_device *dev, u32 base)
{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- u32 mast = nv_rd32(dev, 0x00c040);
- u32 ctrl = nv_rd32(dev, base + 0);
- u32 coef = nv_rd32(dev, base + 4);
+ struct nouveau_device *device = nouveau_dev(dev);
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ u32 mast = nv_rd32(device, 0x00c040);
+ u32 ctrl = nv_rd32(device, base + 0);
+ u32 coef = nv_rd32(device, base + 4);
u32 ref = read_pll_ref(dev, base);
u32 clk = 0;
int N1, N2, M1, M2;
if (base == 0x004028 && (mast & 0x00100000)) {
/* wtf, appears to only disable post-divider on nva0 */
- if (dev_priv->chipset != 0xa0)
+ if (nv_device(drm->device)->chipset != 0xa0)
return read_clk(dev, clk_src_dom6);
}
@@ -205,13 +216,14 @@ read_pll(struct drm_device *dev, u32 base)
static u32
read_clk(struct drm_device *dev, enum clk_src src)
{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- u32 mast = nv_rd32(dev, 0x00c040);
+ struct nouveau_device *device = nouveau_dev(dev);
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ u32 mast = nv_rd32(device, 0x00c040);
u32 P = 0;
switch (src) {
case clk_src_crystal:
- return dev_priv->crystal;
+ return device->crystal;
case clk_src_href:
return 100000; /* PCIE reference clock */
case clk_src_hclk:
@@ -230,7 +242,7 @@ read_clk(struct drm_device *dev, enum clk_src src)
break;
case clk_src_nvclk:
if (!(mast & 0x00100000))
- P = (nv_rd32(dev, 0x004028) & 0x00070000) >> 16;
+ P = (nv_rd32(device, 0x004028) & 0x00070000) >> 16;
switch (mast & 0x00000003) {
case 0x00000000: return read_clk(dev, clk_src_crystal) >> P;
case 0x00000001: return read_clk(dev, clk_src_dom6);
@@ -239,7 +251,7 @@ read_clk(struct drm_device *dev, enum clk_src src)
}
break;
case clk_src_sclk:
- P = (nv_rd32(dev, 0x004020) & 0x00070000) >> 16;
+ P = (nv_rd32(device, 0x004020) & 0x00070000) >> 16;
switch (mast & 0x00000030) {
case 0x00000000:
if (mast & 0x00000080)
@@ -251,8 +263,8 @@ read_clk(struct drm_device *dev, enum clk_src src)
}
break;
case clk_src_mclk:
- P = (nv_rd32(dev, 0x004008) & 0x00070000) >> 16;
- if (nv_rd32(dev, 0x004008) & 0x00000200) {
+ P = (nv_rd32(device, 0x004008) & 0x00070000) >> 16;
+ if (nv_rd32(device, 0x004008) & 0x00000200) {
switch (mast & 0x0000c000) {
case 0x00000000:
return read_clk(dev, clk_src_crystal) >> P;
@@ -266,7 +278,7 @@ read_clk(struct drm_device *dev, enum clk_src src)
break;
case clk_src_vdec:
P = (read_div(dev) & 0x00000700) >> 8;
- switch (dev_priv->chipset) {
+ switch (nv_device(drm->device)->chipset) {
case 0x84:
case 0x86:
case 0x92:
@@ -275,7 +287,7 @@ read_clk(struct drm_device *dev, enum clk_src src)
case 0xa0:
switch (mast & 0x00000c00) {
case 0x00000000:
- if (dev_priv->chipset == 0xa0) /* wtf?? */
+ if (nv_device(drm->device)->chipset == 0xa0) /* wtf?? */
return read_clk(dev, clk_src_nvclk) >> P;
return read_clk(dev, clk_src_crystal) >> P;
case 0x00000400:
@@ -303,7 +315,7 @@ read_clk(struct drm_device *dev, enum clk_src src)
}
break;
case clk_src_dom6:
- switch (dev_priv->chipset) {
+ switch (nv_device(drm->device)->chipset) {
case 0x50:
case 0xa0:
return read_pll(dev, 0x00e810) >> 2;
@@ -329,22 +341,22 @@ read_clk(struct drm_device *dev, enum clk_src src)
break;
}
- NV_DEBUG(dev, "unknown clock source %d 0x%08x\n", src, mast);
+ NV_DEBUG(drm, "unknown clock source %d 0x%08x\n", src, mast);
return 0;
}
int
nv50_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- if (dev_priv->chipset == 0xaa ||
- dev_priv->chipset == 0xac)
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ if (nv_device(drm->device)->chipset == 0xaa ||
+ nv_device(drm->device)->chipset == 0xac)
return 0;
perflvl->core = read_clk(dev, clk_src_nvclk);
perflvl->shader = read_clk(dev, clk_src_sclk);
perflvl->memory = read_clk(dev, clk_src_mclk);
- if (dev_priv->chipset != 0x50) {
+ if (nv_device(drm->device)->chipset != 0x50) {
perflvl->vdec = read_clk(dev, clk_src_vdec);
perflvl->dom6 = read_clk(dev, clk_src_dom6);
}
@@ -363,22 +375,25 @@ struct nv50_pm_state {
};
static u32
-calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll,
+calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll,
u32 clk, int *N1, int *M1, int *log2P)
{
+ struct nouveau_device *device = nouveau_dev(dev);
+ struct nouveau_bios *bios = nouveau_bios(device);
+ struct nouveau_clock *pclk = nouveau_clock(device);
struct nouveau_pll_vals coef;
int ret;
- ret = get_pll_limits(dev, reg, pll);
+ ret = nvbios_pll_parse(bios, reg, pll);
if (ret)
return 0;
- pll->vco2.maxfreq = 0;
+ pll->vco2.max_freq = 0;
pll->refclk = read_pll_ref(dev, reg);
if (!pll->refclk)
return 0;
- ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef);
+ ret = pclk->pll_calc(pclk, pll, clk, &coef);
if (ret == 0)
return 0;
@@ -461,27 +476,29 @@ mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec)
static u32
mclk_mrg(struct nouveau_mem_exec_func *exec, int mr)
{
+ struct nouveau_device *device = nouveau_dev(exec->dev);
if (mr <= 1)
- return nv_rd32(exec->dev, 0x1002c0 + ((mr - 0) * 4));
+ return nv_rd32(device, 0x1002c0 + ((mr - 0) * 4));
if (mr <= 3)
- return nv_rd32(exec->dev, 0x1002e0 + ((mr - 2) * 4));
+ return nv_rd32(device, 0x1002e0 + ((mr - 2) * 4));
return 0;
}
static void
mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data)
{
- struct drm_nouveau_private *dev_priv = exec->dev->dev_private;
+ struct nouveau_device *device = nouveau_dev(exec->dev);
+ struct nouveau_fb *pfb = nouveau_fb(device);
struct nv50_pm_state *info = exec->priv;
struct hwsq_ucode *hwsq = &info->mclk_hwsq;
if (mr <= 1) {
- if (dev_priv->vram_rank_B)
+ if (pfb->ram.ranks > 1)
hwsq_wr32(hwsq, 0x1002c8 + ((mr - 0) * 4), data);
hwsq_wr32(hwsq, 0x1002c0 + ((mr - 0) * 4), data);
} else
if (mr <= 3) {
- if (dev_priv->vram_rank_B)
+ if (pfb->ram.ranks > 1)
hwsq_wr32(hwsq, 0x1002e8 + ((mr - 2) * 4), data);
hwsq_wr32(hwsq, 0x1002e0 + ((mr - 2) * 4), data);
}
@@ -490,11 +507,12 @@ mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data)
static void
mclk_clock_set(struct nouveau_mem_exec_func *exec)
{
+ struct nouveau_device *device = nouveau_dev(exec->dev);
struct nv50_pm_state *info = exec->priv;
struct hwsq_ucode *hwsq = &info->mclk_hwsq;
- u32 ctrl = nv_rd32(exec->dev, 0x004008);
+ u32 ctrl = nv_rd32(device, 0x004008);
- info->mmast = nv_rd32(exec->dev, 0x00c040);
+ info->mmast = nv_rd32(device, 0x00c040);
info->mmast &= ~0xc0000000; /* get MCLK_2 from HREF */
info->mmast |= 0x0000c000; /* use MCLK_2 as MPLL_BYPASS clock */
@@ -508,7 +526,7 @@ mclk_clock_set(struct nouveau_mem_exec_func *exec)
static void
mclk_timing_set(struct nouveau_mem_exec_func *exec)
{
- struct drm_device *dev = exec->dev;
+ struct nouveau_device *device = nouveau_dev(exec->dev);
struct nv50_pm_state *info = exec->priv;
struct nouveau_pm_level *perflvl = info->perflvl;
struct hwsq_ucode *hwsq = &info->mclk_hwsq;
@@ -516,7 +534,7 @@ mclk_timing_set(struct nouveau_mem_exec_func *exec)
for (i = 0; i < 9; i++) {
u32 reg = 0x100220 + (i * 4);
- u32 val = nv_rd32(dev, reg);
+ u32 val = nv_rd32(device, reg);
if (val != perflvl->timing.reg[i])
hwsq_wr32(hwsq, reg, perflvl->timing.reg[i]);
}
@@ -526,7 +544,8 @@ static int
calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl,
struct nv50_pm_state *info)
{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_device *device = nouveau_dev(dev);
u32 crtc_mask = nv50_display_active_crtcs(dev);
struct nouveau_mem_exec_func exec = {
.dev = dev,
@@ -542,22 +561,22 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl,
.priv = info
};
struct hwsq_ucode *hwsq = &info->mclk_hwsq;
- struct pll_lims pll;
+ struct nvbios_pll pll;
int N, M, P;
int ret;
/* use pcie refclock if possible, otherwise use mpll */
- info->mctrl = nv_rd32(dev, 0x004008);
+ info->mctrl = nv_rd32(device, 0x004008);
info->mctrl &= ~0x81ff0200;
if (clk_same(perflvl->memory, read_clk(dev, clk_src_href))) {
- info->mctrl |= 0x00000200 | (pll.log2p_bias << 19);
+ info->mctrl |= 0x00000200 | (pll.bias_p << 19);
} else {
ret = calc_pll(dev, 0x4008, &pll, perflvl->memory, &N, &M, &P);
if (ret == 0)
return -EINVAL;
info->mctrl |= 0x80000000 | (P << 22) | (P << 16);
- info->mctrl |= pll.log2p_bias << 19;
+ info->mctrl |= pll.bias_p << 19;
info->mcoef = (N << 8) | M;
}
@@ -567,7 +586,7 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl,
hwsq_op5f(hwsq, crtc_mask, 0x00); /* wait for scanout */
hwsq_op5f(hwsq, crtc_mask, 0x01); /* wait for vblank */
}
- if (dev_priv->chipset >= 0x92)
+ if (nv_device(drm->device)->chipset >= 0x92)
hwsq_wr32(hwsq, 0x611200, 0x00003300); /* disable scanout */
hwsq_setf(hwsq, 0x10, 0); /* disable bus access */
hwsq_op5f(hwsq, 0x00, 0x01); /* no idea :s */
@@ -578,7 +597,7 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl,
hwsq_setf(hwsq, 0x10, 1); /* enable bus access */
hwsq_op5f(hwsq, 0x00, 0x00); /* no idea, reverse of 0x00, 0x01? */
- if (dev_priv->chipset >= 0x92)
+ if (nv_device(drm->device)->chipset >= 0x92)
hwsq_wr32(hwsq, 0x611200, 0x00003330); /* enable scanout */
hwsq_fini(hwsq);
return 0;
@@ -587,16 +606,17 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl,
void *
nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_device *device = nouveau_dev(dev);
+ struct nouveau_drm *drm = nouveau_drm(dev);
struct nv50_pm_state *info;
struct hwsq_ucode *hwsq;
- struct pll_lims pll;
+ struct nvbios_pll pll;
u32 out, mast, divs, ctrl;
int clk, ret = -EINVAL;
int N, M, P1, P2;
- if (dev_priv->chipset == 0xaa ||
- dev_priv->chipset == 0xac)
+ if (nv_device(drm->device)->chipset == 0xaa ||
+ nv_device(drm->device)->chipset == 0xac)
return ERR_PTR(-ENODEV);
info = kmalloc(sizeof(*info), GFP_KERNEL);
@@ -645,7 +665,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
clk = calc_div(perflvl->core, perflvl->vdec, &P1);
/* see how close we can get using xpll/hclk as a source */
- if (dev_priv->chipset != 0x98)
+ if (nv_device(drm->device)->chipset != 0x98)
out = read_pll(dev, 0x004030);
else
out = read_clk(dev, clk_src_hclkm3d2);
@@ -654,7 +674,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
/* select whichever gets us closest */
if (abs((int)perflvl->vdec - clk) <=
abs((int)perflvl->vdec - out)) {
- if (dev_priv->chipset != 0x98)
+ if (nv_device(drm->device)->chipset != 0x98)
mast |= 0x00000c00;
divs |= P1 << 8;
} else {
@@ -682,7 +702,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
}
/* vdec/dom6: complete switch to new clocks */
- switch (dev_priv->chipset) {
+ switch (nv_device(drm->device)->chipset) {
case 0x92:
case 0x94:
case 0x96:
@@ -698,7 +718,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
/* core/shader: make sure sclk/nvclk are disconnected from their
* PLLs (nvclk to dom6, sclk to hclk)
*/
- if (dev_priv->chipset < 0x92)
+ if (nv_device(drm->device)->chipset < 0x92)
mast = (mast & ~0x001000b0) | 0x00100080;
else
mast = (mast & ~0x000000b3) | 0x00000081;
@@ -710,7 +730,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
if (clk == 0)
goto error;
- ctrl = nv_rd32(dev, 0x004028) & ~0xc03f0100;
+ ctrl = nv_rd32(device, 0x004028) & ~0xc03f0100;
mast &= ~0x00100000;
mast |= 3;
@@ -723,7 +743,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
* cases will be handled by tying to nvclk, but it's possible there's
* corners
*/
- ctrl = nv_rd32(dev, 0x004020) & ~0xc03f0100;
+ ctrl = nv_rd32(device, 0x004020) & ~0xc03f0100;
if (P1-- && perflvl->shader == (perflvl->core << 1)) {
hwsq_wr32(hwsq, 0x004020, (P1 << 19) | (P1 << 16) | ctrl);
@@ -752,11 +772,12 @@ error:
static int
prog_hwsq(struct drm_device *dev, struct hwsq_ucode *hwsq)
{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_device *device = nouveau_dev(dev);
+ struct nouveau_drm *drm = nouveau_drm(dev);
u32 hwsq_data, hwsq_kick;
int i;
- if (dev_priv->chipset < 0x94) {
+ if (nv_device(drm->device)->chipset < 0x94) {
hwsq_data = 0x001400;
hwsq_kick = 0x00000003;
} else {
@@ -764,22 +785,22 @@ prog_hwsq(struct drm_device *dev, struct hwsq_ucode *hwsq)
hwsq_kick = 0x00000001;
}
/* upload hwsq ucode */
- nv_mask(dev, 0x001098, 0x00000008, 0x00000000);
- nv_wr32(dev, 0x001304, 0x00000000);
- if (dev_priv->chipset >= 0x92)
- nv_wr32(dev, 0x001318, 0x00000000);
+ nv_mask(device, 0x001098, 0x00000008, 0x00000000);
+ nv_wr32(device, 0x001304, 0x00000000);
+ if (nv_device(drm->device)->chipset >= 0x92)
+ nv_wr32(device, 0x001318, 0x00000000);
for (i = 0; i < hwsq->len / 4; i++)
- nv_wr32(dev, hwsq_data + (i * 4), hwsq->ptr.u32[i]);
- nv_mask(dev, 0x001098, 0x00000018, 0x00000018);
+ nv_wr32(device, hwsq_data + (i * 4), hwsq->ptr.u32[i]);
+ nv_mask(device, 0x001098, 0x00000018, 0x00000018);
/* launch, and wait for completion */
- nv_wr32(dev, 0x00130c, hwsq_kick);
- if (!nv_wait(dev, 0x001308, 0x00000100, 0x00000000)) {
- NV_ERROR(dev, "hwsq ucode exec timed out\n");
- NV_ERROR(dev, "0x001308: 0x%08x\n", nv_rd32(dev, 0x001308));
+ nv_wr32(device, 0x00130c, hwsq_kick);
+ if (!nv_wait(device, 0x001308, 0x00000100, 0x00000000)) {
+ NV_ERROR(drm, "hwsq ucode exec timed out\n");
+ NV_ERROR(drm, "0x001308: 0x%08x\n", nv_rd32(device, 0x001308));
for (i = 0; i < hwsq->len / 4; i++) {
- NV_ERROR(dev, "0x%06x: 0x%08x\n", 0x1400 + (i * 4),
- nv_rd32(dev, 0x001400 + (i * 4)));
+ NV_ERROR(drm, "0x%06x: 0x%08x\n", 0x1400 + (i * 4),
+ nv_rd32(device, 0x001400 + (i * 4)));
}
return -EIO;
@@ -791,20 +812,22 @@ prog_hwsq(struct drm_device *dev, struct hwsq_ucode *hwsq)
int
nv50_pm_clocks_set(struct drm_device *dev, void *data)
{
+ struct nouveau_device *device = nouveau_dev(dev);
struct nv50_pm_state *info = data;
struct bit_entry M;
int ret = -EBUSY;
/* halt and idle execution engines */
- nv_mask(dev, 0x002504, 0x00000001, 0x00000001);
- if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010))
+ nv_mask(device, 0x002504, 0x00000001, 0x00000001);
+ if (!nv_wait(device, 0x002504, 0x00000010, 0x00000010))
goto resume;
- if (!nv_wait(dev, 0x00251c, 0x0000003f, 0x0000003f))
+ if (!nv_wait(device, 0x00251c, 0x0000003f, 0x0000003f))
goto resume;
/* program memory clock, if necessary - must come before engine clock
* reprogramming due to how we construct the hwsq scripts in pre()
*/
+#define nouveau_bios_init_exec(a,b) nouveau_bios_run_init_table((a), (b), NULL, 0)
if (info->mclk_hwsq.len) {
/* execute some scripts that do ??? from the vbios.. */
if (!bit_table(dev, 'M', &M) && M.version == 1) {
@@ -826,61 +849,7 @@ nv50_pm_clocks_set(struct drm_device *dev, void *data)
ret = prog_hwsq(dev, &info->eclk_hwsq);
resume:
- nv_mask(dev, 0x002504, 0x00000001, 0x00000000);
+ nv_mask(device, 0x002504, 0x00000001, 0x00000000);
kfree(info);
return ret;
}
-
-static int
-pwm_info(struct drm_device *dev, int *line, int *ctrl, int *indx)
-{
- if (*line == 0x04) {
- *ctrl = 0x00e100;
- *line = 4;
- *indx = 0;
- } else
- if (*line == 0x09) {
- *ctrl = 0x00e100;
- *line = 9;
- *indx = 1;
- } else
- if (*line == 0x10) {
- *ctrl = 0x00e28c;
- *line = 0;
- *indx = 0;
- } else {
- NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", *line);
- return -ENODEV;
- }
-
- return 0;
-}
-
-int
-nv50_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty)
-{
- int ctrl, id, ret = pwm_info(dev, &line, &ctrl, &id);
- if (ret)
- return ret;
-
- if (nv_rd32(dev, ctrl) & (1 << line)) {
- *divs = nv_rd32(dev, 0x00e114 + (id * 8));
- *duty = nv_rd32(dev, 0x00e118 + (id * 8));
- return 0;
- }
-
- return -EINVAL;
-}
-
-int
-nv50_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty)
-{
- int ctrl, id, ret = pwm_info(dev, &line, &ctrl, &id);
- if (ret)
- return ret;
-
- nv_mask(dev, ctrl, 0x00010001 << line, 0x00000001 << line);
- nv_wr32(dev, 0x00e114 + (id * 8), divs);
- nv_wr32(dev, 0x00e118 + (id * 8), duty | 0x80000000);
- return 0;
-}