summary refs log tree commit diff
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.c247
1 files changed, 108 insertions, 139 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c
index 07593fd73af3..c4a65039b1ca 100644
--- a/drivers/gpu/drm/nouveau/nv50_pm.c
+++ b/drivers/gpu/drm/nouveau/nv50_pm.c
@@ -23,13 +23,19 @@
  */
 
 #include <drm/drmP.h>
-#include "nouveau_drv.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;
-}