drm/nouveau/fb: initialise vram controller as pfb sub-object
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
54ecff3e1a
commit
dceef5d87c
|
@ -80,6 +80,17 @@ nouveau-y += core/subdev/fb/nv49.o
|
|||
nouveau-y += core/subdev/fb/nv4e.o
|
||||
nouveau-y += core/subdev/fb/nv50.o
|
||||
nouveau-y += core/subdev/fb/nvc0.o
|
||||
nouveau-y += core/subdev/fb/ramnv04.o
|
||||
nouveau-y += core/subdev/fb/ramnv10.o
|
||||
nouveau-y += core/subdev/fb/ramnv1a.o
|
||||
nouveau-y += core/subdev/fb/ramnv20.o
|
||||
nouveau-y += core/subdev/fb/ramnv40.o
|
||||
nouveau-y += core/subdev/fb/ramnv41.o
|
||||
nouveau-y += core/subdev/fb/ramnv44.o
|
||||
nouveau-y += core/subdev/fb/ramnv49.o
|
||||
nouveau-y += core/subdev/fb/ramnv4e.o
|
||||
nouveau-y += core/subdev/fb/ramnv50.o
|
||||
nouveau-y += core/subdev/fb/ramnvc0.o
|
||||
nouveau-y += core/subdev/gpio/base.o
|
||||
nouveau-y += core/subdev/gpio/nv10.o
|
||||
nouveau-y += core/subdev/gpio/nv50.o
|
||||
|
|
|
@ -320,7 +320,7 @@ nv40_fifo_init(struct nouveau_object *object)
|
|||
break;
|
||||
default:
|
||||
nv_wr32(priv, 0x002230, 0x00000000);
|
||||
nv_wr32(priv, 0x002220, ((pfb->ram.size - 512 * 1024 +
|
||||
nv_wr32(priv, 0x002220, ((pfb->ram->size - 512 * 1024 +
|
||||
priv->ramfc->addr) >> 16) |
|
||||
0x00030000);
|
||||
break;
|
||||
|
|
|
@ -53,31 +53,7 @@ struct nouveau_fb {
|
|||
|
||||
bool (*memtype_valid)(struct nouveau_fb *, u32 memtype);
|
||||
|
||||
struct {
|
||||
enum {
|
||||
NV_MEM_TYPE_UNKNOWN = 0,
|
||||
NV_MEM_TYPE_STOLEN,
|
||||
NV_MEM_TYPE_SGRAM,
|
||||
NV_MEM_TYPE_SDRAM,
|
||||
NV_MEM_TYPE_DDR1,
|
||||
NV_MEM_TYPE_DDR2,
|
||||
NV_MEM_TYPE_DDR3,
|
||||
NV_MEM_TYPE_GDDR2,
|
||||
NV_MEM_TYPE_GDDR3,
|
||||
NV_MEM_TYPE_GDDR4,
|
||||
NV_MEM_TYPE_GDDR5
|
||||
} type;
|
||||
u64 stolen;
|
||||
u64 size;
|
||||
|
||||
int ranks;
|
||||
int parts;
|
||||
|
||||
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 **);
|
||||
} ram;
|
||||
struct nouveau_ram *ram;
|
||||
|
||||
struct nouveau_mm vram;
|
||||
struct nouveau_mm tags;
|
||||
|
@ -102,18 +78,6 @@ nouveau_fb(void *obj)
|
|||
return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_FB];
|
||||
}
|
||||
|
||||
#define nouveau_fb_create(p,e,c,d) \
|
||||
nouveau_subdev_create((p), (e), (c), 0, "PFB", "fb", (d))
|
||||
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) \
|
||||
nouveau_subdev_fini(&(p)->base, (s))
|
||||
|
||||
void _nouveau_fb_dtor(struct nouveau_object *);
|
||||
int _nouveau_fb_init(struct nouveau_object *);
|
||||
#define _nouveau_fb_fini _nouveau_subdev_fini
|
||||
|
||||
extern struct nouveau_oclass nv04_fb_oclass;
|
||||
extern struct nouveau_oclass nv10_fb_oclass;
|
||||
extern struct nouveau_oclass nv1a_fb_oclass;
|
||||
|
@ -132,40 +96,31 @@ extern struct nouveau_oclass nv4e_fb_oclass;
|
|||
extern struct nouveau_oclass nv50_fb_oclass;
|
||||
extern struct nouveau_oclass nvc0_fb_oclass;
|
||||
|
||||
struct nouveau_bios;
|
||||
int nouveau_fb_bios_memtype(struct nouveau_bios *);
|
||||
struct nouveau_ram {
|
||||
struct nouveau_object base;
|
||||
enum {
|
||||
NV_MEM_TYPE_UNKNOWN = 0,
|
||||
NV_MEM_TYPE_STOLEN,
|
||||
NV_MEM_TYPE_SGRAM,
|
||||
NV_MEM_TYPE_SDRAM,
|
||||
NV_MEM_TYPE_DDR1,
|
||||
NV_MEM_TYPE_DDR2,
|
||||
NV_MEM_TYPE_DDR3,
|
||||
NV_MEM_TYPE_GDDR2,
|
||||
NV_MEM_TYPE_GDDR3,
|
||||
NV_MEM_TYPE_GDDR4,
|
||||
NV_MEM_TYPE_GDDR5
|
||||
} type;
|
||||
u64 stolen;
|
||||
u64 size;
|
||||
u32 tags;
|
||||
|
||||
bool nv04_fb_memtype_valid(struct nouveau_fb *, u32 memtype);
|
||||
int ranks;
|
||||
int parts;
|
||||
|
||||
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 *);
|
||||
void nv20_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
|
||||
|
||||
int nv30_fb_init(struct nouveau_object *);
|
||||
void nv30_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
|
||||
u32 pitch, u32 flags, struct nouveau_fb_tile *);
|
||||
|
||||
void nv40_fb_tile_comp(struct nouveau_fb *, int i, u32 size, u32 flags,
|
||||
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 *);
|
||||
|
||||
void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
|
||||
u32 pitch, u32 flags, struct nouveau_fb_tile *);
|
||||
|
||||
void nv50_fb_vram_del(struct nouveau_fb *, struct nouveau_mem **);
|
||||
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 **);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -57,7 +57,57 @@ nouveau_fb_bios_memtype(struct nouveau_bios *bios)
|
|||
}
|
||||
|
||||
int
|
||||
nouveau_fb_preinit(struct nouveau_fb *pfb)
|
||||
_nouveau_fb_fini(struct nouveau_object *object, bool suspend)
|
||||
{
|
||||
struct nouveau_fb *pfb = (void *)object;
|
||||
int ret;
|
||||
|
||||
ret = nv_ofuncs(pfb->ram)->fini(nv_object(pfb->ram), suspend);
|
||||
if (ret && suspend)
|
||||
return ret;
|
||||
|
||||
return nouveau_subdev_fini(&pfb->base, suspend);
|
||||
}
|
||||
|
||||
int
|
||||
_nouveau_fb_init(struct nouveau_object *object)
|
||||
{
|
||||
struct nouveau_fb *pfb = (void *)object;
|
||||
int ret, i;
|
||||
|
||||
ret = nouveau_subdev_init(&pfb->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = nv_ofuncs(pfb->ram)->init(nv_object(pfb->ram));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < pfb->tile.regions; i++)
|
||||
pfb->tile.prog(pfb, i, &pfb->tile.region[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_nouveau_fb_dtor(struct nouveau_object *object)
|
||||
{
|
||||
struct nouveau_fb *pfb = (void *)object;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pfb->tile.regions; i++)
|
||||
pfb->tile.fini(pfb, i, &pfb->tile.region[i]);
|
||||
nouveau_mm_fini(&pfb->tags);
|
||||
nouveau_mm_fini(&pfb->vram);
|
||||
|
||||
nouveau_object_ref(NULL, (struct nouveau_object **)&pfb->ram);
|
||||
nouveau_subdev_destroy(&pfb->base);
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_fb_create_(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, struct nouveau_oclass *ramcls,
|
||||
int length, void **pobject)
|
||||
{
|
||||
static const char *name[] = {
|
||||
[NV_MEM_TYPE_UNKNOWN] = "unknown",
|
||||
|
@ -72,69 +122,42 @@ nouveau_fb_preinit(struct nouveau_fb *pfb)
|
|||
[NV_MEM_TYPE_GDDR4 ] = "GDDR4",
|
||||
[NV_MEM_TYPE_GDDR5 ] = "GDDR5",
|
||||
};
|
||||
int ret, tags;
|
||||
struct nouveau_object *ram;
|
||||
struct nouveau_fb *pfb;
|
||||
int ret;
|
||||
|
||||
tags = pfb->ram.init(pfb);
|
||||
if (tags < 0 || !pfb->ram.size) {
|
||||
ret = nouveau_subdev_create_(parent, engine, oclass, 0, "PFB", "fb",
|
||||
length, pobject);
|
||||
pfb = *pobject;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = nouveau_object_ctor(nv_object(pfb), nv_object(pfb),
|
||||
ramcls, NULL, 0, &ram);
|
||||
if (ret) {
|
||||
nv_fatal(pfb, "error detecting memory configuration!!\n");
|
||||
return (tags < 0) ? tags : -ERANGE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
atomic_dec(&ram->parent->refcount);
|
||||
atomic_dec(&ram->engine->refcount);
|
||||
pfb->ram = (void *)ram;
|
||||
|
||||
if (!nouveau_mm_initialised(&pfb->vram)) {
|
||||
ret = nouveau_mm_init(&pfb->vram, 0, pfb->ram.size >> 12, 1);
|
||||
ret = nouveau_mm_init(&pfb->vram, 0, pfb->ram->size >> 12, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!nouveau_mm_initialised(&pfb->tags)) {
|
||||
ret = nouveau_mm_init(&pfb->tags, 0, tags ? ++tags : 0, 1);
|
||||
ret = nouveau_mm_init(&pfb->tags, 0, pfb->ram->tags ?
|
||||
++pfb->ram->tags : 0, 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);
|
||||
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", pfb->ram->tags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_fb_destroy(struct nouveau_fb *pfb)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pfb->tile.regions; i++)
|
||||
pfb->tile.fini(pfb, i, &pfb->tile.region[i]);
|
||||
nouveau_mm_fini(&pfb->tags);
|
||||
nouveau_mm_fini(&pfb->vram);
|
||||
|
||||
nouveau_subdev_destroy(&pfb->base);
|
||||
}
|
||||
|
||||
void
|
||||
_nouveau_fb_dtor(struct nouveau_object *object)
|
||||
{
|
||||
struct nouveau_fb *pfb = (void *)object;
|
||||
nouveau_fb_destroy(pfb);
|
||||
}
|
||||
int
|
||||
nouveau_fb_init(struct nouveau_fb *pfb)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
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]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_nouveau_fb_init(struct nouveau_object *object)
|
||||
{
|
||||
struct nouveau_fb *pfb = (void *)object;
|
||||
return nouveau_fb_init(pfb);
|
||||
}
|
||||
|
|
|
@ -22,24 +22,8 @@
|
|||
* Authors: Ben Skeggs
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
|
||||
#define NV04_PFB_BOOT_0 0x00100000
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT_4MB 0x00000001
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT_8MB 0x00000002
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT_16MB 0x00000003
|
||||
# define NV04_PFB_BOOT_0_RAM_WIDTH_128 0x00000004
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE 0x00000028
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT 0x00000000
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT 0x00000008
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT_4BANK 0x00000010
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT 0x00000018
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBIT 0x00000020
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBITX16 0x00000028
|
||||
# define NV04_PFB_BOOT_0_UMA_ENABLE 0x00000100
|
||||
# define NV04_PFB_BOOT_0_UMA_SIZE 0x0000f000
|
||||
#define NV04_PFB_CFG0 0x00100200
|
||||
|
||||
struct nv04_fb_priv {
|
||||
|
@ -55,37 +39,6 @@ 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)
|
||||
{
|
||||
|
@ -112,14 +65,13 @@ nv04_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv04_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv04_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.ram.init = nv04_fb_vram_init;
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
|
|
@ -24,25 +24,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
|
||||
struct nv10_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
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)
|
||||
|
@ -78,18 +65,17 @@ nv10_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv10_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv10_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
|
|
@ -24,37 +24,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.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,
|
||||
|
@ -63,18 +38,17 @@ nv1a_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv1a_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv1a_ram_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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
|
|
@ -24,29 +24,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
|
||||
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);
|
||||
pfb->ram.parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
|
||||
|
||||
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)
|
||||
|
@ -65,7 +48,7 @@ nv20_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
|
|||
struct nouveau_fb_tile *tile)
|
||||
{
|
||||
u32 tiles = DIV_ROUND_UP(size, 0x40);
|
||||
u32 tags = round_up(tiles / pfb->ram.parts, 0x40);
|
||||
u32 tags = round_up(tiles / pfb->ram->parts, 0x40);
|
||||
if (!nouveau_mm_head(&pfb->tags, 1, tags, tags, 1, &tile->tag)) {
|
||||
if (!(flags & 2)) tile->zcomp = 0x00000000; /* Z16 */
|
||||
else tile->zcomp = 0x04000000; /* Z24S8 */
|
||||
|
@ -105,19 +88,18 @@ nv20_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv20_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv20_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
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_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
|
||||
struct nv25_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
|
@ -35,7 +35,7 @@ nv25_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
|
|||
struct nouveau_fb_tile *tile)
|
||||
{
|
||||
u32 tiles = DIV_ROUND_UP(size, 0x40);
|
||||
u32 tags = round_up(tiles / pfb->ram.parts, 0x40);
|
||||
u32 tags = round_up(tiles / pfb->ram->parts, 0x40);
|
||||
if (!nouveau_mm_head(&pfb->tags, 1, tags, tags, 1, &tile->tag)) {
|
||||
if (!(flags & 2)) tile->zcomp = 0x00100000; /* Z16 */
|
||||
else tile->zcomp = 0x00200000; /* Z24S8 */
|
||||
|
@ -54,19 +54,18 @@ nv25_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv25_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv20_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
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_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
|
||||
struct nv30_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
|
@ -54,7 +54,7 @@ nv30_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
|
|||
struct nouveau_fb_tile *tile)
|
||||
{
|
||||
u32 tiles = DIV_ROUND_UP(size, 0x40);
|
||||
u32 tags = round_up(tiles / pfb->ram.parts, 0x40);
|
||||
u32 tags = round_up(tiles / pfb->ram->parts, 0x40);
|
||||
if (!nouveau_mm_head(&pfb->tags, 1, tags, tags, 1, &tile->tag)) {
|
||||
if (flags & 2) tile->zcomp |= 0x01000000; /* Z16 */
|
||||
else tile->zcomp |= 0x02000000; /* Z24S8 */
|
||||
|
@ -132,19 +132,18 @@ nv30_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv30_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv20_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
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 = nv30_fb_tile_init;
|
||||
priv->base.tile.comp = nv30_fb_tile_comp;
|
||||
priv->base.tile.fini = nv20_fb_tile_fini;
|
||||
priv->base.tile.prog = nv20_fb_tile_prog;
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
|
||||
struct nv35_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
|
@ -35,7 +35,7 @@ nv35_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
|
|||
struct nouveau_fb_tile *tile)
|
||||
{
|
||||
u32 tiles = DIV_ROUND_UP(size, 0x40);
|
||||
u32 tags = round_up(tiles / pfb->ram.parts, 0x40);
|
||||
u32 tags = round_up(tiles / pfb->ram->parts, 0x40);
|
||||
if (!nouveau_mm_head(&pfb->tags, 1, tags, tags, 1, &tile->tag)) {
|
||||
if (flags & 2) tile->zcomp |= 0x04000000; /* Z16 */
|
||||
else tile->zcomp |= 0x08000000; /* Z24S8 */
|
||||
|
@ -55,19 +55,18 @@ nv35_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv35_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv20_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
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 = nv30_fb_tile_init;
|
||||
priv->base.tile.comp = nv35_fb_tile_comp;
|
||||
priv->base.tile.fini = nv20_fb_tile_fini;
|
||||
priv->base.tile.prog = nv20_fb_tile_prog;
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
|
||||
struct nv36_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
|
@ -35,7 +35,7 @@ nv36_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
|
|||
struct nouveau_fb_tile *tile)
|
||||
{
|
||||
u32 tiles = DIV_ROUND_UP(size, 0x40);
|
||||
u32 tags = round_up(tiles / pfb->ram.parts, 0x40);
|
||||
u32 tags = round_up(tiles / pfb->ram->parts, 0x40);
|
||||
if (!nouveau_mm_head(&pfb->tags, 1, tags, tags, 1, &tile->tag)) {
|
||||
if (flags & 2) tile->zcomp |= 0x10000000; /* Z16 */
|
||||
else tile->zcomp |= 0x20000000; /* Z24S8 */
|
||||
|
@ -55,19 +55,18 @@ nv36_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv36_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv20_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
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 = nv30_fb_tile_init;
|
||||
priv->base.tile.comp = nv36_fb_tile_comp;
|
||||
priv->base.tile.fini = nv20_fb_tile_fini;
|
||||
priv->base.tile.prog = nv20_fb_tile_prog;
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
|
|
@ -24,34 +24,18 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
|
||||
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;
|
||||
pfb->ram.parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
|
||||
return nv_rd32(pfb, 0x100320);
|
||||
}
|
||||
|
||||
void
|
||||
nv40_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
|
||||
struct nouveau_fb_tile *tile)
|
||||
{
|
||||
u32 tiles = DIV_ROUND_UP(size, 0x80);
|
||||
u32 tags = round_up(tiles / pfb->ram.parts, 0x100);
|
||||
u32 tags = round_up(tiles / pfb->ram->parts, 0x100);
|
||||
if ( (flags & 2) &&
|
||||
!nouveau_mm_head(&pfb->tags, 1, tags, tags, 1, &tile->tag)) {
|
||||
tile->zcomp = 0x28000000; /* Z24S8_SPLIT_GRAD */
|
||||
|
@ -85,19 +69,18 @@ nv40_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv40_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv40_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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 = nv20_fb_tile_fini;
|
||||
priv->base.tile.prog = nv20_fb_tile_prog;
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,28 +24,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
|
||||
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;
|
||||
pfb->ram.parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
|
||||
return nv_rd32(pfb, 0x100320);
|
||||
}
|
||||
|
||||
void
|
||||
nv41_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
|
||||
{
|
||||
|
@ -78,19 +62,18 @@ nv41_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv41_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv41_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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.comp = nv40_fb_tile_comp;
|
||||
priv->base.tile.fini = nv20_fb_tile_fini;
|
||||
priv->base.tile.prog = nv41_fb_tile_prog;
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,27 +24,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
|
||||
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)
|
||||
|
@ -87,18 +72,17 @@ nv44_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv44_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv44_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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 = nv20_fb_tile_fini;
|
||||
priv->base.tile.prog = nv44_fb_tile_prog;
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
|
||||
struct nv46_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
|
@ -52,18 +52,17 @@ nv46_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv46_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv44_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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 = nv20_fb_tile_fini;
|
||||
priv->base.tile.prog = nv44_fb_tile_prog;
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
|
||||
struct nv47_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
|
@ -38,19 +38,18 @@ nv47_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv47_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv41_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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.comp = nv40_fb_tile_comp;
|
||||
priv->base.tile.fini = nv20_fb_tile_fini;
|
||||
priv->base.tile.prog = nv41_fb_tile_prog;
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,29 +24,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
|
||||
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;
|
||||
pfb->ram.parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
|
||||
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,
|
||||
|
@ -55,20 +38,18 @@ nv49_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv49_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv49_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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.comp = nv40_fb_tile_comp;
|
||||
priv->base.tile.fini = nv20_fb_tile_fini;
|
||||
priv->base.tile.prog = nv41_fb_tile_prog;
|
||||
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,20 +24,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
|
||||
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,
|
||||
|
@ -46,18 +38,17 @@ nv4e_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv4e_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv4e_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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 = nv20_fb_tile_fini;
|
||||
priv->base.tile.prog = nv44_fb_tile_prog;
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <core/engctx.h>
|
||||
#include <core/object.h>
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include "priv.h"
|
||||
#include <subdev/bios.h>
|
||||
|
||||
struct nv50_fb_priv {
|
||||
|
@ -36,7 +36,8 @@ struct nv50_fb_priv {
|
|||
dma_addr_t r100c08;
|
||||
};
|
||||
|
||||
static int types[0x80] = {
|
||||
int
|
||||
nv50_fb_memtype[0x80] = {
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0,
|
||||
|
@ -50,192 +51,7 @@ static int types[0x80] = {
|
|||
static bool
|
||||
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, tags = 0;
|
||||
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;
|
||||
tags = nv_rd32(pfb, 0x100320);
|
||||
break;
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
|
||||
u32 memtype, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct nv50_fb_priv *priv = (void *)pfb;
|
||||
struct nouveau_mm *heap = &priv->base.vram;
|
||||
struct nouveau_mm *tags = &priv->base.tags;
|
||||
struct nouveau_mm_node *r;
|
||||
struct nouveau_mem *mem;
|
||||
int comp = (memtype & 0x300) >> 8;
|
||||
int type = (memtype & 0x07f);
|
||||
int back = (memtype & 0x800);
|
||||
int min, max, ret;
|
||||
|
||||
max = (size >> 12);
|
||||
min = ncmin ? (ncmin >> 12) : max;
|
||||
align >>= 12;
|
||||
|
||||
mem = kzalloc(sizeof(*mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&pfb->base.mutex);
|
||||
if (comp) {
|
||||
if (align == 16) {
|
||||
int n = (max >> 4) * comp;
|
||||
|
||||
ret = nouveau_mm_head(tags, 1, n, n, 1, &mem->tag);
|
||||
if (ret)
|
||||
mem->tag = NULL;
|
||||
}
|
||||
|
||||
if (unlikely(!mem->tag))
|
||||
comp = 0;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&mem->regions);
|
||||
mem->memtype = (comp << 7) | type;
|
||||
mem->size = max;
|
||||
|
||||
type = types[type];
|
||||
do {
|
||||
if (back)
|
||||
ret = nouveau_mm_tail(heap, type, max, min, align, &r);
|
||||
else
|
||||
ret = nouveau_mm_head(heap, type, max, min, align, &r);
|
||||
if (ret) {
|
||||
mutex_unlock(&pfb->base.mutex);
|
||||
pfb->ram.put(pfb, &mem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_add_tail(&r->rl_entry, &mem->regions);
|
||||
max -= r->length;
|
||||
} while (max);
|
||||
mutex_unlock(&pfb->base.mutex);
|
||||
|
||||
r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
|
||||
mem->offset = (u64)r->offset << 12;
|
||||
*pmem = mem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_fb_vram_del(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct nv50_fb_priv *priv = (void *)pfb;
|
||||
struct nouveau_mm_node *this;
|
||||
struct nouveau_mem *mem;
|
||||
|
||||
mem = *pmem;
|
||||
*pmem = NULL;
|
||||
if (unlikely(mem == NULL))
|
||||
return;
|
||||
|
||||
mutex_lock(&pfb->base.mutex);
|
||||
while (!list_empty(&mem->regions)) {
|
||||
this = list_first_entry(&mem->regions, typeof(*this), rl_entry);
|
||||
|
||||
list_del(&this->rl_entry);
|
||||
nouveau_mm_free(&priv->base.vram, &this);
|
||||
}
|
||||
|
||||
nouveau_mm_free(&priv->base.tags, &mem->tag);
|
||||
mutex_unlock(&pfb->base.mutex);
|
||||
|
||||
kfree(mem);
|
||||
return nv50_fb_memtype[(memtype & 0xff00) >> 8] != 0;
|
||||
}
|
||||
|
||||
static const struct nouveau_enum vm_dispatch_subclients[] = {
|
||||
|
@ -432,7 +248,7 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nv50_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nv50_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -449,11 +265,8 @@ 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;
|
||||
nv_subdev(priv)->intr = nv50_fb_intr;
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -22,9 +22,7 @@
|
|||
* Authors: Ben Skeggs
|
||||
*/
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include <subdev/ltcg.h>
|
||||
#include <subdev/bios.h>
|
||||
#include "priv.h"
|
||||
|
||||
struct nvc0_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
|
@ -34,7 +32,6 @@ struct nvc0_fb_priv {
|
|||
|
||||
extern const u8 nvc0_pte_storage_type_map[256];
|
||||
|
||||
|
||||
static bool
|
||||
nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)
|
||||
{
|
||||
|
@ -42,137 +39,6 @@ nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)
|
|||
return likely((nvc0_pte_storage_type_map[memtype] != 0xff));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct nouveau_mm *mm = &pfb->vram;
|
||||
struct nouveau_mm_node *r;
|
||||
struct nouveau_mem *mem;
|
||||
int type = (memtype & 0x0ff);
|
||||
int back = (memtype & 0x800);
|
||||
int ret;
|
||||
const bool comp = nvc0_pte_storage_type_map[type] != type;
|
||||
|
||||
size >>= 12;
|
||||
align >>= 12;
|
||||
ncmin >>= 12;
|
||||
if (!ncmin)
|
||||
ncmin = size;
|
||||
|
||||
mem = kzalloc(sizeof(*mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&mem->regions);
|
||||
mem->size = size;
|
||||
|
||||
mutex_lock(&pfb->base.mutex);
|
||||
if (comp) {
|
||||
struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb->base.base.parent);
|
||||
|
||||
/* compression only works with lpages */
|
||||
if (align == (1 << (17 - 12))) {
|
||||
int n = size >> 5;
|
||||
ltcg->tags_alloc(ltcg, n, &mem->tag);
|
||||
}
|
||||
if (unlikely(!mem->tag))
|
||||
type = nvc0_pte_storage_type_map[type];
|
||||
}
|
||||
mem->memtype = type;
|
||||
|
||||
do {
|
||||
if (back)
|
||||
ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r);
|
||||
else
|
||||
ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r);
|
||||
if (ret) {
|
||||
mutex_unlock(&pfb->base.mutex);
|
||||
pfb->ram.put(pfb, &mem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_add_tail(&r->rl_entry, &mem->regions);
|
||||
size -= r->length;
|
||||
} while (size);
|
||||
mutex_unlock(&pfb->base.mutex);
|
||||
|
||||
r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
|
||||
mem->offset = (u64)r->offset << 12;
|
||||
*pmem = mem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nvc0_fb_vram_del(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb->base.base.parent);
|
||||
|
||||
if ((*pmem)->tag)
|
||||
ltcg->tags_free(ltcg, &(*pmem)->tag);
|
||||
|
||||
nv50_fb_vram_del(pfb, pmem);
|
||||
}
|
||||
|
||||
static int
|
||||
nvc0_fb_init(struct nouveau_object *object)
|
||||
{
|
||||
|
@ -212,15 +78,12 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
struct nvc0_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &nvc0_ram_oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
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 = nvc0_fb_vram_del;
|
||||
|
||||
priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
|
||||
if (priv->r100c10_page) {
|
||||
|
@ -231,7 +94,7 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
return nouveau_fb_preinit(&priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
#ifndef __NVKM_FB_PRIV_H__
|
||||
#define __NVKM_FB_PRIV_H__
|
||||
|
||||
#include <subdev/fb.h>
|
||||
|
||||
#define nouveau_ram_create(p,e,o,d) \
|
||||
nouveau_object_create_((p), (e), (o), 0, sizeof(**d), (void **)d)
|
||||
#define nouveau_ram_destroy(p) \
|
||||
nouveau_object_destroy(&(p)->base)
|
||||
#define nouveau_ram_init(p) \
|
||||
nouveau_object_init(&(p)->base)
|
||||
#define nouveau_ram_fini(p,s) \
|
||||
nouveau_object_fini(&(p)->base, (s))
|
||||
|
||||
#define _nouveau_ram_dtor nouveau_object_destroy
|
||||
#define _nouveau_ram_init nouveau_object_init
|
||||
#define _nouveau_ram_fini nouveau_object_fini
|
||||
|
||||
extern struct nouveau_oclass nv04_ram_oclass;
|
||||
extern struct nouveau_oclass nv10_ram_oclass;
|
||||
extern struct nouveau_oclass nv1a_ram_oclass;
|
||||
extern struct nouveau_oclass nv20_ram_oclass;
|
||||
extern struct nouveau_oclass nv40_ram_oclass;
|
||||
extern struct nouveau_oclass nv41_ram_oclass;
|
||||
extern struct nouveau_oclass nv44_ram_oclass;
|
||||
extern struct nouveau_oclass nv49_ram_oclass;
|
||||
extern struct nouveau_oclass nv4e_ram_oclass;
|
||||
extern struct nouveau_oclass nv50_ram_oclass;
|
||||
extern struct nouveau_oclass nvc0_ram_oclass;
|
||||
|
||||
#define nouveau_fb_create(p,e,c,r,d) \
|
||||
nouveau_fb_create_((p), (e), (c), (r), sizeof(**d), (void **)d)
|
||||
#define nouveau_fb_destroy(p) ({ \
|
||||
struct nouveau_fb *pfb = (p); \
|
||||
_nouveau_fb_dtor(nv_object(pfb)); \
|
||||
})
|
||||
#define nouveau_fb_init(p) ({ \
|
||||
struct nouveau_fb *pfb = (p); \
|
||||
_nouveau_fb_init(nv_object(pfb)); \
|
||||
})
|
||||
#define nouveau_fb_fini(p,s) ({ \
|
||||
struct nouveau_fb *pfb = (p); \
|
||||
_nouveau_fb_fini(nv_object(pfb), (s)); \
|
||||
})
|
||||
|
||||
int nouveau_fb_create_(struct nouveau_object *, struct nouveau_object *,
|
||||
struct nouveau_oclass *, struct nouveau_oclass *,
|
||||
int length, void **pobject);
|
||||
void _nouveau_fb_dtor(struct nouveau_object *);
|
||||
int _nouveau_fb_init(struct nouveau_object *);
|
||||
int _nouveau_fb_fini(struct nouveau_object *, bool);
|
||||
|
||||
struct nouveau_bios;
|
||||
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 *);
|
||||
|
||||
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 *);
|
||||
void nv20_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
|
||||
|
||||
int nv30_fb_init(struct nouveau_object *);
|
||||
void nv30_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
|
||||
u32 pitch, u32 flags, struct nouveau_fb_tile *);
|
||||
|
||||
void nv40_fb_tile_comp(struct nouveau_fb *, int i, u32 size, u32 flags,
|
||||
struct nouveau_fb_tile *);
|
||||
|
||||
int nv41_fb_init(struct nouveau_object *);
|
||||
void nv41_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
|
||||
|
||||
int nv44_fb_init(struct nouveau_object *);
|
||||
void nv44_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
|
||||
|
||||
void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
|
||||
u32 pitch, u32 flags, struct nouveau_fb_tile *);
|
||||
|
||||
void nv50_ram_put(struct nouveau_fb *, struct nouveau_mem **);
|
||||
extern int nv50_fb_memtype[0x80];
|
||||
|
||||
#endif
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define NV04_PFB_BOOT_0 0x00100000
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT_4MB 0x00000001
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT_8MB 0x00000002
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT_16MB 0x00000003
|
||||
# define NV04_PFB_BOOT_0_RAM_WIDTH_128 0x00000004
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE 0x00000028
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT 0x00000000
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT 0x00000008
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT_4BANK 0x00000010
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT 0x00000018
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBIT 0x00000020
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBITX16 0x00000028
|
||||
# define NV04_PFB_BOOT_0_UMA_ENABLE 0x00000100
|
||||
# define NV04_PFB_BOOT_0_UMA_SIZE 0x0000f000
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
static int
|
||||
nv04_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_fb *pfb = nouveau_fb(parent);
|
||||
struct nouveau_ram *ram;
|
||||
u32 boot0 = nv_rd32(pfb, NV04_PFB_BOOT_0);
|
||||
int ret;
|
||||
|
||||
ret = nouveau_ram_create(parent, engine, oclass, &ram);
|
||||
*pobject = nv_object(ram);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (boot0 & 0x00000100) {
|
||||
ram->size = ((boot0 >> 12) & 0xf) * 2 + 2;
|
||||
ram->size *= 1024 * 1024;
|
||||
} else {
|
||||
switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) {
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB:
|
||||
ram->size = 32 * 1024 * 1024;
|
||||
break;
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB:
|
||||
ram->size = 16 * 1024 * 1024;
|
||||
break;
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB:
|
||||
ram->size = 8 * 1024 * 1024;
|
||||
break;
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB:
|
||||
ram->size = 4 * 1024 * 1024;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((boot0 & 0x00000038) <= 0x10)
|
||||
ram->type = NV_MEM_TYPE_SGRAM;
|
||||
else
|
||||
ram->type = NV_MEM_TYPE_SDRAM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
nv04_ram_oclass = {
|
||||
.handle = 0,
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv04_ram_create,
|
||||
.dtor = _nouveau_ram_dtor,
|
||||
.init = _nouveau_ram_init,
|
||||
.fini = _nouveau_ram_fini,
|
||||
}
|
||||
};
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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 "priv.h"
|
||||
|
||||
static int
|
||||
nv10_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_fb *pfb = nouveau_fb(parent);
|
||||
struct nouveau_ram *ram;
|
||||
u32 cfg0 = nv_rd32(pfb, 0x100200);
|
||||
int ret;
|
||||
|
||||
ret = nouveau_ram_create(parent, engine, oclass, &ram);
|
||||
*pobject = nv_object(ram);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cfg0 & 0x00000001)
|
||||
ram->type = NV_MEM_TYPE_DDR1;
|
||||
else
|
||||
ram->type = NV_MEM_TYPE_SDRAM;
|
||||
|
||||
ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct nouveau_oclass
|
||||
nv10_ram_oclass = {
|
||||
.handle = 0,
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv10_ram_create,
|
||||
.dtor = _nouveau_ram_dtor,
|
||||
.init = _nouveau_ram_init,
|
||||
.fini = _nouveau_ram_fini,
|
||||
}
|
||||
};
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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 "priv.h"
|
||||
|
||||
static int
|
||||
nv1a_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_fb *pfb = nouveau_fb(parent);
|
||||
struct nouveau_ram *ram;
|
||||
struct pci_dev *bridge;
|
||||
u32 mem, mib;
|
||||
int ret;
|
||||
|
||||
bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
|
||||
if (!bridge) {
|
||||
nv_fatal(pfb, "no bridge device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = nouveau_ram_create(parent, engine, oclass, &ram);
|
||||
*pobject = nv_object(ram);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ram->type = NV_MEM_TYPE_STOLEN;
|
||||
ram->size = mib * 1024 * 1024;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
nv1a_ram_oclass = {
|
||||
.handle = 0,
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv1a_ram_create,
|
||||
.dtor = _nouveau_ram_dtor,
|
||||
.init = _nouveau_ram_init,
|
||||
.fini = _nouveau_ram_fini,
|
||||
}
|
||||
};
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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 "priv.h"
|
||||
|
||||
static int
|
||||
nv20_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_fb *pfb = nouveau_fb(parent);
|
||||
struct nouveau_ram *ram;
|
||||
u32 pbus1218 = nv_rd32(pfb, 0x001218);
|
||||
int ret;
|
||||
|
||||
ret = nouveau_ram_create(parent, engine, oclass, &ram);
|
||||
*pobject = nv_object(ram);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (pbus1218 & 0x00000300) {
|
||||
case 0x00000000: ram->type = NV_MEM_TYPE_SDRAM; break;
|
||||
case 0x00000100: ram->type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000200: ram->type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000300: ram->type = NV_MEM_TYPE_GDDR2; break;
|
||||
}
|
||||
ram->size = (nv_rd32(pfb, 0x10020c) & 0xff000000);
|
||||
ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
|
||||
ram->tags = nv_rd32(pfb, 0x100320);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
nv20_ram_oclass = {
|
||||
.handle = 0,
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv20_ram_create,
|
||||
.dtor = _nouveau_ram_dtor,
|
||||
.init = _nouveau_ram_init,
|
||||
.fini = _nouveau_ram_fini,
|
||||
}
|
||||
};
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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 "priv.h"
|
||||
|
||||
static int
|
||||
nv40_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_fb *pfb = nouveau_fb(parent);
|
||||
struct nouveau_ram *ram;
|
||||
u32 pbus1218 = nv_rd32(pfb, 0x001218);
|
||||
int ret;
|
||||
|
||||
ret = nouveau_ram_create(parent, engine, oclass, &ram);
|
||||
*pobject = nv_object(ram);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (pbus1218 & 0x00000300) {
|
||||
case 0x00000000: ram->type = NV_MEM_TYPE_SDRAM; break;
|
||||
case 0x00000100: ram->type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000200: ram->type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000300: ram->type = NV_MEM_TYPE_DDR2; break;
|
||||
}
|
||||
|
||||
ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
||||
ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
|
||||
ram->tags = nv_rd32(pfb, 0x100320);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct nouveau_oclass
|
||||
nv40_ram_oclass = {
|
||||
.handle = 0,
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv40_ram_create,
|
||||
.dtor = _nouveau_ram_dtor,
|
||||
.init = _nouveau_ram_init,
|
||||
.fini = _nouveau_ram_fini,
|
||||
}
|
||||
};
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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 "priv.h"
|
||||
|
||||
static int
|
||||
nv41_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_fb *pfb = nouveau_fb(parent);
|
||||
struct nouveau_ram *ram;
|
||||
u32 pfb474 = nv_rd32(pfb, 0x100474);
|
||||
int ret;
|
||||
|
||||
ret = nouveau_ram_create(parent, engine, oclass, &ram);
|
||||
*pobject = nv_object(ram);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (pfb474 & 0x00000004)
|
||||
ram->type = NV_MEM_TYPE_GDDR3;
|
||||
if (pfb474 & 0x00000002)
|
||||
ram->type = NV_MEM_TYPE_DDR2;
|
||||
if (pfb474 & 0x00000001)
|
||||
ram->type = NV_MEM_TYPE_DDR1;
|
||||
|
||||
ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
||||
ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
|
||||
ram->tags = nv_rd32(pfb, 0x100320);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
nv41_ram_oclass = {
|
||||
.handle = 0,
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv41_ram_create,
|
||||
.dtor = _nouveau_ram_dtor,
|
||||
.init = _nouveau_ram_init,
|
||||
.fini = _nouveau_ram_fini,
|
||||
}
|
||||
};
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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 "priv.h"
|
||||
|
||||
static int
|
||||
nv44_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_fb *pfb = nouveau_fb(parent);
|
||||
struct nouveau_ram *ram;
|
||||
u32 pfb474 = nv_rd32(pfb, 0x100474);
|
||||
int ret;
|
||||
|
||||
ret = nouveau_ram_create(parent, engine, oclass, &ram);
|
||||
*pobject = nv_object(ram);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (pfb474 & 0x00000004)
|
||||
ram->type = NV_MEM_TYPE_GDDR3;
|
||||
if (pfb474 & 0x00000002)
|
||||
ram->type = NV_MEM_TYPE_DDR2;
|
||||
if (pfb474 & 0x00000001)
|
||||
ram->type = NV_MEM_TYPE_DDR1;
|
||||
|
||||
ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
nv44_ram_oclass = {
|
||||
.handle = 0,
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv44_ram_create,
|
||||
.dtor = _nouveau_ram_dtor,
|
||||
.init = _nouveau_ram_init,
|
||||
.fini = _nouveau_ram_fini,
|
||||
}
|
||||
};
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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 "priv.h"
|
||||
|
||||
static int
|
||||
nv49_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_fb *pfb = nouveau_fb(parent);
|
||||
struct nouveau_ram *ram;
|
||||
u32 pfb914 = nv_rd32(pfb, 0x100914);
|
||||
int ret;
|
||||
|
||||
ret = nouveau_ram_create(parent, engine, oclass, &ram);
|
||||
*pobject = nv_object(ram);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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;
|
||||
pfb->ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
|
||||
pfb->ram->tags = nv_rd32(pfb, 0x100320);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
nv49_ram_oclass = {
|
||||
.handle = 0,
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv49_ram_create,
|
||||
.dtor = _nouveau_ram_dtor,
|
||||
.init = _nouveau_ram_init,
|
||||
.fini = _nouveau_ram_fini,
|
||||
}
|
||||
};
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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 "priv.h"
|
||||
|
||||
static int
|
||||
nv4e_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_fb *pfb = nouveau_fb(parent);
|
||||
struct nouveau_ram *ram;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_ram_create(parent, engine, oclass, &ram);
|
||||
*pobject = nv_object(ram);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pfb->ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
||||
pfb->ram->type = NV_MEM_TYPE_STOLEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
nv4e_ram_oclass = {
|
||||
.handle = 0,
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv4e_ram_create,
|
||||
.dtor = _nouveau_ram_dtor,
|
||||
.init = _nouveau_ram_init,
|
||||
.fini = _nouveau_ram_fini,
|
||||
}
|
||||
};
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
* 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 <core/mm.h>
|
||||
#include "priv.h"
|
||||
|
||||
void
|
||||
nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct nouveau_mm_node *this;
|
||||
struct nouveau_mem *mem;
|
||||
|
||||
mem = *pmem;
|
||||
*pmem = NULL;
|
||||
if (unlikely(mem == NULL))
|
||||
return;
|
||||
|
||||
mutex_lock(&pfb->base.mutex);
|
||||
while (!list_empty(&mem->regions)) {
|
||||
this = list_first_entry(&mem->regions, typeof(*this), rl_entry);
|
||||
|
||||
list_del(&this->rl_entry);
|
||||
nouveau_mm_free(&pfb->vram, &this);
|
||||
}
|
||||
|
||||
nouveau_mm_free(&pfb->tags, &mem->tag);
|
||||
mutex_unlock(&pfb->base.mutex);
|
||||
|
||||
kfree(mem);
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
|
||||
u32 memtype, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct nouveau_mm *heap = &pfb->vram;
|
||||
struct nouveau_mm *tags = &pfb->tags;
|
||||
struct nouveau_mm_node *r;
|
||||
struct nouveau_mem *mem;
|
||||
int comp = (memtype & 0x300) >> 8;
|
||||
int type = (memtype & 0x07f);
|
||||
int back = (memtype & 0x800);
|
||||
int min, max, ret;
|
||||
|
||||
max = (size >> 12);
|
||||
min = ncmin ? (ncmin >> 12) : max;
|
||||
align >>= 12;
|
||||
|
||||
mem = kzalloc(sizeof(*mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&pfb->base.mutex);
|
||||
if (comp) {
|
||||
if (align == 16) {
|
||||
int n = (max >> 4) * comp;
|
||||
|
||||
ret = nouveau_mm_head(tags, 1, n, n, 1, &mem->tag);
|
||||
if (ret)
|
||||
mem->tag = NULL;
|
||||
}
|
||||
|
||||
if (unlikely(!mem->tag))
|
||||
comp = 0;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&mem->regions);
|
||||
mem->memtype = (comp << 7) | type;
|
||||
mem->size = max;
|
||||
|
||||
type = nv50_fb_memtype[type];
|
||||
do {
|
||||
if (back)
|
||||
ret = nouveau_mm_tail(heap, type, max, min, align, &r);
|
||||
else
|
||||
ret = nouveau_mm_head(heap, type, max, min, align, &r);
|
||||
if (ret) {
|
||||
mutex_unlock(&pfb->base.mutex);
|
||||
pfb->ram->put(pfb, &mem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_add_tail(&r->rl_entry, &mem->regions);
|
||||
max -= r->length;
|
||||
} while (max);
|
||||
mutex_unlock(&pfb->base.mutex);
|
||||
|
||||
r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
|
||||
mem->offset = (u64)r->offset << 12;
|
||||
*pmem = mem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32
|
||||
nv50_fb_vram_rblock(struct nouveau_fb *pfb, struct nouveau_ram *ram)
|
||||
{
|
||||
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 != ram->size) {
|
||||
nv_warn(pfb, "memory controller reports %d MiB VRAM\n",
|
||||
(u32)(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_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 datasize,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_fb *pfb = nouveau_fb(parent);
|
||||
struct nouveau_device *device = nv_device(pfb);
|
||||
struct nouveau_bios *bios = nouveau_bios(device);
|
||||
struct nouveau_ram *ram;
|
||||
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
|
||||
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
|
||||
u32 size;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_ram_create(parent, engine, oclass, &ram);
|
||||
*pobject = nv_object(ram);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ram->size = nv_rd32(pfb, 0x10020c);
|
||||
ram->size = (ram->size & 0xffffff00) |
|
||||
((ram->size & 0x000000ff) << 32);
|
||||
|
||||
size = (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;
|
||||
|
||||
ram->type = NV_MEM_TYPE_STOLEN;
|
||||
ram->stolen = (u64)nv_rd32(pfb, 0x100e10) << 12;
|
||||
break;
|
||||
default:
|
||||
switch (nv_rd32(pfb, 0x100714) & 0x00000007) {
|
||||
case 0: ram->type = NV_MEM_TYPE_DDR1; break;
|
||||
case 1:
|
||||
if (nouveau_fb_bios_memtype(bios) == NV_MEM_TYPE_DDR3)
|
||||
ram->type = NV_MEM_TYPE_DDR3;
|
||||
else
|
||||
ram->type = NV_MEM_TYPE_DDR2;
|
||||
break;
|
||||
case 2: ram->type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 3: ram->type = NV_MEM_TYPE_GDDR4; break;
|
||||
case 4: ram->type = NV_MEM_TYPE_GDDR5; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = nouveau_mm_init(&pfb->vram, rsvd_head, size,
|
||||
nv50_fb_vram_rblock(pfb, ram) >> 12);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ram->ranks = (nv_rd32(pfb, 0x100200) & 0x4) ? 2 : 1;
|
||||
ram->tags = nv_rd32(pfb, 0x100320);
|
||||
break;
|
||||
}
|
||||
|
||||
ram->get = nv50_ram_get;
|
||||
ram->put = nv50_ram_put;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
nv50_ram_oclass = {
|
||||
.handle = 0,
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv50_ram_create,
|
||||
.dtor = _nouveau_ram_dtor,
|
||||
.init = _nouveau_ram_init,
|
||||
.fini = _nouveau_ram_fini,
|
||||
}
|
||||
};
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* 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/ltcg.h>
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
extern const u8 nvc0_pte_storage_type_map[256];
|
||||
|
||||
void
|
||||
nvc0_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb);
|
||||
|
||||
if ((*pmem)->tag)
|
||||
ltcg->tags_free(ltcg, &(*pmem)->tag);
|
||||
|
||||
nv50_ram_put(pfb, pmem);
|
||||
}
|
||||
|
||||
int
|
||||
nvc0_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
|
||||
u32 memtype, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct nouveau_mm *mm = &pfb->vram;
|
||||
struct nouveau_mm_node *r;
|
||||
struct nouveau_mem *mem;
|
||||
int type = (memtype & 0x0ff);
|
||||
int back = (memtype & 0x800);
|
||||
const bool comp = nvc0_pte_storage_type_map[type] != type;
|
||||
int ret;
|
||||
|
||||
size >>= 12;
|
||||
align >>= 12;
|
||||
ncmin >>= 12;
|
||||
if (!ncmin)
|
||||
ncmin = size;
|
||||
|
||||
mem = kzalloc(sizeof(*mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&mem->regions);
|
||||
mem->size = size;
|
||||
|
||||
mutex_lock(&pfb->base.mutex);
|
||||
if (comp) {
|
||||
struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb);
|
||||
|
||||
/* compression only works with lpages */
|
||||
if (align == (1 << (17 - 12))) {
|
||||
int n = size >> 5;
|
||||
ltcg->tags_alloc(ltcg, n, &mem->tag);
|
||||
}
|
||||
|
||||
if (unlikely(!mem->tag))
|
||||
type = nvc0_pte_storage_type_map[type];
|
||||
}
|
||||
mem->memtype = type;
|
||||
|
||||
do {
|
||||
if (back)
|
||||
ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r);
|
||||
else
|
||||
ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r);
|
||||
if (ret) {
|
||||
mutex_unlock(&pfb->base.mutex);
|
||||
pfb->ram->put(pfb, &mem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_add_tail(&r->rl_entry, &mem->regions);
|
||||
size -= r->length;
|
||||
} while (size);
|
||||
mutex_unlock(&pfb->base.mutex);
|
||||
|
||||
r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
|
||||
mem->offset = (u64)r->offset << 12;
|
||||
*pmem = mem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nvc0_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_fb *pfb = nouveau_fb(parent);
|
||||
struct nouveau_bios *bios = nouveau_bios(pfb);
|
||||
struct nouveau_ram *ram;
|
||||
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;
|
||||
|
||||
ret = nouveau_ram_create(parent, engine, oclass, &ram);
|
||||
*pobject = nv_object(ram);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nv_debug(pfb, "0x100800: 0x%08x\n", nv_rd32(pfb, 0x100800));
|
||||
nv_debug(pfb, "parts 0x%08x mask 0x%08x\n", parts, pmask);
|
||||
|
||||
ram->type = nouveau_fb_bios_memtype(bios);
|
||||
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);
|
||||
ram->size += (u64)psize << 20;
|
||||
}
|
||||
}
|
||||
|
||||
/* if all controllers have the same amount attached, there's no holes */
|
||||
if (uniform) {
|
||||
offset = rsvd_head;
|
||||
length = (ram->size >> 12) - rsvd_head - rsvd_tail;
|
||||
ret = nouveau_mm_init(&pfb->vram, offset, length, 1);
|
||||
} else {
|
||||
/* 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 = (ram->size >> 12) - (bsize << 8) - rsvd_tail;
|
||||
|
||||
ret = nouveau_mm_init(&pfb->vram, offset, length, 0);
|
||||
if (ret)
|
||||
nouveau_mm_fini(&pfb->vram);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ram->get = nvc0_ram_get;
|
||||
ram->put = nvc0_ram_put;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
nvc0_ram_oclass = {
|
||||
.handle = 0,
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nvc0_ram_create,
|
||||
.dtor = _nouveau_ram_dtor,
|
||||
.init = _nouveau_ram_init,
|
||||
.fini = _nouveau_ram_fini,
|
||||
}
|
||||
};
|
|
@ -56,7 +56,7 @@ nv50_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pfb->ram.get(pfb, size, align, 0, 0x800, &node->mem);
|
||||
ret = pfb->ram->get(pfb, size, align, 0, 0x800, &node->mem);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -71,7 +71,7 @@ nv50_instobj_dtor(struct nouveau_object *object)
|
|||
{
|
||||
struct nv50_instobj_priv *node = (void *)object;
|
||||
struct nouveau_fb *pfb = nouveau_fb(object);
|
||||
pfb->ram.put(pfb, &node->mem);
|
||||
pfb->ram->put(pfb, &node->mem);
|
||||
nouveau_instobj_destroy(&node->base);
|
||||
}
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
|
|||
nv_wr32(priv, 0x17e000, priv->part_nr);
|
||||
|
||||
/* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
|
||||
priv->num_tags = (pfb->ram.size >> 17) / 4;
|
||||
priv->num_tags = (pfb->ram->size >> 17) / 4;
|
||||
if (priv->num_tags > (1 << 17))
|
||||
priv->num_tags = 1 << 17; /* we have 17 bits in PTE */
|
||||
priv->num_tags = (priv->num_tags + 63) & ~63; /* round up to 64 */
|
||||
|
|
|
@ -86,8 +86,8 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
|
|||
|
||||
/* IGPs don't have real VRAM, re-target to stolen system memory */
|
||||
target = 0;
|
||||
if (nouveau_fb(vma->vm->vmm)->ram.stolen) {
|
||||
phys += nouveau_fb(vma->vm->vmm)->ram.stolen;
|
||||
if (nouveau_fb(vma->vm->vmm)->ram->stolen) {
|
||||
phys += nouveau_fb(vma->vm->vmm)->ram->stolen;
|
||||
target = 3;
|
||||
}
|
||||
|
||||
|
|
|
@ -255,7 +255,7 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t type)
|
|||
{
|
||||
struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(drm->device);
|
||||
u32 vram_pages = pfb->ram.size >> PAGE_SHIFT;
|
||||
u32 vram_pages = pfb->ram->size >> PAGE_SHIFT;
|
||||
|
||||
if (nv_device(drm->device)->card_type == NV_10 &&
|
||||
nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) &&
|
||||
|
|
|
@ -147,7 +147,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nouveau_cli *cli,
|
|||
args.limit = client->vm->vmm->limit - 1;
|
||||
} else
|
||||
if (chan->push.buffer->bo.mem.mem_type == TTM_PL_VRAM) {
|
||||
u64 limit = pfb->ram.size - imem->reserved - 1;
|
||||
u64 limit = pfb->ram->size - imem->reserved - 1;
|
||||
if (device->card_type == NV_04) {
|
||||
/* nv04 vram pushbuf hack, retarget to its location in
|
||||
* the framebuffer bar rather than direct vram access..
|
||||
|
@ -282,7 +282,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
|
|||
} else {
|
||||
args.flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR;
|
||||
args.start = 0;
|
||||
args.limit = pfb->ram.size - imem->reserved - 1;
|
||||
args.limit = pfb->ram->size - imem->reserved - 1;
|
||||
}
|
||||
|
||||
ret = nouveau_object_new(nv_object(client), chan->handle, vram,
|
||||
|
|
|
@ -467,10 +467,10 @@ nouveau_fbcon_init(struct drm_device *dev)
|
|||
|
||||
drm_fb_helper_single_add_all_connectors(&fbcon->helper);
|
||||
|
||||
if (pfb->ram.size <= 32 * 1024 * 1024)
|
||||
if (pfb->ram->size <= 32 * 1024 * 1024)
|
||||
preferred_bpp = 8;
|
||||
else
|
||||
if (pfb->ram.size <= 64 * 1024 * 1024)
|
||||
if (pfb->ram->size <= 64 * 1024 * 1024)
|
||||
preferred_bpp = 16;
|
||||
else
|
||||
preferred_bpp = 32;
|
||||
|
|
|
@ -125,7 +125,7 @@ nv50_mem_timing_calc(struct drm_device *dev, u32 freq,
|
|||
t->reg[7] = 0x4000202 | (e->tCL - 1) << 16;
|
||||
|
||||
/* XXX: P.version == 1 only has DDR2 and GDDR3? */
|
||||
if (pfb->ram.type == NV_MEM_TYPE_DDR2) {
|
||||
if (pfb->ram->type == NV_MEM_TYPE_DDR2) {
|
||||
t->reg[5] |= (e->tCL + 3) << 8;
|
||||
t->reg[6] |= (t->tCWL - 2) << 8;
|
||||
t->reg[8] |= (e->tCL - 4);
|
||||
|
@ -428,7 +428,7 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq,
|
|||
break;
|
||||
}
|
||||
|
||||
switch (pfb->ram.type * !ret) {
|
||||
switch (pfb->ram->type * !ret) {
|
||||
case NV_MEM_TYPE_GDDR3:
|
||||
ret = nouveau_mem_gddr3_mr(dev, freq, e, len, boot, t);
|
||||
break;
|
||||
|
@ -455,7 +455,7 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq,
|
|||
else
|
||||
dll_off = !!(ramcfg[2] & 0x40);
|
||||
|
||||
switch (pfb->ram.type) {
|
||||
switch (pfb->ram->type) {
|
||||
case NV_MEM_TYPE_GDDR3:
|
||||
t->mr[1] &= ~0x00000040;
|
||||
t->mr[1] |= 0x00000040 * dll_off;
|
||||
|
@ -522,7 +522,7 @@ nouveau_mem_timing_read(struct drm_device *dev, struct nouveau_pm_memtiming *t)
|
|||
t->odt = 0;
|
||||
t->drive_strength = 0;
|
||||
|
||||
switch (pfb->ram.type) {
|
||||
switch (pfb->ram->type) {
|
||||
case NV_MEM_TYPE_DDR3:
|
||||
t->odt |= (t->mr[1] & 0x200) >> 7;
|
||||
case NV_MEM_TYPE_DDR2:
|
||||
|
@ -551,7 +551,7 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec,
|
|||
u32 mr[3] = { info->mr[0], info->mr[1], info->mr[2] };
|
||||
u32 mr1_dlloff;
|
||||
|
||||
switch (pfb->ram.type) {
|
||||
switch (pfb->ram->type) {
|
||||
case NV_MEM_TYPE_DDR2:
|
||||
tDLLK = 2000;
|
||||
mr1_dlloff = 0x00000001;
|
||||
|
@ -572,7 +572,7 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec,
|
|||
}
|
||||
|
||||
/* fetch current MRs */
|
||||
switch (pfb->ram.type) {
|
||||
switch (pfb->ram->type) {
|
||||
case NV_MEM_TYPE_GDDR3:
|
||||
case NV_MEM_TYPE_DDR3:
|
||||
mr[2] = exec->mrg(exec, 2);
|
||||
|
@ -639,7 +639,7 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec,
|
|||
exec->mrs (exec, 0, info->mr[0] | 0x00000000);
|
||||
exec->wait(exec, tMRD);
|
||||
exec->wait(exec, tDLLK);
|
||||
if (pfb->ram.type == NV_MEM_TYPE_GDDR3)
|
||||
if (pfb->ram->type == NV_MEM_TYPE_GDDR3)
|
||||
exec->precharge(exec);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man,
|
|||
struct nouveau_drm *drm = nouveau_bdev(man->bdev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(drm->device);
|
||||
nouveau_mem_node_cleanup(mem->mm_node);
|
||||
pfb->ram.put(pfb, (struct nouveau_mem **)&mem->mm_node);
|
||||
pfb->ram->put(pfb, (struct nouveau_mem **)&mem->mm_node);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -88,7 +88,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
|
|||
if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG)
|
||||
size_nc = 1 << nvbo->page_shift;
|
||||
|
||||
ret = pfb->ram.get(pfb, mem->num_pages << PAGE_SHIFT,
|
||||
ret = pfb->ram->get(pfb, mem->num_pages << PAGE_SHIFT,
|
||||
mem->page_alignment << PAGE_SHIFT, size_nc,
|
||||
(nvbo->tile_flags >> 8) & 0x3ff, &node);
|
||||
if (ret) {
|
||||
|
@ -386,7 +386,7 @@ nouveau_ttm_init(struct nouveau_drm *drm)
|
|||
}
|
||||
|
||||
/* VRAM init */
|
||||
drm->gem.vram_available = nouveau_fb(drm->device)->ram.size;
|
||||
drm->gem.vram_available = nouveau_fb(drm->device)->ram->size;
|
||||
drm->gem.vram_available -= nouveau_instmem(drm->device)->reserved;
|
||||
|
||||
ret = ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_VRAM,
|
||||
|
|
|
@ -159,7 +159,7 @@ nv50_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
|
|||
.flags = NV_DMA_TARGET_VRAM |
|
||||
NV_DMA_ACCESS_RDWR,
|
||||
.start = 0,
|
||||
.limit = pfb->ram.size - 1,
|
||||
.limit = pfb->ram->size - 1,
|
||||
.conf0 = NV50_DMA_CONF0_ENABLE |
|
||||
NV50_DMA_CONF0_PART_256,
|
||||
}, sizeof(struct nv_dma_class), &object);
|
||||
|
@ -172,7 +172,7 @@ nv50_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
|
|||
.flags = NV_DMA_TARGET_VRAM |
|
||||
NV_DMA_ACCESS_RDWR,
|
||||
.start = 0,
|
||||
.limit = pfb->ram.size - 1,
|
||||
.limit = pfb->ram->size - 1,
|
||||
.conf0 = NV50_DMA_CONF0_ENABLE | 0x70 |
|
||||
NV50_DMA_CONF0_PART_256,
|
||||
}, sizeof(struct nv_dma_class), &object);
|
||||
|
@ -185,7 +185,7 @@ nv50_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
|
|||
.flags = NV_DMA_TARGET_VRAM |
|
||||
NV_DMA_ACCESS_RDWR,
|
||||
.start = 0,
|
||||
.limit = pfb->ram.size - 1,
|
||||
.limit = pfb->ram->size - 1,
|
||||
.conf0 = NV50_DMA_CONF0_ENABLE | 0x7a |
|
||||
NV50_DMA_CONF0_PART_256,
|
||||
}, sizeof(struct nv_dma_class), &object);
|
||||
|
@ -204,7 +204,7 @@ nvc0_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
|
|||
.flags = NV_DMA_TARGET_VRAM |
|
||||
NV_DMA_ACCESS_RDWR,
|
||||
.start = 0,
|
||||
.limit = pfb->ram.size - 1,
|
||||
.limit = pfb->ram->size - 1,
|
||||
.conf0 = NVC0_DMA_CONF0_ENABLE,
|
||||
}, sizeof(struct nv_dma_class), &object);
|
||||
if (ret)
|
||||
|
@ -216,7 +216,7 @@ nvc0_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
|
|||
.flags = NV_DMA_TARGET_VRAM |
|
||||
NV_DMA_ACCESS_RDWR,
|
||||
.start = 0,
|
||||
.limit = pfb->ram.size - 1,
|
||||
.limit = pfb->ram->size - 1,
|
||||
.conf0 = NVC0_DMA_CONF0_ENABLE | 0xfe,
|
||||
}, sizeof(struct nv_dma_class), &object);
|
||||
if (ret)
|
||||
|
@ -228,7 +228,7 @@ nvc0_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
|
|||
.flags = NV_DMA_TARGET_VRAM |
|
||||
NV_DMA_ACCESS_RDWR,
|
||||
.start = 0,
|
||||
.limit = pfb->ram.size - 1,
|
||||
.limit = pfb->ram->size - 1,
|
||||
.conf0 = NVC0_DMA_CONF0_ENABLE | 0xfe,
|
||||
}, sizeof(struct nv_dma_class), &object);
|
||||
return ret;
|
||||
|
@ -246,7 +246,7 @@ nvd0_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
|
|||
.flags = NV_DMA_TARGET_VRAM |
|
||||
NV_DMA_ACCESS_RDWR,
|
||||
.start = 0,
|
||||
.limit = pfb->ram.size - 1,
|
||||
.limit = pfb->ram->size - 1,
|
||||
.conf0 = NVD0_DMA_CONF0_ENABLE |
|
||||
NVD0_DMA_CONF0_PAGE_LP,
|
||||
}, sizeof(struct nv_dma_class), &object);
|
||||
|
@ -259,7 +259,7 @@ nvd0_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
|
|||
.flags = NV_DMA_TARGET_VRAM |
|
||||
NV_DMA_ACCESS_RDWR,
|
||||
.start = 0,
|
||||
.limit = pfb->ram.size - 1,
|
||||
.limit = pfb->ram->size - 1,
|
||||
.conf0 = NVD0_DMA_CONF0_ENABLE | 0xfe |
|
||||
NVD0_DMA_CONF0_PAGE_LP,
|
||||
}, sizeof(struct nv_dma_class), &object);
|
||||
|
@ -316,7 +316,7 @@ nv50_dmac_create(struct nouveau_object *core, u32 bclass, u8 head,
|
|||
.flags = NV_DMA_TARGET_VRAM |
|
||||
NV_DMA_ACCESS_RDWR,
|
||||
.start = 0,
|
||||
.limit = pfb->ram.size - 1,
|
||||
.limit = pfb->ram->size - 1,
|
||||
}, sizeof(struct nv_dma_class), &object);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -493,12 +493,12 @@ mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data)
|
|||
struct hwsq_ucode *hwsq = &info->mclk_hwsq;
|
||||
|
||||
if (mr <= 1) {
|
||||
if (pfb->ram.ranks > 1)
|
||||
if (pfb->ram->ranks > 1)
|
||||
hwsq_wr32(hwsq, 0x1002c8 + ((mr - 0) * 4), data);
|
||||
hwsq_wr32(hwsq, 0x1002c0 + ((mr - 0) * 4), data);
|
||||
} else
|
||||
if (mr <= 3) {
|
||||
if (pfb->ram.ranks > 1)
|
||||
if (pfb->ram->ranks > 1)
|
||||
hwsq_wr32(hwsq, 0x1002e8 + ((mr - 2) * 4), data);
|
||||
hwsq_wr32(hwsq, 0x1002e0 + ((mr - 2) * 4), data);
|
||||
}
|
||||
|
|
|
@ -389,12 +389,12 @@ mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data)
|
|||
struct nouveau_device *device = nouveau_dev(exec->dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(device);
|
||||
if (mr <= 1) {
|
||||
if (pfb->ram.ranks > 1)
|
||||
if (pfb->ram->ranks > 1)
|
||||
nv_wr32(device, 0x1002c8 + ((mr - 0) * 4), data);
|
||||
nv_wr32(device, 0x1002c0 + ((mr - 0) * 4), data);
|
||||
} else
|
||||
if (mr <= 3) {
|
||||
if (pfb->ram.ranks > 1)
|
||||
if (pfb->ram->ranks > 1)
|
||||
nv_wr32(device, 0x1002e8 + ((mr - 2) * 4), data);
|
||||
nv_wr32(device, 0x1002e0 + ((mr - 2) * 4), data);
|
||||
}
|
||||
|
|
|
@ -477,7 +477,7 @@ mclk_mrg(struct nouveau_mem_exec_func *exec, int mr)
|
|||
{
|
||||
struct nouveau_device *device = nouveau_dev(exec->dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(device);
|
||||
if (pfb->ram.type != NV_MEM_TYPE_GDDR5) {
|
||||
if (pfb->ram->type != NV_MEM_TYPE_GDDR5) {
|
||||
if (mr <= 1)
|
||||
return nv_rd32(device, 0x10f300 + ((mr - 0) * 4));
|
||||
return nv_rd32(device, 0x10f320 + ((mr - 2) * 4));
|
||||
|
@ -496,15 +496,15 @@ mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data)
|
|||
{
|
||||
struct nouveau_device *device = nouveau_dev(exec->dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(device);
|
||||
if (pfb->ram.type != NV_MEM_TYPE_GDDR5) {
|
||||
if (pfb->ram->type != NV_MEM_TYPE_GDDR5) {
|
||||
if (mr <= 1) {
|
||||
nv_wr32(device, 0x10f300 + ((mr - 0) * 4), data);
|
||||
if (pfb->ram.ranks > 1)
|
||||
if (pfb->ram->ranks > 1)
|
||||
nv_wr32(device, 0x10f308 + ((mr - 0) * 4), data);
|
||||
} else
|
||||
if (mr <= 3) {
|
||||
nv_wr32(device, 0x10f320 + ((mr - 2) * 4), data);
|
||||
if (pfb->ram.ranks > 1)
|
||||
if (pfb->ram->ranks > 1)
|
||||
nv_wr32(device, 0x10f328 + ((mr - 2) * 4), data);
|
||||
}
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue