summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/core/subdev
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/core/subdev')
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bar/base.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c15
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/P0260.c109
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/base.c55
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c29
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/init.c18
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/therm.c11
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/base.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h8
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/gm107.c56
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c50
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/gm107.c38
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.h8
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/priv.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/ramgm107.c56
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c34
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c7
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c7
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c (renamed from drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c)109
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h21
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c142
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/base.c55
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mxm/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/base.c14
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fan.c25
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c40
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c57
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c83
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h27
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/timer/priv.h6
48 files changed, 906 insertions, 259 deletions
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
index 7098ddd54678..bdf594116f3f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
@@ -118,8 +118,8 @@ nouveau_bar_create_(struct nouveau_object *parent,
if (ret)
return ret;
- bar->iomem = ioremap(pci_resource_start(device->pdev, 3),
- pci_resource_len(device->pdev, 3));
+ bar->iomem = ioremap(nv_device_resource_start(device, 3),
+ nv_device_resource_len(device, 3));
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
index 090d594a21b3..f748ba49dfc8 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
@@ -139,7 +139,7 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
/* BAR3 */
start = 0x0100000000ULL;
- limit = start + pci_resource_len(device->pdev, 3);
+ limit = start + nv_device_resource_len(device, 3);
ret = nouveau_vm_new(device, start, limit, start, &vm);
if (ret)
@@ -173,7 +173,7 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
/* BAR1 */
start = 0x0000000000ULL;
- limit = start + pci_resource_len(device->pdev, 1);
+ limit = start + nv_device_resource_len(device, 1);
ret = nouveau_vm_new(device, start, limit--, start, &vm);
if (ret)
@@ -231,7 +231,7 @@ static int
nv50_bar_init(struct nouveau_object *object)
{
struct nv50_bar_priv *priv = (void *)object;
- int ret;
+ int ret, i;
ret = nouveau_bar_init(&priv->base);
if (ret)
@@ -249,6 +249,8 @@ nv50_bar_init(struct nouveau_object *object)
nv_wr32(priv, 0x001704, 0x40000000 | priv->mem->addr >> 12);
nv_wr32(priv, 0x001708, 0x80000000 | priv->bar1->node->offset >> 4);
nv_wr32(priv, 0x00170c, 0x80000000 | priv->bar3->node->offset >> 4);
+ for (i = 0; i < 8; i++)
+ nv_wr32(priv, 0x001900 + (i * 4), 0x00000000);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
index bac5e754de35..3f30db62e656 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
@@ -84,7 +84,6 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_object **pobject)
{
struct nouveau_device *device = nv_device(parent);
- struct pci_dev *pdev = device->pdev;
struct nvc0_bar_priv *priv;
struct nouveau_gpuobj *mem;
struct nouveau_vm *vm;
@@ -107,14 +106,14 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret)
return ret;
- ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 3), 0, &vm);
+ ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 3), 0, &vm);
if (ret)
return ret;
atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]);
ret = nouveau_gpuobj_new(nv_object(priv), NULL,
- (pci_resource_len(pdev, 3) >> 12) * 8,
+ (nv_device_resource_len(device, 3) >> 12) * 8,
0x1000, NVOBJ_FLAG_ZERO_ALLOC,
&vm->pgt[0].obj[0]);
vm->pgt[0].refcount[0] = 1;
@@ -128,8 +127,8 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr));
nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr));
- nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 3) - 1));
- nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 3) - 1));
+ nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 3) - 1));
+ nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 3) - 1));
/* BAR1 */
ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0,
@@ -143,7 +142,7 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret)
return ret;
- ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 1), 0, &vm);
+ ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 1), 0, &vm);
if (ret)
return ret;
@@ -156,8 +155,8 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr));
nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr));
- nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 1) - 1));
- nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 1) - 1));
+ nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 1) - 1));
+ nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 1) - 1));
priv->base.alloc = nouveau_bar_alloc;
priv->base.kmap = nvc0_bar_kmap;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/P0260.c b/drivers/gpu/drm/nouveau/core/subdev/bios/P0260.c
new file mode 100644
index 000000000000..199f4e5f7488
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/P0260.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bios/bit.h>
+#include <subdev/bios/ramcfg.h>
+#include <subdev/bios/P0260.h>
+
+u32
+nvbios_P0260Te(struct nouveau_bios *bios,
+ u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz)
+{
+ struct bit_entry bit_P;
+ u32 data = 0x00000000;
+
+ if (!bit_entry(bios, 'P', &bit_P)) {
+ if (bit_P.version == 2 && bit_P.length > 0x63)
+ data = nv_ro32(bios, bit_P.offset + 0x60);
+ if (data) {
+ *ver = nv_ro08(bios, data + 0);
+ switch (*ver) {
+ case 0x10:
+ *hdr = nv_ro08(bios, data + 1);
+ *cnt = nv_ro08(bios, data + 2);
+ *len = 4;
+ *xnr = nv_ro08(bios, data + 3);
+ *xsz = 4;
+ return data;
+ default:
+ break;
+ }
+ }
+ }
+
+ return 0x00000000;
+}
+
+u32
+nvbios_P0260Ee(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len)
+{
+ u8 hdr, cnt, xnr, xsz;
+ u32 data = nvbios_P0260Te(bios, ver, &hdr, &cnt, len, &xnr, &xsz);
+ if (data && idx < cnt)
+ return data + hdr + (idx * *len);
+ return 0x00000000;
+}
+
+u32
+nvbios_P0260Ep(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len,
+ struct nvbios_P0260E *info)
+{
+ u32 data = nvbios_P0260Ee(bios, idx, ver, len);
+ memset(info, 0x00, sizeof(*info));
+ switch (!!data * *ver) {
+ case 0x10:
+ info->data = nv_ro32(bios, data);
+ return data;
+ default:
+ break;
+ }
+ return 0x00000000;
+}
+
+u32
+nvbios_P0260Xe(struct nouveau_bios *bios, int idx, u8 *ver, u8 *xsz)
+{
+ u8 hdr, cnt, len, xnr;
+ u32 data = nvbios_P0260Te(bios, ver, &hdr, &cnt, &len, &xnr, xsz);
+ if (data && idx < xnr)
+ return data + hdr + (cnt * len) + (idx * *xsz);
+ return 0x00000000;
+}
+
+u32
+nvbios_P0260Xp(struct nouveau_bios *bios, int idx, u8 *ver, u8 *hdr,
+ struct nvbios_P0260X *info)
+{
+ u32 data = nvbios_P0260Xe(bios, idx, ver, hdr);
+ memset(info, 0x00, sizeof(*info));
+ switch (!!data * *ver) {
+ case 0x10:
+ info->data = nv_ro32(bios, data);
+ return data;
+ default:
+ break;
+ }
+ return 0x00000000;
+}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
index ef0c9c4a8cc3..e9df94f96d78 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
@@ -90,10 +90,26 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios)
int i;
if (device->card_type >= NV_50) {
- if ( device->card_type < NV_C0 ||
- !(nv_rd32(bios, 0x022500) & 0x00000001))
- addr = (u64)(nv_rd32(bios, 0x619f04) & 0xffffff00) << 8;
+ if (device->card_type >= NV_C0 && device->card_type < GM100) {
+ if (nv_rd32(bios, 0x022500) & 0x00000001)
+ return;
+ } else
+ if (device->card_type >= GM100) {
+ if (nv_rd32(bios, 0x021c04) & 0x00000001)
+ return;
+ }
+
+ addr = nv_rd32(bios, 0x619f04);
+ if (!(addr & 0x00000008)) {
+ nv_debug(bios, "... not enabled\n");
+ return;
+ }
+ if ( (addr & 0x00000003) != 1) {
+ nv_debug(bios, "... not in vram\n");
+ return;
+ }
+ addr = (u64)(addr >> 8) << 8;
if (!addr) {
addr = (u64)nv_rd32(bios, 0x001700) << 16;
addr += 0xf0000;
@@ -141,6 +157,10 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
pcireg = 0x001850;
access = nv_mask(bios, pcireg, 0x00000001, 0x00000000);
+ /* WARNING: PROM accesses should always be 32-bits aligned. Other
+ * accesses work on most chipset but do not on Kepler chipsets
+ */
+
/* bail if no rom signature, with a workaround for a PROM reading
* issue on some chipsets. the first read after a period of
* inactivity returns the wrong result, so retry the first header
@@ -148,31 +168,32 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
*/
i = 16;
do {
- if (nv_rd08(bios, 0x300000) == 0x55)
+ if ((nv_rd32(bios, 0x300000) & 0xffff) == 0xaa55)
break;
} while (i--);
- if (!i || nv_rd08(bios, 0x300001) != 0xaa)
- goto out;
-
- /* additional check (see note below) - read PCI record header */
- pcir = nv_rd08(bios, 0x300018) |
- nv_rd08(bios, 0x300019) << 8;
- if (nv_rd08(bios, 0x300000 + pcir) != 'P' ||
- nv_rd08(bios, 0x300001 + pcir) != 'C' ||
- nv_rd08(bios, 0x300002 + pcir) != 'I' ||
- nv_rd08(bios, 0x300003 + pcir) != 'R')
+ if (!i)
goto out;
/* read entire bios image to system memory */
- bios->size = nv_rd08(bios, 0x300002) * 512;
+ bios->size = ((nv_rd32(bios, 0x300000) >> 16) & 0xff) * 512;
if (!bios->size)
goto out;
bios->data = kmalloc(bios->size, GFP_KERNEL);
if (bios->data) {
- for (i = 0; i < bios->size; i++)
- nv_wo08(bios, i, nv_rd08(bios, 0x300000 + i));
+ for (i = 0; i < bios->size; i+=4)
+ nv_wo32(bios, i, nv_rd32(bios, 0x300000 + i));
+ }
+
+ /* check the PCI record header */
+ pcir = nv_ro16(bios, 0x0018);
+ if (bios->data[pcir + 0] != 'P' ||
+ bios->data[pcir + 1] != 'C' ||
+ bios->data[pcir + 2] != 'I' ||
+ bios->data[pcir + 3] != 'R') {
+ bios->size = 0;
+ kfree(bios->data);
}
out:
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
index 2d9b9d7a7992..88606bfaf847 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
@@ -142,9 +142,36 @@ dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len,
if (*ver >= 0x40) {
u32 conf = nv_ro32(bios, dcb + 0x04);
switch (outp->type) {
+ case DCB_OUTPUT_DP:
+ switch (conf & 0x00e00000) {
+ case 0x00000000:
+ outp->dpconf.link_bw = 0x06;
+ break;
+ case 0x00200000:
+ outp->dpconf.link_bw = 0x0a;
+ break;
+ case 0x00400000:
+ default:
+ outp->dpconf.link_bw = 0x14;
+ break;
+ }
+
+ switch (conf & 0x0f000000) {
+ case 0x0f000000:
+ outp->dpconf.link_nr = 4;
+ break;
+ case 0x03000000:
+ outp->dpconf.link_nr = 2;
+ break;
+ case 0x01000000:
+ default:
+ outp->dpconf.link_nr = 1;
+ break;
+ }
+
+ /* fall-through... */
case DCB_OUTPUT_TMDS:
case DCB_OUTPUT_LVDS:
- case DCB_OUTPUT_DP:
outp->link = (conf & 0x00000030) >> 4;
outp->sorconf.link = outp->link; /*XXX*/
outp->extdev = 0x00;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
index de201baeb053..acaeaf79e3f0 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
@@ -118,6 +118,8 @@ init_conn(struct nvbios_init *init)
static inline u32
init_nvreg(struct nvbios_init *init, u32 reg)
{
+ struct nouveau_devinit *devinit = nouveau_devinit(init->bios);
+
/* C51 (at least) sometimes has the lower bits set which the VBIOS
* interprets to mean that access needs to go through certain IO
* ports instead. The NVIDIA binary driver has been seen to access
@@ -147,6 +149,9 @@ init_nvreg(struct nvbios_init *init, u32 reg)
if (reg & ~0x00fffffc)
warn("unknown bits in register 0x%08x\n", reg);
+
+ if (devinit->mmio)
+ reg = devinit->mmio(devinit, reg);
return reg;
}
@@ -154,7 +159,7 @@ static u32
init_rd32(struct nvbios_init *init, u32 reg)
{
reg = init_nvreg(init, reg);
- if (init_exec(init))
+ if (reg != ~0 && init_exec(init))
return nv_rd32(init->subdev, reg);
return 0x00000000;
}
@@ -163,7 +168,7 @@ static void
init_wr32(struct nvbios_init *init, u32 reg, u32 val)
{
reg = init_nvreg(init, reg);
- if (init_exec(init))
+ if (reg != ~0 && init_exec(init))
nv_wr32(init->subdev, reg, val);
}
@@ -171,7 +176,7 @@ static u32
init_mask(struct nvbios_init *init, u32 reg, u32 mask, u32 val)
{
reg = init_nvreg(init, reg);
- if (init_exec(init)) {
+ if (reg != ~0 && init_exec(init)) {
u32 tmp = nv_rd32(init->subdev, reg);
nv_wr32(init->subdev, reg, (tmp & ~mask) | val);
return tmp;
@@ -410,7 +415,7 @@ init_ram_restrict(struct nvbios_init *init)
* in case *not* re-reading the strap causes similar breakage.
*/
if (!init->ramcfg || init->bios->version.major < 0x70)
- init->ramcfg = 0x80000000 | nvbios_ramcfg_index(init->bios);
+ init->ramcfg = 0x80000000 | nvbios_ramcfg_index(init->subdev);
return (init->ramcfg & 0x7fffffff);
}
@@ -845,9 +850,8 @@ init_idx_addr_latched(struct nvbios_init *init)
u32 data = nv_ro32(bios, init->offset + 13);
u8 count = nv_ro08(bios, init->offset + 17);
- trace("INDEX_ADDRESS_LATCHED\t"
- "R[0x%06x] : R[0x%06x]\n\tCTRL &= 0x%08x |= 0x%08x\n",
- creg, dreg, mask, data);
+ trace("INDEX_ADDRESS_LATCHED\tR[0x%06x] : R[0x%06x]\n", creg, dreg);
+ trace("\tCTRL &= 0x%08x |= 0x%08x\n", mask, data);
init->offset += 18;
while (count--) {
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c b/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c
index 991aedda999b..6c401f70ab99 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c
@@ -27,9 +27,9 @@
#include <subdev/bios/ramcfg.h>
static u8
-nvbios_ramcfg_strap(struct nouveau_bios *bios)
+nvbios_ramcfg_strap(struct nouveau_subdev *subdev)
{
- return (nv_rd32(bios, 0x101000) & 0x0000003c) >> 2;
+ return (nv_rd32(subdev, 0x101000) & 0x0000003c) >> 2;
}
u8
@@ -48,9 +48,10 @@ nvbios_ramcfg_count(struct nouveau_bios *bios)
}
u8
-nvbios_ramcfg_index(struct nouveau_bios *bios)
+nvbios_ramcfg_index(struct nouveau_subdev *subdev)
{
- u8 strap = nvbios_ramcfg_strap(bios);
+ struct nouveau_bios *bios = nouveau_bios(subdev);
+ u8 strap = nvbios_ramcfg_strap(subdev);
u32 xlat = 0x00000000;
struct bit_entry bit_M;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c
index 22ac6dbd6c8f..d15854094078 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c
@@ -164,6 +164,7 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios,
i = 0;
fan->nr_fan_trip = 0;
+ fan->fan_mode = NVBIOS_THERM_FAN_OTHER;
while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) {
s16 value = nv_ro16(bios, entry + 1);
@@ -174,6 +175,8 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios,
break;
case 0x24:
fan->nr_fan_trip++;
+ if (fan->fan_mode > NVBIOS_THERM_FAN_TRIP)
+ fan->fan_mode = NVBIOS_THERM_FAN_TRIP;
cur_trip = &fan->trip[fan->nr_fan_trip - 1];
cur_trip->hysteresis = value & 0xf;
cur_trip->temp = (value & 0xff0) >> 4;
@@ -194,11 +197,19 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios,
fan->slow_down_period = value;
break;
case 0x46:
+ if (fan->fan_mode > NVBIOS_THERM_FAN_LINEAR)
+ fan->fan_mode = NVBIOS_THERM_FAN_LINEAR;
fan->linear_min_temp = nv_ro08(bios, entry + 1);
fan->linear_max_temp = nv_ro08(bios, entry + 2);
break;
}
}
+ /* starting from fermi, fan management is always linear */
+ if (nv_device(bios)->card_type >= NV_C0 &&
+ fan->fan_mode == NVBIOS_THERM_FAN_OTHER) {
+ fan->fan_mode = NVBIOS_THERM_FAN_LINEAR;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
index 8fa34e8152c2..239acfe876c3 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
@@ -96,5 +96,6 @@ nouveau_devinit_create_(struct nouveau_object *parent,
devinit->post = nouveau_boolopt(device->cfgopt, "NvForcePost", false);
devinit->meminit = impl->meminit;
devinit->pll_set = impl->pll_set;
+ devinit->mmio = impl->mmio;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h
index 6b56a0f4cb40..4fe49cf4c99a 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h
@@ -24,6 +24,8 @@
*
*/
+#include <core/device.h>
+
#define NV04_PFB_BOOT_0 0x00100000
# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003
# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000
@@ -60,10 +62,10 @@
# define NV10_PFB_REFCTRL_VALID_1 (1 << 31)
static inline struct io_mapping *
-fbmem_init(struct pci_dev *pdev)
+fbmem_init(struct nouveau_device *dev)
{
- return io_mapping_create_wc(pci_resource_start(pdev, 1),
- pci_resource_len(pdev, 1));
+ return io_mapping_create_wc(nv_device_resource_start(dev, 1),
+ nv_device_resource_len(dev, 1));
}
static inline void
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/gm107.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/gm107.c
new file mode 100644
index 000000000000..c69bc7f54e37
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/gm107.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static u64
+gm107_devinit_disable(struct nouveau_devinit *devinit)
+{
+ struct nv50_devinit_priv *priv = (void *)devinit;
+ u32 r021c00 = nv_rd32(priv, 0x021c00);
+ u32 r021c04 = nv_rd32(priv, 0x021c04);
+ u64 disable = 0ULL;
+
+ if (r021c00 & 0x00000001)
+ disable |= (1ULL << NVDEV_ENGINE_COPY0);
+ if (r021c00 & 0x00000004)
+ disable |= (1ULL << NVDEV_ENGINE_COPY2);
+ if (r021c04 & 0x00000001)
+ disable |= (1ULL << NVDEV_ENGINE_DISP);
+
+ return disable;
+}
+
+struct nouveau_oclass *
+gm107_devinit_oclass = &(struct nouveau_devinit_impl) {
+ .base.handle = NV_SUBDEV(DEVINIT, 0x07),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = nv50_devinit_ctor,
+ .dtor = _nouveau_devinit_dtor,
+ .init = nv50_devinit_init,
+ .fini = _nouveau_devinit_fini,
+ },
+ .pll_set = nvc0_devinit_pll_set,
+ .disable = gm107_devinit_disable,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
index 7037eae46e44..052ad690b468 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
@@ -38,7 +38,7 @@ nv04_devinit_meminit(struct nouveau_devinit *devinit)
int i;
/* Map the framebuffer aperture */
- fb = fbmem_init(nv_device(priv)->pdev);
+ fb = fbmem_init(nv_device(priv));
if (!fb) {
nv_error(priv, "failed to map fb\n");
return;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c
index 98b7e6780dc7..4a19c10e5178 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c
@@ -53,7 +53,7 @@ nv05_devinit_meminit(struct nouveau_devinit *devinit)
int i, v;
/* Map the framebuffer aperture */
- fb = fbmem_init(nv_device(priv)->pdev);
+ fb = fbmem_init(nv_device(priv));
if (!fb) {
nv_error(priv, "failed to map fb\n");
return;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
index 32b3d2131a7f..3b8d657da279 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
@@ -46,7 +46,7 @@ nv10_devinit_meminit(struct nouveau_devinit *devinit)
mem_width_count = 2;
/* Map the framebuffer aperture */
- fb = fbmem_init(nv_device(priv)->pdev);
+ fb = fbmem_init(nv_device(priv));
if (!fb) {
nv_error(priv, "failed to map fb\n");
return;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c
index 4689ba303b0b..04bc9732644c 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c
@@ -37,7 +37,7 @@ nv20_devinit_meminit(struct nouveau_devinit *devinit)
struct io_mapping *fb;
/* Map the framebuffer aperture */
- fb = fbmem_init(nv_device(priv)->pdev);
+ fb = fbmem_init(nv_device(priv));
if (!fb) {
nv_error(priv, "failed to map fb\n");
return;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
index 141c27e9f182..51d5076333ec 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
@@ -5,6 +5,7 @@
struct nv50_devinit_priv {
struct nouveau_devinit base;
+ u32 r001540;
};
int nv50_devinit_ctor(struct nouveau_object *, struct nouveau_object *,
@@ -15,4 +16,6 @@ int nv50_devinit_pll_set(struct nouveau_devinit *, u32, u32);
int nva3_devinit_pll_set(struct nouveau_devinit *, u32, u32);
+int nvc0_devinit_pll_set(struct nouveau_devinit *, u32, u32);
+
#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
index 6dedf1dad7f7..006cf348bda7 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
@@ -81,6 +81,55 @@ nva3_devinit_disable(struct nouveau_devinit *devinit)
return disable;
}
+static u32
+nva3_devinit_mmio_part[] = {
+ 0x100720, 0x1008bc, 4,
+ 0x100a20, 0x100adc, 4,
+ 0x100d80, 0x100ddc, 4,
+ 0x110000, 0x110f9c, 4,
+ 0x111000, 0x11103c, 8,
+ 0x111080, 0x1110fc, 4,
+ 0x111120, 0x1111fc, 4,
+ 0x111300, 0x1114bc, 4,
+ 0,
+};
+
+static u32
+nva3_devinit_mmio(struct nouveau_devinit *devinit, u32 addr)
+{
+ struct nv50_devinit_priv *priv = (void *)devinit;
+ u32 *mmio = nva3_devinit_mmio_part;
+
+ /* the init tables on some boards have INIT_RAM_RESTRICT_ZM_REG_GROUP
+ * instructions which touch registers that may not even exist on
+ * some configurations (Quadro 400), which causes the register
+ * interface to screw up for some amount of time after attempting to
+ * write to one of these, and results in all sorts of things going
+ * horribly wrong.
+ *
+ * the binary driver avoids touching these registers at all, however,
+ * the video bios doesn't care and does what the scripts say. it's
+ * presumed that the io-port access to priv registers isn't effected
+ * by the screw-up bug mentioned above.
+ *
+ * really, a new opcode should've been invented to handle these
+ * requirements, but whatever, it's too late for that now.
+ */
+ while (mmio[0]) {
+ if (addr >= mmio[0] && addr <= mmio[1]) {
+ u32 part = (addr / mmio[2]) & 7;
+ if (!priv->r001540)
+ priv->r001540 = nv_rd32(priv, 0x001540);
+ if (part >= hweight8((priv->r001540 >> 16) & 0xff))
+ return ~0;
+ return addr;
+ }
+ mmio += 3;
+ }
+
+ return addr;
+}
+
struct nouveau_oclass *
nva3_devinit_oclass = &(struct nouveau_devinit_impl) {
.base.handle = NV_SUBDEV(DEVINIT, 0xa3),
@@ -92,4 +141,5 @@ nva3_devinit_oclass = &(struct nouveau_devinit_impl) {
},
.pll_set = nva3_devinit_pll_set,
.disable = nva3_devinit_disable,
+ .mmio = nva3_devinit_mmio,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
index fa7e63766b1b..30c765747eea 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
@@ -24,7 +24,7 @@
#include "nv50.h"
-static int
+int
nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
{
struct nv50_devinit_priv *priv = (void *)devinit;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
index 822a2fbf44a5..f0e8683ad840 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
@@ -11,6 +11,7 @@ struct nouveau_devinit_impl {
void (*meminit)(struct nouveau_devinit *);
int (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq);
u64 (*disable)(struct nouveau_devinit *);
+ u32 (*mmio)(struct nouveau_devinit *, u32);
};
#define nouveau_devinit_create(p,e,o,d) \
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/gm107.c b/drivers/gpu/drm/nouveau/core/subdev/fb/gm107.c
new file mode 100644
index 000000000000..c4840aedc2dc
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/gm107.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nvc0.h"
+
+struct nouveau_oclass *
+gm107_fb_oclass = &(struct nouveau_fb_impl) {
+ .base.handle = NV_SUBDEV(FB, 0x07),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = nvc0_fb_ctor,
+ .dtor = nvc0_fb_dtor,
+ .init = nvc0_fb_init,
+ .fini = _nouveau_fb_fini,
+ },
+ .memtype = nvc0_fb_memtype_valid,
+ .ram = &gm107_ram_oclass,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
index cbc7f00c1278..1fc55c1e91a1 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
@@ -250,10 +250,8 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (priv->r100c08_page) {
- priv->r100c08 = pci_map_page(device->pdev, priv->r100c08_page,
- 0, PAGE_SIZE,
- PCI_DMA_BIDIRECTIONAL);
- if (pci_dma_mapping_error(device->pdev, priv->r100c08))
+ priv->r100c08 = nv_device_map_page(device, priv->r100c08_page);
+ if (!priv->r100c08)
nv_warn(priv, "failed 0x100c08 page map\n");
} else {
nv_warn(priv, "failed 0x100c08 page alloc\n");
@@ -270,8 +268,7 @@ nv50_fb_dtor(struct nouveau_object *object)
struct nv50_fb_priv *priv = (void *)object;
if (priv->r100c08_page) {
- pci_unmap_page(device->pdev, priv->r100c08, PAGE_SIZE,
- PCI_DMA_BIDIRECTIONAL);
+ nv_device_unmap_page(device, priv->r100c08);
__free_page(priv->r100c08_page);
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
index 45470e1f0385..0670ae33ee45 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
@@ -70,8 +70,7 @@ nvc0_fb_dtor(struct nouveau_object *object)
struct nvc0_fb_priv *priv = (void *)object;
if (priv->r100c10_page) {
- pci_unmap_page(device->pdev, priv->r100c10, PAGE_SIZE,
- PCI_DMA_BIDIRECTIONAL);
+ nv_device_unmap_page(device, priv->r100c10);
__free_page(priv->r100c10_page);
}
@@ -94,10 +93,8 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (priv->r100c10_page) {
- priv->r100c10 = pci_map_page(device->pdev, priv->r100c10_page,
- 0, PAGE_SIZE,
- PCI_DMA_BIDIRECTIONAL);
- if (pci_dma_mapping_error(device->pdev, priv->r100c10))
+ priv->r100c10 = nv_device_map_page(device, priv->r100c10_page);
+ if (!priv->r100c10)
return -EFAULT;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.h b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.h
index 9e1931eb746f..705a06d755ad 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.h
@@ -18,12 +18,14 @@ int nvc0_fb_init(struct nouveau_object *);
bool nvc0_fb_memtype_valid(struct nouveau_fb *, u32);
-#define nvc0_ram_create(p,e,o,d) \
- nvc0_ram_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nvc0_ram_create(p,e,o,m,d) \
+ nvc0_ram_create_((p), (e), (o), (m), sizeof(**d), (void **)d)
int nvc0_ram_create_(struct nouveau_object *, struct nouveau_object *,
- struct nouveau_oclass *, int, void **);
+ struct nouveau_oclass *, u32, int, void **);
int nvc0_ram_get(struct nouveau_fb *, u64, u32, u32, u32,
struct nouveau_mem **);
void nvc0_ram_put(struct nouveau_fb *, struct nouveau_mem **);
+int nve0_ram_init(struct nouveau_object*);
+
#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
index edaf95dee612..da74c889aed4 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
@@ -32,6 +32,7 @@ extern struct nouveau_oclass nva3_ram_oclass;
extern struct nouveau_oclass nvaa_ram_oclass;
extern struct nouveau_oclass nvc0_ram_oclass;
extern struct nouveau_oclass nve0_ram_oclass;
+extern struct nouveau_oclass gm107_ram_oclass;
int nouveau_sddr3_calc(struct nouveau_ram *ram);
int nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramgm107.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramgm107.c
new file mode 100644
index 000000000000..4c6363595c79
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramgm107.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nvc0.h"
+
+struct gm107_ram {
+ struct nouveau_ram base;
+};
+
+static int
+gm107_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct gm107_ram *ram;
+ int ret;
+
+ ret = nvc0_ram_create(parent, engine, oclass, 0x021c14, &ram);
+ *pobject = nv_object(ram);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+struct nouveau_oclass
+gm107_ram_oclass = {
+ .handle = 0,
+ .ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = gm107_ram_ctor,
+ .dtor = _nouveau_ram_dtor,
+ .init = nve0_ram_init,
+ .fini = _nouveau_ram_fini,
+ }
+};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
index c7fdb3a9e88b..ef91b6e893af 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
@@ -91,7 +91,7 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq)
} while (perfE.memory < freq);
/* locate specific data set for the attached memory */
- strap = nvbios_ramcfg_index(bios);
+ strap = nvbios_ramcfg_index(nv_subdev(pfb));
if (strap >= cnt) {
nv_error(pfb, "invalid ramcfg strap\n");
return -EINVAL;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
index f4ae8aa46a25..6eb97f16fbda 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
@@ -98,7 +98,7 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
}
/* locate specific data set for the attached memory */
- strap = nvbios_ramcfg_index(bios);
+ strap = nvbios_ramcfg_index(nv_subdev(pfb));
if (strap >= cnt) {
nv_error(pfb, "invalid ramcfg strap\n");
return -EINVAL;
@@ -335,21 +335,23 @@ nva3_ram_init(struct nouveau_object *object)
/* prepare for ddr link training, and load training patterns */
switch (ram->base.type) {
case NV_MEM_TYPE_DDR3: {
- static const u32 pattern[16] = {
- 0xaaaaaaaa, 0xcccccccc, 0xdddddddd, 0xeeeeeeee,
- 0x00000000, 0x11111111, 0x44444444, 0xdddddddd,
- 0x33333333, 0x55555555, 0x77777777, 0x66666666,
- 0x99999999, 0x88888888, 0xeeeeeeee, 0xbbbbbbbb,
- };
-
- nv_wr32(pfb, 0x100538, 0x10001ff6); /*XXX*/
- nv_wr32(pfb, 0x1005a8, 0x0000ffff);
- nv_mask(pfb, 0x10f800, 0x00000001, 0x00000001);
- for (i = 0; i < 0x30; i++) {
- nv_wr32(pfb, 0x10f8c0, (i << 8) | i);
- nv_wr32(pfb, 0x10f8e0, (i << 8) | i);
- nv_wr32(pfb, 0x10f900, pattern[i % 16]);
- nv_wr32(pfb, 0x10f920, pattern[i % 16]);
+ if (nv_device(pfb)->chipset == 0xa8) {
+ static const u32 pattern[16] = {
+ 0xaaaaaaaa, 0xcccccccc, 0xdddddddd, 0xeeeeeeee,
+ 0x00000000, 0x11111111, 0x44444444, 0xdddddddd,
+ 0x33333333, 0x55555555, 0x77777777, 0x66666666,
+ 0x99999999, 0x88888888, 0xeeeeeeee, 0xbbbbbbbb,
+ };
+
+ nv_wr32(pfb, 0x100538, 0x10001ff6); /*XXX*/
+ nv_wr32(pfb, 0x1005a8, 0x0000ffff);
+ nv_mask(pfb, 0x10f800, 0x00000001, 0x00000001);
+ for (i = 0; i < 0x30; i++) {
+ nv_wr32(pfb, 0x10f8c0, (i << 8) | i);
+ nv_wr32(pfb, 0x10f8e0, (i << 8) | i);
+ nv_wr32(pfb, 0x10f900, pattern[i % 16]);
+ nv_wr32(pfb, 0x10f920, pattern[i % 16]);
+ }
}
}
break;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
index 0391b824ee76..8edc92224c84 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
@@ -152,7 +152,7 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq)
}
/* locate specific data set for the attached memory */
- strap = nvbios_ramcfg_index(bios);
+ strap = nvbios_ramcfg_index(nv_subdev(pfb));
if (strap >= cnt) {
nv_error(pfb, "invalid ramcfg strap\n");
return -EINVAL;
@@ -505,7 +505,8 @@ nvc0_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
int
nvc0_ram_create_(struct nouveau_object *parent, struct nouveau_object *engine,
- struct nouveau_oclass *oclass, int size, void **pobject)
+ struct nouveau_oclass *oclass, u32 maskaddr, int size,
+ void **pobject)
{
struct nouveau_fb *pfb = nouveau_fb(parent);
struct nouveau_bios *bios = nouveau_bios(pfb);
@@ -513,7 +514,7 @@ nvc0_ram_create_(struct nouveau_object *parent, struct nouveau_object *engine,
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
u32 parts = nv_rd32(pfb, 0x022438);
- u32 pmask = nv_rd32(pfb, 0x022554);
+ u32 pmask = nv_rd32(pfb, maskaddr);
u32 bsize = nv_rd32(pfb, 0x10f20c);
u32 offset, length;
bool uniform = true;
@@ -630,7 +631,7 @@ nvc0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nvc0_ram *ram;
int ret;
- ret = nvc0_ram_create(parent, engine, oclass, &ram);
+ ret = nvc0_ram_create(parent, engine, oclass, 0x022554, &ram);
*pobject = nv_object(ram);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
index 3257c522a021..16752192cf87 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
@@ -950,10 +950,11 @@ nve0_ram_calc_data(struct nouveau_fb *pfb, u32 freq,
}
/* locate specific data set for the attached memory */
+ strap = nvbios_ramcfg_index(nv_subdev(pfb));
ram->base.ramcfg.data = nvbios_rammapSp(bios, ram->base.rammap.data,
ram->base.rammap.version,
- ram->base.rammap.size, cnt, len,
- nvbios_ramcfg_index(bios),
+ ram->base.rammap.size,
+ cnt, len, strap,
&ram->base.ramcfg.version,
&ram->base.ramcfg.size,
&data->bios);
@@ -1123,7 +1124,7 @@ nve0_ram_tidy(struct nouveau_fb *pfb)
ram_exec(fuc, false);
}
-static int
+int
nve0_ram_init(struct nouveau_object *object)
{
struct nouveau_fb *pfb = (void *)object->parent;
@@ -1226,7 +1227,7 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
int ret, i;
u32 tmp;
- ret = nvc0_ram_create(parent, engine, oclass, &ram);
+ ret = nvc0_ram_create(parent, engine, oclass, 0x022554, &ram);
*pobject = nv_object(ram);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
index c4c1d415e7fe..2ef774731629 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
@@ -46,7 +46,8 @@ nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match)
u8 unk0 = !!(data & 0x02000000);
u8 unk1 = !!(data & 0x04000000);
u32 val = (unk1 << 16) | unk0;
- u32 reg = regs[line >> 4]; line &= 0x0f;
+ u32 reg = regs[line >> 4];
+ u32 lsh = line & 0x0f;
if ( func == DCB_GPIO_UNUSED ||
(match != DCB_GPIO_UNUSED && match != func))
@@ -54,7 +55,7 @@ nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match)
gpio->set(gpio, 0, func, line, defs);
- nv_mask(priv, reg, 0x00010001 << line, val << line);
+ nv_mask(priv, reg, 0x00010001 << lsh, val << lsh);
}
}
@@ -79,7 +80,7 @@ nv50_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out)
if (nv50_gpio_location(line, &reg, &shift))
return -EINVAL;
- nv_mask(gpio, reg, 7 << shift, (((dir ^ 1) << 1) | out) << shift);
+ nv_mask(gpio, reg, 3 << shift, (((dir ^ 1) << 1) | out) << shift);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
index c33c03d2f4af..378e05b88e6f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
@@ -111,7 +111,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,
snprintf(port->adapter.name, sizeof(port->adapter.name),
"nouveau-%s-%d", device->name, index);
port->adapter.owner = THIS_MODULE;
- port->adapter.dev.parent = &device->pdev->dev;
+ port->adapter.dev.parent = nv_device_base(device);
port->index = index;
port->func = func;
i2c_set_adapdata(&port->adapter, i2c);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
index ec0b9661d614..8803809f9fc5 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
@@ -50,7 +50,6 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_object **pobject)
{
struct nouveau_device *device = nv_device(parent);
- struct pci_dev *pdev = device->pdev;
struct nv04_instmem_priv *priv;
int ret, bar, vs;
@@ -60,13 +59,13 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
return ret;
/* map bar */
- if (pci_resource_len(pdev, 2))
+ if (nv_device_resource_len(device, 2))
bar = 2;
else
bar = 3;
- priv->iomem = ioremap(pci_resource_start(pdev, bar),
- pci_resource_len(pdev, bar));
+ priv->iomem = ioremap(nv_device_resource_start(device, bar),
+ nv_device_resource_len(device, bar));
if (!priv->iomem) {
nv_error(priv, "unable to map PRAMIN BAR\n");
return -EFAULT;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c
index cce65cc56514..f2f3338a967a 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c
@@ -22,44 +22,35 @@
* Authors: Ben Skeggs
*/
-#include <subdev/ltcg.h>
#include <subdev/fb.h>
#include <subdev/timer.h>
-struct nvc0_ltcg_priv {
- struct nouveau_ltcg base;
- u32 part_nr;
- u32 subp_nr;
- u32 num_tags;
- u32 tag_base;
- struct nouveau_mm tags;
- struct nouveau_mm_node *tag_ram;
-};
+#include "gf100.h"
static void
-nvc0_ltcg_subp_isr(struct nvc0_ltcg_priv *priv, int unit, int subp)
+gf100_ltcg_lts_isr(struct gf100_ltcg_priv *priv, int ltc, int lts)
{
- u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400);
- u32 stat = nv_rd32(priv, subp_base + 0x020);
+ u32 base = 0x141000 + (ltc * 0x2000) + (lts * 0x400);
+ u32 stat = nv_rd32(priv, base + 0x020);
if (stat) {
- nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", unit, subp, stat);
- nv_wr32(priv, subp_base + 0x020, stat);
+ nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", ltc, lts, stat);
+ nv_wr32(priv, base + 0x020, stat);
}
}
static void
-nvc0_ltcg_intr(struct nouveau_subdev *subdev)
+gf100_ltcg_intr(struct nouveau_subdev *subdev)
{
- struct nvc0_ltcg_priv *priv = (void *)subdev;
- u32 units;
-
- units = nv_rd32(priv, 0x00017c);
- while (units) {
- u32 subp, unit = ffs(units) - 1;
- for (subp = 0; subp < priv->subp_nr; subp++)
- nvc0_ltcg_subp_isr(priv, unit, subp);
- units &= ~(1 << unit);
+ struct gf100_ltcg_priv *priv = (void *)subdev;
+ u32 mask;
+
+ mask = nv_rd32(priv, 0x00017c);
+ while (mask) {
+ u32 lts, ltc = __ffs(mask);
+ for (lts = 0; lts < priv->lts_nr; lts++)
+ gf100_ltcg_lts_isr(priv, ltc, lts);
+ mask &= ~(1 << ltc);
}
/* we do something horribly wrong and upset PMFB a lot, so mask off
@@ -68,11 +59,11 @@ nvc0_ltcg_intr(struct nouveau_subdev *subdev)
nv_mask(priv, 0x000640, 0x02000000, 0x00000000);
}
-static int
-nvc0_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n,
+int
+gf100_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n,
struct nouveau_mm_node **pnode)
{
- struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
+ struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
int ret;
ret = nouveau_mm_head(&priv->tags, 1, n, n, 1, pnode);
@@ -82,18 +73,18 @@ nvc0_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n,
return ret;
}
-static void
-nvc0_ltcg_tags_free(struct nouveau_ltcg *ltcg, struct nouveau_mm_node **pnode)
+void
+gf100_ltcg_tags_free(struct nouveau_ltcg *ltcg, struct nouveau_mm_node **pnode)
{
- struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
+ struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
nouveau_mm_free(&priv->tags, pnode);
}
static void
-nvc0_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
+gf100_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
{
- struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
+ struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
u32 last = first + count - 1;
int p, i;
@@ -104,16 +95,16 @@ nvc0_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
nv_wr32(priv, 0x17e8c8, 0x4); /* trigger clear */
/* wait until it's finished with clearing */
- for (p = 0; p < priv->part_nr; ++p) {
- for (i = 0; i < priv->subp_nr; ++i)
+ for (p = 0; p < priv->ltc_nr; ++p) {
+ for (i = 0; i < priv->lts_nr; ++i)
nv_wait(priv, 0x1410c8 + p * 0x2000 + i * 0x400, ~0, 0);
}
}
/* TODO: Figure out tag memory details and drop the over-cautious allocation.
*/
-static int
-nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
+int
+gf100_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct gf100_ltcg_priv *priv)
{
u32 tag_size, tag_margin, tag_align;
int ret;
@@ -124,7 +115,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
priv->num_tags = 1 << 17; /* we have 17 bits in PTE */
priv->num_tags = (priv->num_tags + 63) & ~63; /* round up to 64 */
- tag_align = priv->part_nr * 0x800;
+ tag_align = priv->ltc_nr * 0x800;
tag_margin = (tag_align < 0x6000) ? 0x6000 : tag_align;
/* 4 part 4 sub: 0x2000 bytes for 56 tags */
@@ -157,11 +148,11 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
}
static int
-nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+gf100_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
- struct nvc0_ltcg_priv *priv;
+ struct gf100_ltcg_priv *priv;
struct nouveau_fb *pfb = nouveau_fb(parent);
u32 parts, mask;
int ret, i;
@@ -175,27 +166,27 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
mask = nv_rd32(priv, 0x022554);
for (i = 0; i < parts; i++) {
if (!(mask & (1 << i)))
- priv->part_nr++;
+ priv->ltc_nr++;
}
- priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28;
+ priv->lts_nr = nv_rd32(priv, 0x17e8dc) >> 28;
- ret = nvc0_ltcg_init_tag_ram(pfb, priv);
+ ret = gf100_ltcg_init_tag_ram(pfb, priv);
if (ret)
return ret;
- priv->base.tags_alloc = nvc0_ltcg_tags_alloc;
- priv->base.tags_free = nvc0_ltcg_tags_free;
- priv->base.tags_clear = nvc0_ltcg_tags_clear;
+ priv->base.tags_alloc = gf100_ltcg_tags_alloc;
+ priv->base.tags_free = gf100_ltcg_tags_free;
+ priv->base.tags_clear = gf100_ltcg_tags_clear;
- nv_subdev(priv)->intr = nvc0_ltcg_intr;
+ nv_subdev(priv)->intr = gf100_ltcg_intr;
return 0;
}
-static void
-nvc0_ltcg_dtor(struct nouveau_object *object)
+void
+gf100_ltcg_dtor(struct nouveau_object *object)
{
struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
- struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
+ struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
struct nouveau_fb *pfb = nouveau_fb(ltcg->base.base.parent);
nouveau_mm_fini(&priv->tags);
@@ -205,10 +196,10 @@ nvc0_ltcg_dtor(struct nouveau_object *object)
}
static int
-nvc0_ltcg_init(struct nouveau_object *object)
+gf100_ltcg_init(struct nouveau_object *object)
{
struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
- struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
+ struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
int ret;
ret = nouveau_ltcg_init(ltcg);
@@ -216,20 +207,20 @@ nvc0_ltcg_init(struct nouveau_object *object)
return ret;
nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
- nv_wr32(priv, 0x17e8d8, priv->part_nr);
+ nv_wr32(priv, 0x17e8d8, priv->ltc_nr);
if (nv_device(ltcg)->card_type >= NV_E0)
- nv_wr32(priv, 0x17e000, priv->part_nr);
+ nv_wr32(priv, 0x17e000, priv->ltc_nr);
nv_wr32(priv, 0x17e8d4, priv->tag_base);
return 0;
}
-struct nouveau_oclass
-nvc0_ltcg_oclass = {
+struct nouveau_oclass *
+gf100_ltcg_oclass = &(struct nouveau_oclass) {
.handle = NV_SUBDEV(LTCG, 0xc0),
.ofuncs = &(struct nouveau_ofuncs) {
- .ctor = nvc0_ltcg_ctor,
- .dtor = nvc0_ltcg_dtor,
- .init = nvc0_ltcg_init,
+ .ctor = gf100_ltcg_ctor,
+ .dtor = gf100_ltcg_dtor,
+ .init = gf100_ltcg_init,
.fini = _nouveau_ltcg_fini,
},
};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h
new file mode 100644
index 000000000000..87b10b8412ea
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h
@@ -0,0 +1,21 @@
+#ifndef __NVKM_LTCG_PRIV_GF100_H__
+#define __NVKM_LTCG_PRIV_GF100_H__
+
+#include <subdev/ltcg.h>
+
+struct gf100_ltcg_priv {
+ struct nouveau_ltcg base;
+ u32 ltc_nr;
+ u32 lts_nr;
+ u32 num_tags;
+ u32 tag_base;
+ struct nouveau_mm tags;
+ struct nouveau_mm_node *tag_ram;
+};
+
+void gf100_ltcg_dtor(struct nouveau_object *);
+int gf100_ltcg_init_tag_ram(struct nouveau_fb *, struct gf100_ltcg_priv *);
+int gf100_ltcg_tags_alloc(struct nouveau_ltcg *, u32, struct nouveau_mm_node **);
+void gf100_ltcg_tags_free(struct nouveau_ltcg *, struct nouveau_mm_node **);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c
new file mode 100644
index 000000000000..e79d0e81de40
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/fb.h>
+#include <subdev/timer.h>
+
+#include "gf100.h"
+
+static void
+gm107_ltcg_lts_isr(struct gf100_ltcg_priv *priv, int ltc, int lts)
+{
+ u32 base = 0x140000 + (ltc * 0x2000) + (lts * 0x400);
+ u32 stat = nv_rd32(priv, base + 0x00c);
+
+ if (stat) {
+ nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", ltc, lts, stat);
+ nv_wr32(priv, base + 0x00c, stat);
+ }
+}
+
+static void
+gm107_ltcg_intr(struct nouveau_subdev *subdev)
+{
+ struct gf100_ltcg_priv *priv = (void *)subdev;
+ u32 mask;
+
+ mask = nv_rd32(priv, 0x00017c);
+ while (mask) {
+ u32 lts, ltc = __ffs(mask);
+ for (lts = 0; lts < priv->lts_nr; lts++)
+ gm107_ltcg_lts_isr(priv, ltc, lts);
+ mask &= ~(1 << ltc);
+ }
+
+ /* we do something horribly wrong and upset PMFB a lot, so mask off
+ * interrupts from it after the first one until it's fixed
+ */
+ nv_mask(priv, 0x000640, 0x02000000, 0x00000000);
+}
+
+static void
+gm107_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
+{
+ struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
+ u32 last = first + count - 1;
+ int p, i;
+
+ BUG_ON((first > last) || (last >= priv->num_tags));
+
+ nv_wr32(priv, 0x17e270, first);
+ nv_wr32(priv, 0x17e274, last);
+ nv_wr32(priv, 0x17e26c, 0x4); /* trigger clear */
+
+ /* wait until it's finished with clearing */
+ for (p = 0; p < priv->ltc_nr; ++p) {
+ for (i = 0; i < priv->lts_nr; ++i)
+ nv_wait(priv, 0x14046c + p * 0x2000 + i * 0x200, ~0, 0);
+ }
+}
+
+static int
+gm107_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct gf100_ltcg_priv *priv;
+ struct nouveau_fb *pfb = nouveau_fb(parent);
+ u32 parts, mask;
+ int ret, i;
+
+ ret = nouveau_ltcg_create(parent, engine, oclass, &priv);
+ *pobject = nv_object(priv);
+ if (ret)
+ return ret;
+
+ parts = nv_rd32(priv, 0x022438);
+ mask = nv_rd32(priv, 0x021c14);
+ for (i = 0; i < parts; i++) {
+ if (!(mask & (1 << i)))
+ priv->ltc_nr++;
+ }
+ priv->lts_nr = nv_rd32(priv, 0x17e280) >> 28;
+
+ ret = gf100_ltcg_init_tag_ram(pfb, priv);
+ if (ret)
+ return ret;
+
+ priv->base.tags_alloc = gf100_ltcg_tags_alloc;
+ priv->base.tags_free = gf100_ltcg_tags_free;
+ priv->base.tags_clear = gm107_ltcg_tags_clear;
+
+ nv_subdev(priv)->intr = gm107_ltcg_intr;
+ return 0;
+}
+
+static int
+gm107_ltcg_init(struct nouveau_object *object)
+{
+ struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
+ struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
+ int ret;
+
+ ret = nouveau_ltcg_init(ltcg);
+ if (ret)
+ return ret;
+
+ nv_wr32(priv, 0x17e27c, priv->ltc_nr);
+ nv_wr32(priv, 0x17e278, priv->tag_base);
+ return 0;
+}
+
+struct nouveau_oclass *
+gm107_ltcg_oclass = &(struct nouveau_oclass) {
+ .handle = NV_SUBDEV(LTCG, 0xff),
+ .ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = gm107_ltcg_ctor,
+ .dtor = gf100_ltcg_dtor,
+ .init = gm107_ltcg_init,
+ .fini = _nouveau_ltcg_fini,
+ },
+};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
index b4b9943773bc..8a5555192fa5 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
@@ -93,7 +93,7 @@ _nouveau_mc_dtor(struct nouveau_object *object)
{
struct nouveau_device *device = nv_device(object);
struct nouveau_mc *pmc = (void *)object;
- free_irq(device->pdev->irq, pmc);
+ free_irq(pmc->irq, pmc);
if (pmc->use_msi)
pci_disable_msi(device->pdev);
nouveau_subdev_destroy(&pmc->base);
@@ -114,33 +114,44 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret)
return ret;
- switch (device->pdev->device & 0x0ff0) {
- case 0x00f0:
- case 0x02e0:
- /* BR02? NFI how these would be handled yet exactly */
- break;
- default:
- switch (device->chipset) {
- case 0xaa: break; /* reported broken, nv also disable it */
- default:
- pmc->use_msi = true;
+ if (nv_device_is_pci(device))
+ switch (device->pdev->device & 0x0ff0) {
+ case 0x00f0:
+ case 0x02e0:
+ /* BR02? NFI how these would be handled yet exactly */
break;
+ default:
+ switch (device->chipset) {
+ case 0xaa:
+ /* reported broken, nv also disable it */
+ break;
+ default:
+ pmc->use_msi = true;
+ break;
}
- }
- pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI", pmc->use_msi);
- if (pmc->use_msi && oclass->msi_rearm) {
- pmc->use_msi = pci_enable_msi(device->pdev) == 0;
- if (pmc->use_msi) {
- nv_info(pmc, "MSI interrupts enabled\n");
- oclass->msi_rearm(pmc);
+ pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI",
+ pmc->use_msi);
+
+ if (pmc->use_msi && oclass->msi_rearm) {
+ pmc->use_msi = pci_enable_msi(device->pdev) == 0;
+ if (pmc->use_msi) {
+ nv_info(pmc, "MSI interrupts enabled\n");
+ oclass->msi_rearm(pmc);
+ }
+ } else {
+ pmc->use_msi = false;
}
- } else {
- pmc->use_msi = false;
}
- ret = request_irq(device->pdev->irq, nouveau_mc_intr,
- IRQF_SHARED, "nouveau", pmc);
+ ret = nv_device_get_irq(device, true);
+ if (ret < 0)
+ return ret;
+ pmc->irq = ret;
+
+ ret = request_irq(pmc->irq, nouveau_mc_intr, IRQF_SHARED, "nouveau",
+ pmc);
+
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c
index 13c5af88a601..51fcf7960417 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c
@@ -96,7 +96,7 @@ mxm_shadow_dsm(struct nouveau_mxm *mxm, u8 version)
acpi_handle handle;
int rev;
- handle = ACPI_HANDLE(&device->pdev->dev);
+ handle = ACPI_HANDLE(nv_device_base(device));
if (!handle)
return false;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
index 80e584a1bd1c..9ad01da6eacb 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
@@ -110,16 +110,18 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode)
poll = false;
break;
case NOUVEAU_THERM_CTRL_AUTO:
- if (priv->fan->bios.nr_fan_trip) {
+ switch(priv->fan->bios.fan_mode) {
+ case NVBIOS_THERM_FAN_TRIP:
duty = nouveau_therm_update_trip(therm);
- } else
- if (priv->fan->bios.linear_min_temp ||
- priv->fan->bios.linear_max_temp) {
+ break;
+ case NVBIOS_THERM_FAN_LINEAR:
duty = nouveau_therm_update_linear(therm);
- } else {
+ break;
+ case NVBIOS_THERM_FAN_OTHER:
if (priv->cstate)
duty = priv->cstate;
poll = false;
+ break;
}
immd = false;
break;
@@ -179,7 +181,7 @@ nouveau_therm_fan_mode(struct nouveau_therm *therm, int mode)
/* do not allow automatic fan management if the thermal sensor is
* not available */
- if (priv->mode == NOUVEAU_THERM_CTRL_AUTO && therm->temp_get(therm) < 0)
+ if (mode == NOUVEAU_THERM_CTRL_AUTO && therm->temp_get(therm) < 0)
return -EINVAL;
if (priv->mode == mode)
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
index 95f6129eeede..016990a8252c 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
@@ -54,8 +54,10 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
/* check that we're not already at the target duty cycle */
duty = fan->get(therm);
- if (duty == target)
- goto done;
+ if (duty == target) {
+ spin_unlock_irqrestore(&fan->lock, flags);
+ return 0;
+ }
/* smooth out the fanspeed increase/decrease */
if (!immediate && duty >= 0) {
@@ -73,8 +75,15 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
nv_debug(therm, "FAN update: %d\n", duty);
ret = fan->set(therm, duty);
- if (ret)
- goto done;
+ if (ret) {
+ spin_unlock_irqrestore(&fan->lock, flags);
+ return ret;
+ }
+
+ /* fan speed updated, drop the fan lock before grabbing the
+ * alarm-scheduling lock and risking a deadlock
+ */
+ spin_unlock_irqrestore(&fan->lock, flags);
/* schedule next fan update, if not at target speed already */
if (list_empty(&fan->alarm.head) && target != duty) {
@@ -92,8 +101,6 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
ptimer->alarm(ptimer, delay * 1000 * 1000, &fan->alarm);
}
-done:
- spin_unlock_irqrestore(&fan->lock, flags);
return ret;
}
@@ -185,11 +192,8 @@ nouveau_therm_fan_set_defaults(struct nouveau_therm *therm)
priv->fan->bios.max_duty = 100;
priv->fan->bios.bump_period = 500;
priv->fan->bios.slow_down_period = 2000;
-/*XXX: talk to mupuf */
-#if 0
priv->fan->bios.linear_min_temp = 40;
priv->fan->bios.linear_max_temp = 85;
-#endif
}
static void
@@ -235,7 +239,8 @@ nouveau_therm_fan_ctor(struct nouveau_therm *therm)
/* attempt to locate a drivable fan, and determine control method */
ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func);
if (ret == 0) {
- if (func.log[0] & DCB_GPIO_LOG_DIR_IN) {
+ /* FIXME: is this really the place to perform such checks ? */
+ if (func.line != 16 && func.log[0] & DCB_GPIO_LOG_DIR_IN) {
nv_debug(therm, "GPIO_FAN is in input mode\n");
ret = -EINVAL;
} else {
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c
index 5f71db8e8992..9a5c07340263 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c
@@ -67,7 +67,7 @@ nouveau_fanpwm_set(struct nouveau_therm *therm, int percent)
if (priv->base.bios.pwm_freq) {
divs = 1;
if (therm->pwm_clock)
- divs = therm->pwm_clock(therm);
+ divs = therm->pwm_clock(therm, priv->func.line);
divs /= priv->base.bios.pwm_freq;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
index 8cf7597a2182..321db927d638 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
@@ -93,7 +93,7 @@ nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
}
int
-nv50_fan_pwm_clock(struct nouveau_therm *therm)
+nv50_fan_pwm_clock(struct nouveau_therm *therm, int line)
{
int chipset = nv_device(therm)->chipset;
int crystal = nv_device(therm)->crystal;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
index 4dd4f81ae873..43fec17ea540 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
@@ -32,10 +32,12 @@ static int
pwm_info(struct nouveau_therm *therm, int line)
{
u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04));
+
switch (gpio & 0x000000c0) {
case 0x00000000: /* normal mode, possibly pwm forced off by us */
case 0x00000040: /* nvio special */
switch (gpio & 0x0000001f) {
+ case 0x00: return 2;
case 0x19: return 1;
case 0x1c: return 0;
default:
@@ -56,8 +58,9 @@ nvd0_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
int indx = pwm_info(therm, line);
if (indx < 0)
return indx;
-
- nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data);
+ else if (indx < 2)
+ nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data);
+ /* nothing to do for indx == 2, it seems hardwired to PTHERM */
return 0;
}
@@ -67,10 +70,15 @@ nvd0_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
int indx = pwm_info(therm, line);
if (indx < 0)
return indx;
-
- if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) {
- *divs = nv_rd32(therm, 0x00e114 + (indx * 8));
- *duty = nv_rd32(therm, 0x00e118 + (indx * 8));
+ else if (indx < 2) {
+ if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) {
+ *divs = nv_rd32(therm, 0x00e114 + (indx * 8));
+ *duty = nv_rd32(therm, 0x00e118 + (indx * 8));
+ return 0;
+ }
+ } else if (indx == 2) {
+ *divs = nv_rd32(therm, 0x0200d8) & 0x1fff;
+ *duty = nv_rd32(therm, 0x0200dc) & 0x1fff;
return 0;
}
@@ -83,16 +91,26 @@ nvd0_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
int indx = pwm_info(therm, line);
if (indx < 0)
return indx;
-
- nv_wr32(therm, 0x00e114 + (indx * 8), divs);
- nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000);
+ else if (indx < 2) {
+ nv_wr32(therm, 0x00e114 + (indx * 8), divs);
+ nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000);
+ } else if (indx == 2) {
+ nv_mask(therm, 0x0200d8, 0x1fff, divs); /* keep the high bits */
+ nv_wr32(therm, 0x0200dc, duty | 0x40000000);
+ }
return 0;
}
static int
-nvd0_fan_pwm_clock(struct nouveau_therm *therm)
+nvd0_fan_pwm_clock(struct nouveau_therm *therm, int line)
{
- return (nv_device(therm)->crystal * 1000) / 20;
+ int indx = pwm_info(therm, line);
+ if (indx < 0)
+ return 0;
+ else if (indx < 2)
+ return (nv_device(therm)->crystal * 1000) / 20;
+ else
+ return nv_device(therm)->crystal * 1000 / 10;
}
static int
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
index 96f8f95693ce..916fca5c7816 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
@@ -143,7 +143,7 @@ void nv40_therm_intr(struct nouveau_subdev *);
int nv50_fan_pwm_ctrl(struct nouveau_therm *, int, bool);
int nv50_fan_pwm_get(struct nouveau_therm *, int, u32 *, u32 *);
int nv50_fan_pwm_set(struct nouveau_therm *, int, u32, u32);
-int nv50_fan_pwm_clock(struct nouveau_therm *);
+int nv50_fan_pwm_clock(struct nouveau_therm *, int);
int nv84_temp_get(struct nouveau_therm *therm);
int nv84_therm_fini(struct nouveau_object *object, bool suspend);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c b/drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c
new file mode 100644
index 000000000000..37484db1f7fc
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv04.h"
+
+static int
+gk20a_timer_init(struct nouveau_object *object)
+{
+ struct nv04_timer_priv *priv = (void *)object;
+ u32 hi = upper_32_bits(priv->suspend_time);
+ u32 lo = lower_32_bits(priv->suspend_time);
+ int ret;
+
+ ret = nouveau_timer_init(&priv->base);
+ if (ret)
+ return ret;
+
+ nv_debug(priv, "time low : 0x%08x\n", lo);
+ nv_debug(priv, "time high : 0x%08x\n", hi);
+
+ /* restore the time before suspend */
+ nv_wr32(priv, NV04_PTIMER_TIME_1, hi);
+ nv_wr32(priv, NV04_PTIMER_TIME_0, lo);
+ return 0;
+}
+
+struct nouveau_oclass
+gk20a_timer_oclass = {
+ .handle = NV_SUBDEV(TIMER, 0xff),
+ .ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = nv04_timer_ctor,
+ .dtor = nv04_timer_dtor,
+ .init = gk20a_timer_init,
+ .fini = nv04_timer_fini,
+ }
+};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
index c0bdd10358d7..240ed0b983a9 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
@@ -22,22 +22,7 @@
* Authors: Ben Skeggs
*/
-#include <subdev/timer.h>
-
-#define NV04_PTIMER_INTR_0 0x009100
-#define NV04_PTIMER_INTR_EN_0 0x009140
-#define NV04_PTIMER_NUMERATOR 0x009200
-#define NV04_PTIMER_DENOMINATOR 0x009210
-#define NV04_PTIMER_TIME_0 0x009400
-#define NV04_PTIMER_TIME_1 0x009410
-#define NV04_PTIMER_ALARM_0 0x009420
-
-struct nv04_timer_priv {
- struct nouveau_timer base;
- struct list_head alarms;
- spinlock_t lock;
- u64 suspend_time;
-};
+#include "nv04.h"
static u64
nv04_timer_read(struct nouveau_timer *ptimer)
@@ -142,35 +127,14 @@ nv04_timer_intr(struct nouveau_subdev *subdev)
}
}
-static int
-nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nv04_timer_priv *priv;
- int ret;
-
- ret = nouveau_timer_create(parent, engine, oclass, &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
-
- priv->base.base.intr = nv04_timer_intr;
- priv->base.read = nv04_timer_read;
- priv->base.alarm = nv04_timer_alarm;
- priv->base.alarm_cancel = nv04_timer_alarm_cancel;
- priv->suspend_time = 0;
-
- INIT_LIST_HEAD(&priv->alarms);
- spin_lock_init(&priv->lock);
- return 0;
-}
-
-static void
-nv04_timer_dtor(struct nouveau_object *object)
+int
+nv04_timer_fini(struct nouveau_object *object, bool suspend)
{
struct nv04_timer_priv *priv = (void *)object;
- return nouveau_timer_destroy(&priv->base);
+ if (suspend)
+ priv->suspend_time = nv04_timer_read(&priv->base);
+ nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000);
+ return nouveau_timer_fini(&priv->base, suspend);
}
static int
@@ -257,14 +221,35 @@ nv04_timer_init(struct nouveau_object *object)
return 0;
}
-static int
-nv04_timer_fini(struct nouveau_object *object, bool suspend)
+void
+nv04_timer_dtor(struct nouveau_object *object)
{
struct nv04_timer_priv *priv = (void *)object;
- if (suspend)
- priv->suspend_time = nv04_timer_read(&priv->base);
- nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000);
- return nouveau_timer_fini(&priv->base, suspend);
+ return nouveau_timer_destroy(&priv->base);
+}
+
+int
+nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nv04_timer_priv *priv;
+ int ret;
+
+ ret = nouveau_timer_create(parent, engine, oclass, &priv);
+ *pobject = nv_object(priv);
+ if (ret)
+ return ret;
+
+ priv->base.base.intr = nv04_timer_intr;
+ priv->base.read = nv04_timer_read;
+ priv->base.alarm = nv04_timer_alarm;
+ priv->base.alarm_cancel = nv04_timer_alarm_cancel;
+ priv->suspend_time = 0;
+
+ INIT_LIST_HEAD(&priv->alarms);
+ spin_lock_init(&priv->lock);
+ return 0;
}
struct nouveau_oclass
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h
new file mode 100644
index 000000000000..4bc152697c37
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h
@@ -0,0 +1,27 @@
+#ifndef __NVKM_TIMER_NV04_H__
+#define __NVKM_TIMER_NV04_H__
+
+#include "priv.h"
+
+#define NV04_PTIMER_INTR_0 0x009100
+#define NV04_PTIMER_INTR_EN_0 0x009140
+#define NV04_PTIMER_NUMERATOR 0x009200
+#define NV04_PTIMER_DENOMINATOR 0x009210
+#define NV04_PTIMER_TIME_0 0x009400
+#define NV04_PTIMER_TIME_1 0x009410
+#define NV04_PTIMER_ALARM_0 0x009420
+
+struct nv04_timer_priv {
+ struct nouveau_timer base;
+ struct list_head alarms;
+ spinlock_t lock;
+ u64 suspend_time;
+};
+
+int nv04_timer_ctor(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void *, u32,
+ struct nouveau_object **);
+void nv04_timer_dtor(struct nouveau_object *);
+int nv04_timer_fini(struct nouveau_object *, bool);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/priv.h b/drivers/gpu/drm/nouveau/core/subdev/timer/priv.h
new file mode 100644
index 000000000000..799dae3f2300
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/timer/priv.h
@@ -0,0 +1,6 @@
+#ifndef __NVKM_TIMER_PRIV_H__
+#define __NVKM_TIMER_PRIV_H__
+
+#include <subdev/timer.h>
+
+#endif