drm/nouveau: port remainder of drm code, and rip out compat layer
v2: Ben Skeggs <bskeggs@redhat.com> - fill in nouveau_pm.dev to prevent oops - fix ppc issues (build + OF shadow) Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Šī revīzija ir iekļauta:
@@ -23,12 +23,19 @@
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include <nouveau_bios.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,
|
||||
@@ -48,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;
|
||||
}
|
||||
@@ -69,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) {
|
||||
@@ -83,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;
|
||||
@@ -96,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;
|
||||
@@ -104,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;
|
||||
}
|
||||
|
||||
@@ -122,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;
|
||||
@@ -140,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:
|
||||
@@ -158,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;
|
||||
}
|
||||
|
||||
@@ -170,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);
|
||||
}
|
||||
|
||||
@@ -204,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:
|
||||
@@ -229,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);
|
||||
@@ -238,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)
|
||||
@@ -250,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;
|
||||
@@ -265,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:
|
||||
@@ -274,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:
|
||||
@@ -302,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;
|
||||
@@ -328,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);
|
||||
}
|
||||
@@ -365,10 +378,13 @@ static u32
|
||||
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;
|
||||
|
||||
@@ -377,7 +393,7 @@ calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll,
|
||||
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;
|
||||
|
||||
@@ -460,26 +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 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 (nvfb_vram_rank_B(exec->dev))
|
||||
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 (nvfb_vram_rank_B(exec->dev))
|
||||
if (pfb->ram.ranks > 1)
|
||||
hwsq_wr32(hwsq, 0x1002e8 + ((mr - 2) * 4), data);
|
||||
hwsq_wr32(hwsq, 0x1002e0 + ((mr - 2) * 4), data);
|
||||
}
|
||||
@@ -488,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 */
|
||||
|
||||
@@ -506,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;
|
||||
@@ -514,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]);
|
||||
}
|
||||
@@ -524,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,
|
||||
@@ -545,7 +566,7 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl,
|
||||
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.bias_p << 19);
|
||||
@@ -565,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 */
|
||||
@@ -576,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;
|
||||
@@ -585,7 +606,8 @@ 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 nvbios_pll pll;
|
||||
@@ -593,8 +615,8 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
|
||||
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);
|
||||
@@ -643,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);
|
||||
@@ -652,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 {
|
||||
@@ -680,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:
|
||||
@@ -696,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;
|
||||
@@ -708,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;
|
||||
|
||||
@@ -721,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);
|
||||
@@ -750,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 {
|
||||
@@ -762,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;
|
||||
@@ -789,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) {
|
||||
@@ -824,7 +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;
|
||||
}
|
||||
@@ -832,6 +857,8 @@ resume:
|
||||
static int
|
||||
pwm_info(struct drm_device *dev, int *line, int *ctrl, int *indx)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
|
||||
if (*line == 0x04) {
|
||||
*ctrl = 0x00e100;
|
||||
*line = 4;
|
||||
@@ -847,7 +874,7 @@ pwm_info(struct drm_device *dev, int *line, int *ctrl, int *indx)
|
||||
*line = 0;
|
||||
*indx = 0;
|
||||
} else {
|
||||
NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", *line);
|
||||
NV_ERROR(drm, "unknown pwm ctrl for gpio %d\n", *line);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -857,13 +884,14 @@ pwm_info(struct drm_device *dev, int *line, int *ctrl, int *indx)
|
||||
int
|
||||
nv50_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty)
|
||||
{
|
||||
struct nouveau_device *device = nouveau_dev(dev);
|
||||
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));
|
||||
if (nv_rd32(device, ctrl) & (1 << line)) {
|
||||
*divs = nv_rd32(device, 0x00e114 + (id * 8));
|
||||
*duty = nv_rd32(device, 0x00e118 + (id * 8));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -873,12 +901,13 @@ nv50_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty)
|
||||
int
|
||||
nv50_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty)
|
||||
{
|
||||
struct nouveau_device *device = nouveau_dev(dev);
|
||||
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);
|
||||
nv_mask(device, ctrl, 0x00010001 << line, 0x00000001 << line);
|
||||
nv_wr32(device, 0x00e114 + (id * 8), divs);
|
||||
nv_wr32(device, 0x00e118 + (id * 8), duty | 0x80000000);
|
||||
return 0;
|
||||
}
|
||||
|
Atsaukties uz šo jaunā problēmā
Block a user