drm/nouveau/fb: create tag heap from common code for all relevant chipsets
A nv2x bug wrt hardcoded tag counts is now also fixed as a side-effect. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
268d5a3017
commit
dac1558d49
@ -64,6 +64,7 @@ nouveau-y += core/subdev/devinit/nv50.o
|
||||
nouveau-y += core/subdev/fb/base.o
|
||||
nouveau-y += core/subdev/fb/nv04.o
|
||||
nouveau-y += core/subdev/fb/nv10.o
|
||||
nouveau-y += core/subdev/fb/nv1a.o
|
||||
nouveau-y += core/subdev/fb/nv20.o
|
||||
nouveau-y += core/subdev/fb/nv25.o
|
||||
nouveau-y += core/subdev/fb/nv30.o
|
||||
|
@ -71,6 +71,7 @@ struct nouveau_fb {
|
||||
u64 size;
|
||||
int ranks;
|
||||
|
||||
int (*init)(struct nouveau_fb *);
|
||||
int (*get)(struct nouveau_fb *, u64 size, u32 align,
|
||||
u32 size_nc, u32 type, struct nouveau_mem **);
|
||||
void (*put)(struct nouveau_fb *, struct nouveau_mem **);
|
||||
@ -101,7 +102,7 @@ nouveau_fb(void *obj)
|
||||
|
||||
#define nouveau_fb_create(p,e,c,d) \
|
||||
nouveau_subdev_create((p), (e), (c), 0, "PFB", "fb", (d))
|
||||
int nouveau_fb_created(struct nouveau_fb *);
|
||||
int nouveau_fb_preinit(struct nouveau_fb *);
|
||||
void nouveau_fb_destroy(struct nouveau_fb *);
|
||||
int nouveau_fb_init(struct nouveau_fb *);
|
||||
#define nouveau_fb_fini(p,s) \
|
||||
@ -113,6 +114,7 @@ int _nouveau_fb_init(struct nouveau_object *);
|
||||
|
||||
extern struct nouveau_oclass nv04_fb_oclass;
|
||||
extern struct nouveau_oclass nv10_fb_oclass;
|
||||
extern struct nouveau_oclass nv1a_fb_oclass;
|
||||
extern struct nouveau_oclass nv20_fb_oclass;
|
||||
extern struct nouveau_oclass nv25_fb_oclass;
|
||||
extern struct nouveau_oclass nv30_fb_oclass;
|
||||
@ -132,6 +134,12 @@ int nouveau_fb_bios_memtype(struct nouveau_bios *);
|
||||
|
||||
bool nv04_fb_memtype_valid(struct nouveau_fb *, u32 memtype);
|
||||
|
||||
void nv10_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
|
||||
u32 pitch, u32 flags, struct nouveau_fb_tile *);
|
||||
void nv10_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *);
|
||||
void nv10_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
|
||||
|
||||
int nv20_fb_vram_init(struct nouveau_fb *);
|
||||
void nv20_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
|
||||
u32 pitch, u32 flags, struct nouveau_fb_tile *);
|
||||
void nv20_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *);
|
||||
@ -142,9 +150,11 @@ void nv30_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
|
||||
u32 pitch, u32 flags, struct nouveau_fb_tile *);
|
||||
void nv30_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *);
|
||||
|
||||
int nv41_fb_vram_init(struct nouveau_fb *);
|
||||
int nv41_fb_init(struct nouveau_object *);
|
||||
void nv41_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
|
||||
|
||||
int nv44_fb_vram_init(struct nouveau_fb *);
|
||||
int nv44_fb_init(struct nouveau_object *);
|
||||
void nv44_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
|
||||
|
||||
|
@ -105,7 +105,7 @@ nv10_identify(struct nouveau_device *device)
|
||||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv1a_fb_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
|
||||
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
|
||||
@ -159,7 +159,7 @@ nv10_identify(struct nouveau_device *device)
|
||||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv1a_fb_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
|
||||
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
|
||||
|
@ -57,27 +57,47 @@ nouveau_fb_bios_memtype(struct nouveau_bios *bios)
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_fb_init(struct nouveau_fb *pfb)
|
||||
nouveau_fb_preinit(struct nouveau_fb *pfb)
|
||||
{
|
||||
int ret, i;
|
||||
static const char *name[] = {
|
||||
[NV_MEM_TYPE_UNKNOWN] = "unknown",
|
||||
[NV_MEM_TYPE_STOLEN ] = "stolen system memory",
|
||||
[NV_MEM_TYPE_SGRAM ] = "SGRAM",
|
||||
[NV_MEM_TYPE_SDRAM ] = "SDRAM",
|
||||
[NV_MEM_TYPE_DDR1 ] = "DDR1",
|
||||
[NV_MEM_TYPE_DDR2 ] = "DDR2",
|
||||
[NV_MEM_TYPE_DDR3 ] = "DDR3",
|
||||
[NV_MEM_TYPE_GDDR2 ] = "GDDR2",
|
||||
[NV_MEM_TYPE_GDDR3 ] = "GDDR3",
|
||||
[NV_MEM_TYPE_GDDR4 ] = "GDDR4",
|
||||
[NV_MEM_TYPE_GDDR5 ] = "GDDR5",
|
||||
};
|
||||
int ret, tags;
|
||||
|
||||
ret = nouveau_subdev_init(&pfb->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
tags = pfb->ram.init(pfb);
|
||||
if (tags < 0 || !pfb->ram.size) {
|
||||
nv_fatal(pfb, "error detecting memory configuration!!\n");
|
||||
return (tags < 0) ? tags : -ERANGE;
|
||||
}
|
||||
|
||||
for (i = 0; i < pfb->tile.regions; i++)
|
||||
pfb->tile.prog(pfb, i, &pfb->tile.region[i]);
|
||||
if (!nouveau_mm_initialised(&pfb->vram)) {
|
||||
ret = nouveau_mm_init(&pfb->vram, 0, pfb->ram.size >> 12, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!nouveau_mm_initialised(&pfb->tags) && tags) {
|
||||
ret = nouveau_mm_init(&pfb->tags, 0, ++tags, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
nv_info(pfb, "RAM type: %s\n", name[pfb->ram.type]);
|
||||
nv_info(pfb, "RAM size: %d MiB\n", (int)(pfb->ram.size >> 20));
|
||||
nv_info(pfb, " ZCOMP: %d tags\n", tags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_nouveau_fb_init(struct nouveau_object *object)
|
||||
{
|
||||
struct nouveau_fb *pfb = (void *)object;
|
||||
return nouveau_fb_init(pfb);
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_fb_destroy(struct nouveau_fb *pfb)
|
||||
{
|
||||
@ -97,30 +117,24 @@ _nouveau_fb_dtor(struct nouveau_object *object)
|
||||
struct nouveau_fb *pfb = (void *)object;
|
||||
nouveau_fb_destroy(pfb);
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_fb_created(struct nouveau_fb *pfb)
|
||||
nouveau_fb_init(struct nouveau_fb *pfb)
|
||||
{
|
||||
static const char *name[] = {
|
||||
[NV_MEM_TYPE_UNKNOWN] = "unknown",
|
||||
[NV_MEM_TYPE_STOLEN ] = "stolen system memory",
|
||||
[NV_MEM_TYPE_SGRAM ] = "SGRAM",
|
||||
[NV_MEM_TYPE_SDRAM ] = "SDRAM",
|
||||
[NV_MEM_TYPE_DDR1 ] = "DDR1",
|
||||
[NV_MEM_TYPE_DDR2 ] = "DDR2",
|
||||
[NV_MEM_TYPE_DDR3 ] = "DDR3",
|
||||
[NV_MEM_TYPE_GDDR2 ] = "GDDR2",
|
||||
[NV_MEM_TYPE_GDDR3 ] = "GDDR3",
|
||||
[NV_MEM_TYPE_GDDR4 ] = "GDDR4",
|
||||
[NV_MEM_TYPE_GDDR5 ] = "GDDR5",
|
||||
};
|
||||
int ret, i;
|
||||
|
||||
if (pfb->ram.size == 0) {
|
||||
nv_fatal(pfb, "no vram detected!!\n");
|
||||
return -ERANGE;
|
||||
}
|
||||
ret = nouveau_subdev_init(&pfb->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < pfb->tile.regions; i++)
|
||||
pfb->tile.prog(pfb, i, &pfb->tile.region[i]);
|
||||
|
||||
nv_info(pfb, "RAM type: %s\n", name[pfb->ram.type]);
|
||||
nv_info(pfb, "RAM size: %d MiB\n", (int)(pfb->ram.size >> 20));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_nouveau_fb_init(struct nouveau_object *object)
|
||||
{
|
||||
struct nouveau_fb *pfb = (void *)object;
|
||||
return nouveau_fb_init(pfb);
|
||||
}
|
||||
|
@ -55,6 +55,37 @@ nv04_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
nv04_fb_vram_init(struct nouveau_fb *pfb)
|
||||
{
|
||||
u32 boot0 = nv_rd32(pfb, NV04_PFB_BOOT_0);
|
||||
if (boot0 & 0x00000100) {
|
||||
pfb->ram.size = ((boot0 >> 12) & 0xf) * 2 + 2;
|
||||
pfb->ram.size *= 1024 * 1024;
|
||||
} else {
|
||||
switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) {
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB:
|
||||
pfb->ram.size = 32 * 1024 * 1024;
|
||||
break;
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB:
|
||||
pfb->ram.size = 16 * 1024 * 1024;
|
||||
break;
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB:
|
||||
pfb->ram.size = 8 * 1024 * 1024;
|
||||
break;
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB:
|
||||
pfb->ram.size = 4 * 1024 * 1024;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((boot0 & 0x00000038) <= 0x10)
|
||||
pfb->ram.type = NV_MEM_TYPE_SGRAM;
|
||||
else
|
||||
pfb->ram.type = NV_MEM_TYPE_SDRAM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nv04_fb_init(struct nouveau_object *object)
|
||||
{
|
||||
@ -79,7 +110,6 @@ nv04_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nv04_fb_priv *priv;
|
||||
u32 boot0;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
@ -87,35 +117,9 @@ nv04_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
boot0 = nv_rd32(priv, NV04_PFB_BOOT_0);
|
||||
if (boot0 & 0x00000100) {
|
||||
priv->base.ram.size = ((boot0 >> 12) & 0xf) * 2 + 2;
|
||||
priv->base.ram.size *= 1024 * 1024;
|
||||
} else {
|
||||
switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) {
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB:
|
||||
priv->base.ram.size = 32 * 1024 * 1024;
|
||||
break;
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB:
|
||||
priv->base.ram.size = 16 * 1024 * 1024;
|
||||
break;
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB:
|
||||
priv->base.ram.size = 8 * 1024 * 1024;
|
||||
break;
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB:
|
||||
priv->base.ram.size = 4 * 1024 * 1024;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((boot0 & 0x00000038) <= 0x10)
|
||||
priv->base.ram.type = NV_MEM_TYPE_SGRAM;
|
||||
else
|
||||
priv->base.ram.type = NV_MEM_TYPE_SDRAM;
|
||||
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
priv->base.ram.init = nv04_fb_vram_init;
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
@ -30,7 +30,20 @@ struct nv10_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
static void
|
||||
static int
|
||||
nv10_fb_vram_init(struct nouveau_fb *pfb)
|
||||
{
|
||||
u32 cfg0 = nv_rd32(pfb, 0x100200);
|
||||
if (cfg0 & 0x00000001)
|
||||
pfb->ram.type = NV_MEM_TYPE_DDR1;
|
||||
else
|
||||
pfb->ram.type = NV_MEM_TYPE_SDRAM;
|
||||
|
||||
pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv10_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
|
||||
u32 flags, struct nouveau_fb_tile *tile)
|
||||
{
|
||||
@ -39,7 +52,7 @@ nv10_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
|
||||
tile->pitch = pitch;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
nv10_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
|
||||
{
|
||||
tile->addr = 0;
|
||||
@ -48,7 +61,7 @@ nv10_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
|
||||
tile->zcomp = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
nv10_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
|
||||
{
|
||||
nv_wr32(pfb, 0x100244 + (i * 0x10), tile->limit);
|
||||
@ -62,7 +75,6 @@ nv10_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nv10_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
@ -71,42 +83,13 @@ nv10_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (device->chipset == 0x1a || device->chipset == 0x1f) {
|
||||
struct pci_dev *bridge;
|
||||
u32 mem, mib;
|
||||
|
||||
bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
|
||||
if (!bridge) {
|
||||
nv_fatal(device, "no bridge device\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (device->chipset == 0x1a) {
|
||||
pci_read_config_dword(bridge, 0x7c, &mem);
|
||||
mib = ((mem >> 6) & 31) + 1;
|
||||
} else {
|
||||
pci_read_config_dword(bridge, 0x84, &mem);
|
||||
mib = ((mem >> 4) & 127) + 1;
|
||||
}
|
||||
|
||||
priv->base.ram.type = NV_MEM_TYPE_STOLEN;
|
||||
priv->base.ram.size = mib * 1024 * 1024;
|
||||
} else {
|
||||
u32 cfg0 = nv_rd32(priv, 0x100200);
|
||||
if (cfg0 & 0x00000001)
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR1;
|
||||
else
|
||||
priv->base.ram.type = NV_MEM_TYPE_SDRAM;
|
||||
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
}
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.ram.init = nv10_fb_vram_init;
|
||||
priv->base.tile.regions = 8;
|
||||
priv->base.tile.init = nv10_fb_tile_init;
|
||||
priv->base.tile.fini = nv10_fb_tile_fini;
|
||||
priv->base.tile.prog = nv10_fb_tile_prog;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
89
drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c
Normal file
89
drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Francisco Jerez.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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 (including the
|
||||
* next paragraph) 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 OWNER(S) AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
|
||||
struct nv1a_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
static int
|
||||
nv1a_fb_vram_init(struct nouveau_fb *pfb)
|
||||
{
|
||||
struct pci_dev *bridge;
|
||||
u32 mem, mib;
|
||||
|
||||
bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
|
||||
if (!bridge) {
|
||||
nv_fatal(pfb, "no bridge device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (nv_device(pfb)->chipset == 0x1a) {
|
||||
pci_read_config_dword(bridge, 0x7c, &mem);
|
||||
mib = ((mem >> 6) & 31) + 1;
|
||||
} else {
|
||||
pci_read_config_dword(bridge, 0x84, &mem);
|
||||
mib = ((mem >> 4) & 127) + 1;
|
||||
}
|
||||
|
||||
pfb->ram.type = NV_MEM_TYPE_STOLEN;
|
||||
pfb->ram.size = mib * 1024 * 1024;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nv1a_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nv1a_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.ram.init = nv1a_fb_vram_init;
|
||||
priv->base.tile.regions = 8;
|
||||
priv->base.tile.init = nv10_fb_tile_init;
|
||||
priv->base.tile.fini = nv10_fb_tile_fini;
|
||||
priv->base.tile.prog = nv10_fb_tile_prog;
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
nv1a_fb_oclass = {
|
||||
.handle = NV_SUBDEV(FB, 0x1a),
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv1a_fb_ctor,
|
||||
.dtor = _nouveau_fb_dtor,
|
||||
.init = _nouveau_fb_init,
|
||||
.fini = _nouveau_fb_fini,
|
||||
},
|
||||
};
|
@ -30,6 +30,22 @@ struct nv20_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
int
|
||||
nv20_fb_vram_init(struct nouveau_fb *pfb)
|
||||
{
|
||||
u32 pbus1218 = nv_rd32(pfb, 0x001218);
|
||||
|
||||
switch (pbus1218 & 0x00000300) {
|
||||
case 0x00000000: pfb->ram.type = NV_MEM_TYPE_SDRAM; break;
|
||||
case 0x00000100: pfb->ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000200: pfb->ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000300: pfb->ram.type = NV_MEM_TYPE_GDDR2; break;
|
||||
}
|
||||
pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
||||
|
||||
return nv_rd32(pfb, 0x100320);
|
||||
}
|
||||
|
||||
void
|
||||
nv20_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
|
||||
u32 flags, struct nouveau_fb_tile *tile)
|
||||
@ -92,9 +108,7 @@ nv20_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nv20_fb_priv *priv;
|
||||
u32 pbus1218;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
@ -102,29 +116,14 @@ nv20_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pbus1218 = nv_rd32(priv, 0x001218);
|
||||
switch (pbus1218 & 0x00000300) {
|
||||
case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
|
||||
case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break;
|
||||
}
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
|
||||
if (device->chipset >= 0x25)
|
||||
ret = nouveau_mm_init(&priv->base.tags, 0, 64 * 1024, 1);
|
||||
else
|
||||
ret = nouveau_mm_init(&priv->base.tags, 0, 32 * 1024, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.ram.init = nv20_fb_vram_init;
|
||||
priv->base.tile.regions = 8;
|
||||
priv->base.tile.init = nv20_fb_tile_init;
|
||||
priv->base.tile.comp = nv20_fb_tile_comp;
|
||||
priv->base.tile.fini = nv20_fb_tile_fini;
|
||||
priv->base.tile.prog = nv20_fb_tile_prog;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
@ -60,9 +60,7 @@ nv25_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nv25_fb_priv *priv;
|
||||
u32 pbus1218;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
@ -70,29 +68,14 @@ nv25_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pbus1218 = nv_rd32(priv, 0x001218);
|
||||
switch (pbus1218 & 0x00000300) {
|
||||
case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
|
||||
case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break;
|
||||
}
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
|
||||
if (device->chipset >= 0x25)
|
||||
ret = nouveau_mm_init(&priv->base.tags, 0, 64 * 1024, 1);
|
||||
else
|
||||
ret = nouveau_mm_init(&priv->base.tags, 0, 32 * 1024, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.ram.init = nv20_fb_vram_init;
|
||||
priv->base.tile.regions = 8;
|
||||
priv->base.tile.init = nv20_fb_tile_init;
|
||||
priv->base.tile.comp = nv25_fb_tile_comp;
|
||||
priv->base.tile.fini = nv20_fb_tile_fini;
|
||||
priv->base.tile.prog = nv20_fb_tile_prog;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
@ -123,7 +123,6 @@ nv30_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nv30_fb_priv *priv;
|
||||
u32 pbus1218;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
@ -131,22 +130,14 @@ nv30_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pbus1218 = nv_rd32(priv, 0x001218);
|
||||
switch (pbus1218 & 0x00000300) {
|
||||
case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
|
||||
case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break;
|
||||
}
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.ram.init = nv20_fb_vram_init;
|
||||
priv->base.tile.regions = 8;
|
||||
priv->base.tile.init = nv30_fb_tile_init;
|
||||
priv->base.tile.comp = nv30_fb_tile_comp;
|
||||
priv->base.tile.fini = nv30_fb_tile_fini;
|
||||
priv->base.tile.prog = nv20_fb_tile_prog;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
@ -43,7 +43,6 @@ nv35_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nv35_fb_priv *priv;
|
||||
u32 pbus1218;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
@ -51,22 +50,14 @@ nv35_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pbus1218 = nv_rd32(priv, 0x001218);
|
||||
switch (pbus1218 & 0x00000300) {
|
||||
case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
|
||||
case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break;
|
||||
}
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.ram.init = nv20_fb_vram_init;
|
||||
priv->base.tile.regions = 8;
|
||||
priv->base.tile.init = nv30_fb_tile_init;
|
||||
priv->base.tile.comp = nv35_fb_tile_comp;
|
||||
priv->base.tile.fini = nv30_fb_tile_fini;
|
||||
priv->base.tile.prog = nv20_fb_tile_prog;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
@ -30,6 +30,21 @@ struct nv40_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
static int
|
||||
nv40_fb_vram_init(struct nouveau_fb *pfb)
|
||||
{
|
||||
u32 pbus1218 = nv_rd32(pfb, 0x001218);
|
||||
switch (pbus1218 & 0x00000300) {
|
||||
case 0x00000000: pfb->ram.type = NV_MEM_TYPE_SDRAM; break;
|
||||
case 0x00000100: pfb->ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000200: pfb->ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000300: pfb->ram.type = NV_MEM_TYPE_DDR2; break;
|
||||
}
|
||||
|
||||
pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
||||
return nv_rd32(pfb, 0x100320);
|
||||
}
|
||||
|
||||
static void
|
||||
nv40_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
|
||||
struct nouveau_fb_tile *tile)
|
||||
@ -56,9 +71,7 @@ nv40_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nv40_fb_priv *priv;
|
||||
u32 pbus1218;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
@ -66,23 +79,14 @@ nv40_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pbus1218 = nv_rd32(priv, 0x001218);
|
||||
switch (pbus1218 & 0x00000300) {
|
||||
case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
|
||||
case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_DDR2; break;
|
||||
}
|
||||
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.ram.init = nv40_fb_vram_init;
|
||||
priv->base.tile.regions = 8;
|
||||
priv->base.tile.init = nv30_fb_tile_init;
|
||||
priv->base.tile.comp = nv40_fb_tile_comp;
|
||||
priv->base.tile.fini = nv30_fb_tile_fini;
|
||||
priv->base.tile.prog = nv20_fb_tile_prog;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,6 +30,21 @@ struct nv41_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
int
|
||||
nv41_fb_vram_init(struct nouveau_fb *pfb)
|
||||
{
|
||||
u32 pfb474 = nv_rd32(pfb, 0x100474);
|
||||
if (pfb474 & 0x00000004)
|
||||
pfb->ram.type = NV_MEM_TYPE_GDDR3;
|
||||
if (pfb474 & 0x00000002)
|
||||
pfb->ram.type = NV_MEM_TYPE_DDR2;
|
||||
if (pfb474 & 0x00000001)
|
||||
pfb->ram.type = NV_MEM_TYPE_DDR1;
|
||||
|
||||
pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
||||
return nv_rd32(pfb, 0x100320);
|
||||
}
|
||||
|
||||
void
|
||||
nv41_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
|
||||
{
|
||||
@ -59,9 +74,7 @@ nv41_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nv41_fb_priv *priv;
|
||||
u32 pfb474;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
@ -69,22 +82,13 @@ nv41_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pfb474 = nv_rd32(priv, 0x100474);
|
||||
if (pfb474 & 0x00000004)
|
||||
priv->base.ram.type = NV_MEM_TYPE_GDDR3;
|
||||
if (pfb474 & 0x00000002)
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR2;
|
||||
if (pfb474 & 0x00000001)
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR1;
|
||||
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.ram.init = nv41_fb_vram_init;
|
||||
priv->base.tile.regions = 12;
|
||||
priv->base.tile.init = nv30_fb_tile_init;
|
||||
priv->base.tile.fini = nv30_fb_tile_fini;
|
||||
priv->base.tile.prog = nv41_fb_tile_prog;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,6 +30,21 @@ struct nv44_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
int
|
||||
nv44_fb_vram_init(struct nouveau_fb *pfb)
|
||||
{
|
||||
u32 pfb474 = nv_rd32(pfb, 0x100474);
|
||||
if (pfb474 & 0x00000004)
|
||||
pfb->ram.type = NV_MEM_TYPE_GDDR3;
|
||||
if (pfb474 & 0x00000002)
|
||||
pfb->ram.type = NV_MEM_TYPE_DDR2;
|
||||
if (pfb474 & 0x00000001)
|
||||
pfb->ram.type = NV_MEM_TYPE_DDR1;
|
||||
|
||||
pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nv44_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
|
||||
u32 flags, struct nouveau_fb_tile *tile)
|
||||
@ -69,9 +84,7 @@ nv44_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nv44_fb_priv *priv;
|
||||
u32 pfb474;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
@ -79,22 +92,13 @@ nv44_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pfb474 = nv_rd32(priv, 0x100474);
|
||||
if (pfb474 & 0x00000004)
|
||||
priv->base.ram.type = NV_MEM_TYPE_GDDR3;
|
||||
if (pfb474 & 0x00000002)
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR2;
|
||||
if (pfb474 & 0x00000001)
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR1;
|
||||
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.ram.init = nv44_fb_vram_init;
|
||||
priv->base.tile.regions = 12;
|
||||
priv->base.tile.init = nv44_fb_tile_init;
|
||||
priv->base.tile.fini = nv30_fb_tile_fini;
|
||||
priv->base.tile.prog = nv44_fb_tile_prog;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
|
||||
|
@ -49,9 +49,7 @@ nv46_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nv46_fb_priv *priv;
|
||||
u32 pfb474;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
@ -59,22 +57,13 @@ nv46_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pfb474 = nv_rd32(priv, 0x100474);
|
||||
if (pfb474 & 0x00000004)
|
||||
priv->base.ram.type = NV_MEM_TYPE_GDDR3;
|
||||
if (pfb474 & 0x00000002)
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR2;
|
||||
if (pfb474 & 0x00000001)
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR1;
|
||||
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.ram.init = nv44_fb_vram_init;
|
||||
priv->base.tile.regions = 15;
|
||||
priv->base.tile.init = nv46_fb_tile_init;
|
||||
priv->base.tile.fini = nv30_fb_tile_fini;
|
||||
priv->base.tile.prog = nv44_fb_tile_prog;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,9 +35,7 @@ nv47_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nv47_fb_priv *priv;
|
||||
u32 pfb474;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
@ -45,22 +43,13 @@ nv47_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pfb474 = nv_rd32(priv, 0x100474);
|
||||
if (pfb474 & 0x00000004)
|
||||
priv->base.ram.type = NV_MEM_TYPE_GDDR3;
|
||||
if (pfb474 & 0x00000002)
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR2;
|
||||
if (pfb474 & 0x00000001)
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR1;
|
||||
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.ram.init = nv41_fb_vram_init;
|
||||
priv->base.tile.regions = 15;
|
||||
priv->base.tile.init = nv30_fb_tile_init;
|
||||
priv->base.tile.fini = nv30_fb_tile_fini;
|
||||
priv->base.tile.prog = nv41_fb_tile_prog;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,14 +30,28 @@ struct nv49_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
static int
|
||||
nv49_fb_vram_init(struct nouveau_fb *pfb)
|
||||
{
|
||||
u32 pfb914 = nv_rd32(pfb, 0x100914);
|
||||
|
||||
switch (pfb914 & 0x00000003) {
|
||||
case 0x00000000: pfb->ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000001: pfb->ram.type = NV_MEM_TYPE_DDR2; break;
|
||||
case 0x00000002: pfb->ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000003: break;
|
||||
}
|
||||
|
||||
pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
||||
return nv_rd32(pfb, 0x100320);
|
||||
}
|
||||
|
||||
static int
|
||||
nv49_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nv49_fb_priv *priv;
|
||||
u32 pfb914;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
@ -45,23 +59,14 @@ nv49_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pfb914 = nv_rd32(priv, 0x100914);
|
||||
switch (pfb914 & 0x00000003) {
|
||||
case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000001: priv->base.ram.type = NV_MEM_TYPE_DDR2; break;
|
||||
case 0x00000002: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000003: break;
|
||||
}
|
||||
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.ram.init = nv49_fb_vram_init;
|
||||
priv->base.tile.regions = 15;
|
||||
priv->base.tile.init = nv30_fb_tile_init;
|
||||
priv->base.tile.fini = nv30_fb_tile_fini;
|
||||
priv->base.tile.prog = nv41_fb_tile_prog;
|
||||
|
||||
return nouveau_fb_created(&priv->base);
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,12 +30,19 @@ struct nv4e_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
static int
|
||||
nv4e_fb_vram_init(struct nouveau_fb *pfb)
|
||||
{
|
||||
pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
||||
pfb->ram.type = NV_MEM_TYPE_STOLEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nv4e_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nv4e_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
@ -44,17 +51,15 @@ nv4e_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
priv->base.ram.type = NV_MEM_TYPE_STOLEN;
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.ram.init = nv4e_fb_vram_init;
|
||||
priv->base.tile.regions = 12;
|
||||
priv->base.tile.init = nv46_fb_tile_init;
|
||||
priv->base.tile.fini = nv30_fb_tile_fini;
|
||||
priv->base.tile.prog = nv44_fb_tile_prog;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
|
||||
struct nouveau_oclass
|
||||
nv4e_fb_oclass = {
|
||||
.handle = NV_SUBDEV(FB, 0x4e),
|
||||
|
@ -51,6 +51,101 @@ nv50_fb_memtype_valid(struct nouveau_fb *pfb, u32 memtype)
|
||||
return types[(memtype & 0xff00) >> 8] != 0;
|
||||
}
|
||||
|
||||
static u32
|
||||
nv50_fb_vram_rblock(struct nouveau_fb *pfb)
|
||||
{
|
||||
int i, parts, colbits, rowbitsa, rowbitsb, banks;
|
||||
u64 rowsize, predicted;
|
||||
u32 r0, r4, rt, ru, rblock_size;
|
||||
|
||||
r0 = nv_rd32(pfb, 0x100200);
|
||||
r4 = nv_rd32(pfb, 0x100204);
|
||||
rt = nv_rd32(pfb, 0x100250);
|
||||
ru = nv_rd32(pfb, 0x001540);
|
||||
nv_debug(pfb, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru);
|
||||
|
||||
for (i = 0, parts = 0; i < 8; i++) {
|
||||
if (ru & (0x00010000 << i))
|
||||
parts++;
|
||||
}
|
||||
|
||||
colbits = (r4 & 0x0000f000) >> 12;
|
||||
rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
|
||||
rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
|
||||
banks = 1 << (((r4 & 0x03000000) >> 24) + 2);
|
||||
|
||||
rowsize = parts * banks * (1 << colbits) * 8;
|
||||
predicted = rowsize << rowbitsa;
|
||||
if (r0 & 0x00000004)
|
||||
predicted += rowsize << rowbitsb;
|
||||
|
||||
if (predicted != pfb->ram.size) {
|
||||
nv_warn(pfb, "memory controller reports %d MiB VRAM\n",
|
||||
(u32)(pfb->ram.size >> 20));
|
||||
}
|
||||
|
||||
rblock_size = rowsize;
|
||||
if (rt & 1)
|
||||
rblock_size *= 3;
|
||||
|
||||
nv_debug(pfb, "rblock %d bytes\n", rblock_size);
|
||||
return rblock_size;
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_fb_vram_init(struct nouveau_fb *pfb)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(pfb);
|
||||
struct nouveau_bios *bios = nouveau_bios(device);
|
||||
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
|
||||
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
|
||||
u32 size;
|
||||
int ret;
|
||||
|
||||
pfb->ram.size = nv_rd32(pfb, 0x10020c);
|
||||
pfb->ram.size = (pfb->ram.size & 0xffffff00) |
|
||||
((pfb->ram.size & 0x000000ff) << 32);
|
||||
|
||||
size = (pfb->ram.size >> 12) - rsvd_head - rsvd_tail;
|
||||
switch (device->chipset) {
|
||||
case 0xaa:
|
||||
case 0xac:
|
||||
case 0xaf: /* IGPs, no reordering, no real VRAM */
|
||||
ret = nouveau_mm_init(&pfb->vram, rsvd_head, size, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pfb->ram.type = NV_MEM_TYPE_STOLEN;
|
||||
pfb->ram.stolen = (u64)nv_rd32(pfb, 0x100e10) << 12;
|
||||
break;
|
||||
default:
|
||||
switch (nv_rd32(pfb, 0x100714) & 0x00000007) {
|
||||
case 0: pfb->ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 1:
|
||||
if (nouveau_fb_bios_memtype(bios) == NV_MEM_TYPE_DDR3)
|
||||
pfb->ram.type = NV_MEM_TYPE_DDR3;
|
||||
else
|
||||
pfb->ram.type = NV_MEM_TYPE_DDR2;
|
||||
break;
|
||||
case 2: pfb->ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 3: pfb->ram.type = NV_MEM_TYPE_GDDR4; break;
|
||||
case 4: pfb->ram.type = NV_MEM_TYPE_GDDR5; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = nouveau_mm_init(&pfb->vram, rsvd_head, size,
|
||||
nv50_fb_vram_rblock(pfb) >> 12);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pfb->ram.ranks = (nv_rd32(pfb, 0x100200) & 0x4) ? 2 : 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return nv_rd32(pfb, 0x100320);
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
|
||||
u32 memtype, struct nouveau_mem **pmem)
|
||||
@ -140,58 +235,13 @@ nv50_fb_vram_del(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
|
||||
kfree(mem);
|
||||
}
|
||||
|
||||
static u32
|
||||
nv50_vram_rblock(struct nv50_fb_priv *priv)
|
||||
{
|
||||
int i, parts, colbits, rowbitsa, rowbitsb, banks;
|
||||
u64 rowsize, predicted;
|
||||
u32 r0, r4, rt, ru, rblock_size;
|
||||
|
||||
r0 = nv_rd32(priv, 0x100200);
|
||||
r4 = nv_rd32(priv, 0x100204);
|
||||
rt = nv_rd32(priv, 0x100250);
|
||||
ru = nv_rd32(priv, 0x001540);
|
||||
nv_debug(priv, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru);
|
||||
|
||||
for (i = 0, parts = 0; i < 8; i++) {
|
||||
if (ru & (0x00010000 << i))
|
||||
parts++;
|
||||
}
|
||||
|
||||
colbits = (r4 & 0x0000f000) >> 12;
|
||||
rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
|
||||
rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
|
||||
banks = 1 << (((r4 & 0x03000000) >> 24) + 2);
|
||||
|
||||
rowsize = parts * banks * (1 << colbits) * 8;
|
||||
predicted = rowsize << rowbitsa;
|
||||
if (r0 & 0x00000004)
|
||||
predicted += rowsize << rowbitsb;
|
||||
|
||||
if (predicted != priv->base.ram.size) {
|
||||
nv_warn(priv, "memory controller reports %d MiB VRAM\n",
|
||||
(u32)(priv->base.ram.size >> 20));
|
||||
}
|
||||
|
||||
rblock_size = rowsize;
|
||||
if (rt & 1)
|
||||
rblock_size *= 3;
|
||||
|
||||
nv_debug(priv, "rblock %d bytes\n", rblock_size);
|
||||
return rblock_size;
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nouveau_bios *bios = nouveau_bios(device);
|
||||
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
|
||||
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
|
||||
struct nv50_fb_priv *priv;
|
||||
u32 tags;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
@ -199,54 +249,6 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (nv_rd32(priv, 0x100714) & 0x00000007) {
|
||||
case 0: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 1:
|
||||
if (nouveau_fb_bios_memtype(bios) == NV_MEM_TYPE_DDR3)
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR3;
|
||||
else
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR2;
|
||||
break;
|
||||
case 2: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 3: priv->base.ram.type = NV_MEM_TYPE_GDDR4; break;
|
||||
case 4: priv->base.ram.type = NV_MEM_TYPE_GDDR5; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c);
|
||||
priv->base.ram.size = (priv->base.ram.size & 0xffffff00) |
|
||||
((priv->base.ram.size & 0x000000ff) << 32);
|
||||
|
||||
tags = nv_rd32(priv, 0x100320);
|
||||
ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nv_debug(priv, "%d compression tags\n", tags);
|
||||
|
||||
size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
|
||||
switch (device->chipset) {
|
||||
case 0xaa:
|
||||
case 0xac:
|
||||
case 0xaf: /* IGPs, no reordering, no real VRAM */
|
||||
ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12;
|
||||
priv->base.ram.type = NV_MEM_TYPE_STOLEN;
|
||||
break;
|
||||
default:
|
||||
ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size,
|
||||
nv50_vram_rblock(priv) >> 12);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->base.ram.ranks = (nv_rd32(priv, 0x100200) & 0x4) ? 2 : 1;
|
||||
break;
|
||||
}
|
||||
|
||||
priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
|
||||
if (priv->r100c08_page) {
|
||||
priv->r100c08 = pci_map_page(device->pdev, priv->r100c08_page,
|
||||
@ -259,9 +261,10 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
}
|
||||
|
||||
priv->base.memtype_valid = nv50_fb_memtype_valid;
|
||||
priv->base.ram.init = nv50_fb_vram_init;
|
||||
priv->base.ram.get = nv50_fb_vram_new;
|
||||
priv->base.ram.put = nv50_fb_vram_del;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -61,6 +61,65 @@ nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)
|
||||
return likely((types[memtype] == 1));
|
||||
}
|
||||
|
||||
static int
|
||||
nvc0_fb_vram_init(struct nouveau_fb *pfb)
|
||||
{
|
||||
struct nouveau_bios *bios = nouveau_bios(pfb);
|
||||
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 bsize = nv_rd32(pfb, 0x10f20c);
|
||||
u32 offset, length;
|
||||
bool uniform = true;
|
||||
int ret, part;
|
||||
|
||||
nv_debug(pfb, "0x100800: 0x%08x\n", nv_rd32(pfb, 0x100800));
|
||||
nv_debug(pfb, "parts 0x%08x mask 0x%08x\n", parts, pmask);
|
||||
|
||||
pfb->ram.type = nouveau_fb_bios_memtype(bios);
|
||||
pfb->ram.ranks = (nv_rd32(pfb, 0x10f200) & 0x00000004) ? 2 : 1;
|
||||
|
||||
/* read amount of vram attached to each memory controller */
|
||||
for (part = 0; part < parts; part++) {
|
||||
if (!(pmask & (1 << part))) {
|
||||
u32 psize = nv_rd32(pfb, 0x11020c + (part * 0x1000));
|
||||
if (psize != bsize) {
|
||||
if (psize < bsize)
|
||||
bsize = psize;
|
||||
uniform = false;
|
||||
}
|
||||
|
||||
nv_debug(pfb, "%d: mem_amount 0x%08x\n", part, psize);
|
||||
pfb->ram.size += (u64)psize << 20;
|
||||
}
|
||||
}
|
||||
|
||||
/* if all controllers have the same amount attached, there's no holes */
|
||||
if (uniform) {
|
||||
offset = rsvd_head;
|
||||
length = (pfb->ram.size >> 12) - rsvd_head - rsvd_tail;
|
||||
return nouveau_mm_init(&pfb->vram, offset, length, 1);
|
||||
}
|
||||
|
||||
/* otherwise, address lowest common amount from 0GiB */
|
||||
ret = nouveau_mm_init(&pfb->vram, rsvd_head, (bsize << 8) * parts, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* and the rest starting from (8GiB + common_size) */
|
||||
offset = (0x0200000000ULL >> 12) + (bsize << 8);
|
||||
length = (pfb->ram.size >> 12) - (bsize << 8) - rsvd_tail;
|
||||
|
||||
ret = nouveau_mm_init(&pfb->vram, offset, length, 0);
|
||||
if (ret) {
|
||||
nouveau_mm_fini(&pfb->vram);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
|
||||
u32 memtype, struct nouveau_mem **pmem)
|
||||
@ -138,66 +197,6 @@ nvc0_fb_dtor(struct nouveau_object *object)
|
||||
nouveau_fb_destroy(&priv->base);
|
||||
}
|
||||
|
||||
static int
|
||||
nvc0_vram_detect(struct nvc0_fb_priv *priv)
|
||||
{
|
||||
struct nouveau_bios *bios = nouveau_bios(priv);
|
||||
struct nouveau_fb *pfb = &priv->base;
|
||||
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
|
||||
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
|
||||
u32 parts = nv_rd32(priv, 0x022438);
|
||||
u32 pmask = nv_rd32(priv, 0x022554);
|
||||
u32 bsize = nv_rd32(priv, 0x10f20c);
|
||||
u32 offset, length;
|
||||
bool uniform = true;
|
||||
int ret, part;
|
||||
|
||||
nv_debug(priv, "0x100800: 0x%08x\n", nv_rd32(priv, 0x100800));
|
||||
nv_debug(priv, "parts 0x%08x mask 0x%08x\n", parts, pmask);
|
||||
|
||||
priv->base.ram.type = nouveau_fb_bios_memtype(bios);
|
||||
priv->base.ram.ranks = (nv_rd32(priv, 0x10f200) & 0x00000004) ? 2 : 1;
|
||||
|
||||
/* read amount of vram attached to each memory controller */
|
||||
for (part = 0; part < parts; part++) {
|
||||
if (!(pmask & (1 << part))) {
|
||||
u32 psize = nv_rd32(priv, 0x11020c + (part * 0x1000));
|
||||
if (psize != bsize) {
|
||||
if (psize < bsize)
|
||||
bsize = psize;
|
||||
uniform = false;
|
||||
}
|
||||
|
||||
nv_debug(priv, "%d: mem_amount 0x%08x\n", part, psize);
|
||||
priv->base.ram.size += (u64)psize << 20;
|
||||
}
|
||||
}
|
||||
|
||||
/* if all controllers have the same amount attached, there's no holes */
|
||||
if (uniform) {
|
||||
offset = rsvd_head;
|
||||
length = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
|
||||
return nouveau_mm_init(&pfb->vram, offset, length, 1);
|
||||
}
|
||||
|
||||
/* otherwise, address lowest common amount from 0GiB */
|
||||
ret = nouveau_mm_init(&pfb->vram, rsvd_head, (bsize << 8) * parts, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* and the rest starting from (8GiB + common_size) */
|
||||
offset = (0x0200000000ULL >> 12) + (bsize << 8);
|
||||
length = (priv->base.ram.size >> 12) - (bsize << 8) - rsvd_tail;
|
||||
|
||||
ret = nouveau_mm_init(&pfb->vram, offset, length, 0);
|
||||
if (ret) {
|
||||
nouveau_mm_fini(&pfb->vram);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
@ -213,13 +212,10 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
return ret;
|
||||
|
||||
priv->base.memtype_valid = nvc0_fb_memtype_valid;
|
||||
priv->base.ram.init = nvc0_fb_vram_init;
|
||||
priv->base.ram.get = nvc0_fb_vram_new;
|
||||
priv->base.ram.put = nv50_fb_vram_del;
|
||||
|
||||
ret = nvc0_vram_detect(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
|
||||
if (!priv->r100c10_page)
|
||||
return -ENOMEM;
|
||||
@ -229,7 +225,7 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
if (pci_dma_mapping_error(device->pdev, priv->r100c10))
|
||||
return -EFAULT;
|
||||
|
||||
return nouveau_fb_created(&priv->base);
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user