Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
[linux-2.6-microblaze.git] / drivers / gpu / drm / nouveau / nv50_pm.c
index 07593fd..c4a6503 100644 (file)
  */
 
 #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;
-}