drm/nouveau/fb: merge fb/vram and port to subdev interfaces
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Родитель
0134a97979
Коммит
861d21074b
|
@ -8,6 +8,7 @@ ccflags-y += -I$(src)
|
|||
|
||||
nouveau-y := core/core/client.o
|
||||
nouveau-y += core/core/engine.o
|
||||
nouveau-y += core/core/enum.o
|
||||
nouveau-y += core/core/handle.o
|
||||
nouveau-y += core/core/mm.o
|
||||
nouveau-y += core/core/namedb.o
|
||||
|
@ -50,6 +51,7 @@ nouveau-y += core/subdev/devinit/nv10.o
|
|||
nouveau-y += core/subdev/devinit/nv1a.o
|
||||
nouveau-y += core/subdev/devinit/nv20.o
|
||||
nouveau-y += core/subdev/devinit/nv50.o
|
||||
nouveau-y += core/subdev/fb/base.o
|
||||
nouveau-y += core/subdev/fb/nv04.o
|
||||
nouveau-y += core/subdev/fb/nv10.o
|
||||
nouveau-y += core/subdev/fb/nv20.o
|
||||
|
@ -57,8 +59,6 @@ nouveau-y += core/subdev/fb/nv30.o
|
|||
nouveau-y += core/subdev/fb/nv40.o
|
||||
nouveau-y += core/subdev/fb/nv50.o
|
||||
nouveau-y += core/subdev/fb/nvc0.o
|
||||
nouveau-y += core/subdev/fb/nv50_vram.o
|
||||
nouveau-y += core/subdev/fb/nvc0_vram.o
|
||||
nouveau-y += core/subdev/gpio/base.o
|
||||
nouveau-y += core/subdev/gpio/nv10.o
|
||||
nouveau-y += core/subdev/gpio/nv50.o
|
||||
|
@ -69,6 +69,7 @@ nouveau-y += core/subdev/i2c/bit.o
|
|||
nouveau-y += core/subdev/instmem/nv04.o
|
||||
nouveau-y += core/subdev/instmem/nv50.o
|
||||
nouveau-y += core/subdev/instmem/nvc0.o
|
||||
nouveau-y += core/subdev/ltcg/nvc0.o
|
||||
nouveau-y += core/subdev/mc/base.o
|
||||
nouveau-y += core/subdev/mc/nv04.o
|
||||
nouveau-y += core/subdev/mc/nv44.o
|
||||
|
|
|
@ -163,7 +163,7 @@ nv40_fifo_init(struct drm_device *dev, int engine)
|
|||
break;
|
||||
default:
|
||||
nv_wr32(dev, 0x002230, 0x00000000);
|
||||
nv_wr32(dev, 0x002220, ((dev_priv->vram_size - 512 * 1024 +
|
||||
nv_wr32(dev, 0x002220, ((nvfb_vram_size(dev) - 512 * 1024 +
|
||||
dev_priv->ramfc->pinst) >> 16) |
|
||||
0x00030000);
|
||||
break;
|
||||
|
|
|
@ -895,9 +895,7 @@ nv10_graph_context_del(struct nouveau_channel *chan, int engine)
|
|||
static void
|
||||
nv10_graph_set_tile_region(struct drm_device *dev, int i)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
|
||||
|
||||
struct nouveau_fb_tile *tile = nvfb_tile(dev, i);
|
||||
nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), tile->limit);
|
||||
nv_wr32(dev, NV10_PGRAPH_TSIZE(i), tile->pitch);
|
||||
nv_wr32(dev, NV10_PGRAPH_TILE(i), tile->addr);
|
||||
|
|
|
@ -472,7 +472,7 @@ static void
|
|||
nv20_graph_set_tile_region(struct drm_device *dev, int i)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
|
||||
struct nouveau_fb_tile *tile = nvfb_tile(dev, i);
|
||||
|
||||
nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit);
|
||||
nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch);
|
||||
|
|
|
@ -125,7 +125,7 @@ static void
|
|||
nv40_graph_set_tile_region(struct drm_device *dev, int i)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
|
||||
struct nouveau_fb_tile *tile = nvfb_tile(dev, i);
|
||||
|
||||
switch (dev_priv->chipset) {
|
||||
case 0x40:
|
||||
|
@ -178,7 +178,6 @@ nv40_graph_init(struct drm_device *dev, int engine)
|
|||
{
|
||||
struct nv40_graph_engine *pgraph = nv_engine(dev, engine);
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
uint32_t vramsz;
|
||||
int i, j;
|
||||
|
||||
|
@ -280,7 +279,7 @@ nv40_graph_init(struct drm_device *dev, int engine)
|
|||
}
|
||||
|
||||
/* Turn all the tiling regions off. */
|
||||
for (i = 0; i < pfb->num_tiles; i++)
|
||||
for (i = 0; i < nvfb_tile_nr(dev); i++)
|
||||
nv40_graph_set_tile_region(dev, i);
|
||||
|
||||
/* begin RAM config */
|
||||
|
|
|
@ -128,7 +128,6 @@ nv31_mpeg_object_new(struct nouveau_channel *chan, int engine,
|
|||
static int
|
||||
nv31_mpeg_init(struct drm_device *dev, int engine)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine);
|
||||
int i;
|
||||
|
||||
|
@ -138,7 +137,7 @@ nv31_mpeg_init(struct drm_device *dev, int engine)
|
|||
nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
|
||||
nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
|
||||
|
||||
for (i = 0; i < dev_priv->engine.fb.num_tiles; i++)
|
||||
for (i = 0; i < nvfb_tile_nr(dev); i++)
|
||||
pmpeg->base.set_tile_region(dev, i);
|
||||
|
||||
/* PMPEG init */
|
||||
|
@ -235,9 +234,7 @@ nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst)
|
|||
static void
|
||||
nv31_vpe_set_tile_region(struct drm_device *dev, int i)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
|
||||
|
||||
struct nouveau_fb_tile *tile = nvfb_tile(dev, i);
|
||||
nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch);
|
||||
nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit);
|
||||
nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr);
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
#ifndef __NOUVEAU_FB_H__
|
||||
#define __NOUVEAU_FB_H__
|
||||
|
||||
#ifndef XXX_THIS_IS_A_HACK
|
||||
#include <core/subdev.h>
|
||||
#include <core/device.h>
|
||||
#endif
|
||||
#include <core/mm.h>
|
||||
#include <subdev/vm.h>
|
||||
|
||||
/* memory type/access flags, do not match hardware values */
|
||||
#define NV_MEM_ACCESS_RO 1
|
||||
#define NV_MEM_ACCESS_WO 2
|
||||
#define NV_MEM_ACCESS_RW (NV_MEM_ACCESS_RO | NV_MEM_ACCESS_WO)
|
||||
#define NV_MEM_ACCESS_SYS 4
|
||||
#define NV_MEM_ACCESS_VM 8
|
||||
#define NV_MEM_ACCESS_NOSNOOP 16
|
||||
|
||||
#define NV_MEM_TARGET_VRAM 0
|
||||
#define NV_MEM_TARGET_PCI 1
|
||||
#define NV_MEM_TARGET_PCI_NOSNOOP 2
|
||||
#define NV_MEM_TARGET_VM 3
|
||||
#define NV_MEM_TARGET_GART 4
|
||||
|
||||
#define NV_MEM_TYPE_VM 0x7f
|
||||
#define NV_MEM_COMP_VM 0x03
|
||||
|
||||
struct nouveau_mem {
|
||||
struct drm_device *dev;
|
||||
|
||||
struct nouveau_vma bar_vma;
|
||||
struct nouveau_vma vma[2];
|
||||
u8 page_shift;
|
||||
|
||||
struct nouveau_mm_node *tag;
|
||||
struct list_head regions;
|
||||
dma_addr_t *pages;
|
||||
u32 memtype;
|
||||
u64 offset;
|
||||
u64 size;
|
||||
struct sg_table *sg;
|
||||
};
|
||||
|
||||
struct nouveau_fb_tile {
|
||||
struct nouveau_mm_node *tag;
|
||||
u32 addr;
|
||||
u32 limit;
|
||||
u32 pitch;
|
||||
u32 zcomp;
|
||||
};
|
||||
|
||||
#ifndef XXX_THIS_IS_A_HACK
|
||||
struct nouveau_fb {
|
||||
struct nouveau_subdev base;
|
||||
|
||||
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 (*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_mm vram;
|
||||
struct nouveau_mm tags;
|
||||
|
||||
struct {
|
||||
struct nouveau_fb_tile region[16];
|
||||
int regions;
|
||||
void (*init)(struct nouveau_fb *, int i, u32 addr, u32 size,
|
||||
u32 pitch, u32 flags, struct nouveau_fb_tile *);
|
||||
void (*fini)(struct nouveau_fb *, int i,
|
||||
struct nouveau_fb_tile *);
|
||||
void (*prog)(struct nouveau_fb *, int i,
|
||||
struct nouveau_fb_tile *);
|
||||
} tile;
|
||||
};
|
||||
|
||||
static inline struct nouveau_fb *
|
||||
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_created(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 nv20_fb_oclass;
|
||||
extern struct nouveau_oclass nv30_fb_oclass;
|
||||
extern struct nouveau_oclass nv40_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 *);
|
||||
|
||||
bool nv04_fb_memtype_valid(struct nouveau_fb *, u32 memtype);
|
||||
|
||||
void nv10_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
|
||||
|
||||
void nv30_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
|
||||
u32 pitch, u32 flags, struct nouveau_fb_tile *);
|
||||
void nv30_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *);
|
||||
|
||||
void nv50_fb_vram_del(struct nouveau_fb *, struct nouveau_mem **);
|
||||
void nv50_fb_trap(struct nouveau_fb *, int display);
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef __NOUVEAU_LTCG_H__
|
||||
#define __NOUVEAU_LTCG_H__
|
||||
|
||||
#include <core/subdev.h>
|
||||
#include <core/device.h>
|
||||
|
||||
struct nouveau_ltcg {
|
||||
struct nouveau_subdev base;
|
||||
};
|
||||
|
||||
static inline struct nouveau_ltcg *
|
||||
nouveau_ltcg(void *obj)
|
||||
{
|
||||
return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_LTCG];
|
||||
}
|
||||
|
||||
#define nouveau_ltcg_create(p,e,o,d) \
|
||||
nouveau_subdev_create_((p), (e), (o), 0, "PLTCG", "level2", \
|
||||
sizeof(**d), (void **)d)
|
||||
#define nouveau_ltcg_destroy(p) \
|
||||
nouveau_subdev_destroy(&(p)->base)
|
||||
#define nouveau_ltcg_init(p) \
|
||||
nouveau_subdev_init(&(p)->base)
|
||||
#define nouveau_ltcg_fini(p,s) \
|
||||
nouveau_subdev_fini(&(p)->base, (s))
|
||||
|
||||
#define _nouveau_ltcg_dtor _nouveau_subdev_dtor
|
||||
#define _nouveau_ltcg_init _nouveau_subdev_init
|
||||
#define _nouveau_ltcg_fini _nouveau_subdev_fini
|
||||
|
||||
extern struct nouveau_oclass nvc0_ltcg_oclass;
|
||||
|
||||
#endif
|
|
@ -25,11 +25,10 @@
|
|||
#ifndef __NOUVEAU_VM_H__
|
||||
#define __NOUVEAU_VM_H__
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
#include "nouveau_drv.h"
|
||||
#include <core/mm.h>
|
||||
|
||||
struct nouveau_mem;
|
||||
|
||||
struct nouveau_vm_pgt {
|
||||
struct nouveau_gpuobj *obj[2];
|
||||
u32 refcount[2];
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <subdev/devinit.h>
|
||||
#include <subdev/mc.h>
|
||||
#include <subdev/timer.h>
|
||||
#include <subdev/fb.h>
|
||||
|
||||
int
|
||||
nv04_identify(struct nouveau_device *device)
|
||||
|
@ -41,6 +42,7 @@ nv04_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass;
|
||||
break;
|
||||
case 0x05:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -49,6 +51,7 @@ nv04_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass;
|
||||
break;
|
||||
default:
|
||||
nv_fatal(device, "unknown RIVA chipset\n");
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <subdev/devinit.h>
|
||||
#include <subdev/mc.h>
|
||||
#include <subdev/timer.h>
|
||||
#include <subdev/fb.h>
|
||||
|
||||
int
|
||||
nv10_identify(struct nouveau_device *device)
|
||||
|
@ -43,6 +44,7 @@ nv10_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
|
||||
break;
|
||||
case 0x15:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -52,6 +54,7 @@ nv10_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
|
||||
break;
|
||||
case 0x16:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -61,6 +64,7 @@ nv10_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
|
||||
break;
|
||||
case 0x1a:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -70,6 +74,7 @@ nv10_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
|
||||
break;
|
||||
case 0x11:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -79,6 +84,7 @@ nv10_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
|
||||
break;
|
||||
case 0x17:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -88,6 +94,7 @@ nv10_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
|
||||
break;
|
||||
case 0x1f:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -97,6 +104,7 @@ nv10_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
|
||||
break;
|
||||
case 0x18:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -106,6 +114,7 @@ nv10_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
|
||||
break;
|
||||
default:
|
||||
nv_fatal(device, "unknown Celsius chipset\n");
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <subdev/devinit.h>
|
||||
#include <subdev/mc.h>
|
||||
#include <subdev/timer.h>
|
||||
#include <subdev/fb.h>
|
||||
|
||||
int
|
||||
nv20_identify(struct nouveau_device *device)
|
||||
|
@ -43,6 +44,7 @@ nv20_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass;
|
||||
break;
|
||||
case 0x25:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -52,6 +54,7 @@ nv20_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass;
|
||||
break;
|
||||
case 0x28:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -61,6 +64,7 @@ nv20_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass;
|
||||
break;
|
||||
case 0x2a:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -70,6 +74,7 @@ nv20_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass;
|
||||
break;
|
||||
default:
|
||||
nv_fatal(device, "unknown Kelvin chipset\n");
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <subdev/devinit.h>
|
||||
#include <subdev/mc.h>
|
||||
#include <subdev/timer.h>
|
||||
#include <subdev/fb.h>
|
||||
|
||||
int
|
||||
nv30_identify(struct nouveau_device *device)
|
||||
|
@ -43,6 +44,7 @@ nv30_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass;
|
||||
break;
|
||||
case 0x35:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -52,6 +54,7 @@ nv30_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass;
|
||||
break;
|
||||
case 0x31:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -61,6 +64,7 @@ nv30_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass;
|
||||
break;
|
||||
case 0x36:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -70,6 +74,7 @@ nv30_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass;
|
||||
break;
|
||||
case 0x34:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -79,6 +84,7 @@ nv30_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass;
|
||||
break;
|
||||
default:
|
||||
nv_fatal(device, "unknown Rankine chipset\n");
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <subdev/devinit.h>
|
||||
#include <subdev/mc.h>
|
||||
#include <subdev/timer.h>
|
||||
#include <subdev/fb.h>
|
||||
|
||||
int
|
||||
nv40_identify(struct nouveau_device *device)
|
||||
|
@ -43,6 +44,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x41:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -52,6 +54,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x42:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -61,6 +64,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x43:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -70,6 +74,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x45:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -79,6 +84,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x47:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -88,6 +94,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x49:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -97,6 +104,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x4b:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -106,6 +114,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x44:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -115,6 +124,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x46:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -124,6 +134,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x4a:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -133,6 +144,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x4c:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -142,6 +154,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x4e:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -151,6 +164,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x63:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -160,6 +174,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x67:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -169,6 +184,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
case 0x68:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -178,6 +194,7 @@ nv40_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
|
||||
break;
|
||||
default:
|
||||
nv_fatal(device, "unknown Curie chipset\n");
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <subdev/devinit.h>
|
||||
#include <subdev/mc.h>
|
||||
#include <subdev/timer.h>
|
||||
#include <subdev/fb.h>
|
||||
|
||||
int
|
||||
nv50_identify(struct nouveau_device *device)
|
||||
|
@ -43,6 +44,7 @@ nv50_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
|
||||
break;
|
||||
case 0x84:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -52,6 +54,7 @@ nv50_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
|
||||
break;
|
||||
case 0x86:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -61,6 +64,7 @@ nv50_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
|
||||
break;
|
||||
case 0x92:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -70,6 +74,7 @@ nv50_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
|
||||
break;
|
||||
case 0x94:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -79,6 +84,7 @@ nv50_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
|
||||
break;
|
||||
case 0x96:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -88,6 +94,7 @@ nv50_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
|
||||
break;
|
||||
case 0x98:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -97,6 +104,7 @@ nv50_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
|
||||
break;
|
||||
case 0xa0:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -106,6 +114,7 @@ nv50_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
|
||||
break;
|
||||
case 0xaa:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -115,6 +124,7 @@ nv50_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
|
||||
break;
|
||||
case 0xac:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -124,6 +134,7 @@ nv50_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
|
||||
break;
|
||||
case 0xa3:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -133,6 +144,7 @@ nv50_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
|
||||
break;
|
||||
case 0xa5:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -142,6 +154,7 @@ nv50_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
|
||||
break;
|
||||
case 0xa8:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -151,6 +164,7 @@ nv50_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
|
||||
break;
|
||||
case 0xaf:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -160,6 +174,7 @@ nv50_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
|
||||
break;
|
||||
default:
|
||||
nv_fatal(device, "unknown Tesla chipset\n");
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include <subdev/devinit.h>
|
||||
#include <subdev/mc.h>
|
||||
#include <subdev/timer.h>
|
||||
#include <subdev/fb.h>
|
||||
#include <subdev/ltcg.h>
|
||||
|
||||
int
|
||||
nvc0_identify(struct nouveau_device *device)
|
||||
|
@ -43,6 +45,8 @@ nvc0_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
|
||||
break;
|
||||
case 0xc4:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -52,6 +56,8 @@ nvc0_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
|
||||
break;
|
||||
case 0xc3:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -61,6 +67,8 @@ nvc0_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
|
||||
break;
|
||||
case 0xce:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -70,6 +78,8 @@ nvc0_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
|
||||
break;
|
||||
case 0xcf:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -79,6 +89,8 @@ nvc0_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
|
||||
break;
|
||||
case 0xc1:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -88,6 +100,8 @@ nvc0_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
|
||||
break;
|
||||
case 0xc8:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -97,6 +111,8 @@ nvc0_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
|
||||
break;
|
||||
case 0xd9:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -106,6 +122,8 @@ nvc0_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
|
||||
break;
|
||||
default:
|
||||
nv_fatal(device, "unknown Fermi chipset\n");
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include <subdev/devinit.h>
|
||||
#include <subdev/mc.h>
|
||||
#include <subdev/timer.h>
|
||||
#include <subdev/fb.h>
|
||||
#include <subdev/ltcg.h>
|
||||
|
||||
int
|
||||
nve0_identify(struct nouveau_device *device)
|
||||
|
@ -43,6 +45,8 @@ nve0_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
|
||||
break;
|
||||
case 0xe7:
|
||||
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
|
||||
|
@ -52,6 +56,8 @@ nve0_identify(struct nouveau_device *device)
|
|||
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
|
||||
break;
|
||||
default:
|
||||
nv_fatal(device, "unknown Kepler chipset\n");
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright 2012 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Ben Skeggs
|
||||
*/
|
||||
|
||||
#include "subdev/fb.h"
|
||||
#include "subdev/bios.h"
|
||||
#include "subdev/bios/bit.h"
|
||||
|
||||
int
|
||||
nouveau_fb_bios_memtype(struct nouveau_bios *bios)
|
||||
{
|
||||
struct bit_entry M;
|
||||
u8 ramcfg;
|
||||
|
||||
ramcfg = (nv_rd32(bios, 0x101000) & 0x0000003c) >> 2;
|
||||
if (!bit_entry(bios, 'M', &M) && M.version == 2 && M.length >= 5) {
|
||||
u16 table = nv_ro16(bios, M.offset + 3);
|
||||
u8 version = nv_ro08(bios, table + 0);
|
||||
u8 header = nv_ro08(bios, table + 1);
|
||||
u8 record = nv_ro08(bios, table + 2);
|
||||
u8 entries = nv_ro08(bios, table + 3);
|
||||
if (table && version == 0x10 && ramcfg < entries) {
|
||||
u16 entry = table + header + (ramcfg * record);
|
||||
switch (nv_ro08(bios, entry) & 0x0f) {
|
||||
case 0: return NV_MEM_TYPE_DDR2;
|
||||
case 1: return NV_MEM_TYPE_DDR3;
|
||||
case 2: return NV_MEM_TYPE_GDDR3;
|
||||
case 3: return NV_MEM_TYPE_GDDR5;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return NV_MEM_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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]);
|
||||
|
||||
if (pfb->tags.block_size)
|
||||
nouveau_mm_fini(&pfb->tags);
|
||||
|
||||
if (pfb->vram.block_size)
|
||||
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_created(struct nouveau_fb *pfb)
|
||||
{
|
||||
static const char *name[] = {
|
||||
[NV_MEM_TYPE_UNKNOWN] = "unknown",
|
||||
[NV_MEM_TYPE_STOLEN ] = "stolen system memory",
|
||||
[NV_MEM_TYPE_SGRAM ] = "SGRAM",
|
||||
[NV_MEM_TYPE_SDRAM ] = "SDRAM",
|
||||
[NV_MEM_TYPE_DDR1 ] = "DDR1",
|
||||
[NV_MEM_TYPE_DDR2 ] = "DDR2",
|
||||
[NV_MEM_TYPE_DDR3 ] = "DDR3",
|
||||
[NV_MEM_TYPE_GDDR2 ] = "GDDR2",
|
||||
[NV_MEM_TYPE_GDDR3 ] = "GDDR3",
|
||||
[NV_MEM_TYPE_GDDR4 ] = "GDDR4",
|
||||
[NV_MEM_TYPE_GDDR5 ] = "GDDR5",
|
||||
};
|
||||
|
||||
if (pfb->ram.size == 0) {
|
||||
nv_fatal(pfb, "no vram detected!!\n");
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
nv_info(pfb, "RAM type: %s\n", name[pfb->ram.type]);
|
||||
nv_info(pfb, "RAM size: %d MiB\n", (int)(pfb->ram.size >> 20));
|
||||
return 0;
|
||||
}
|
|
@ -1,55 +1,130 @@
|
|||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include <nouveau_drm.h>
|
||||
/*
|
||||
* Copyright 2012 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Ben Skeggs
|
||||
*/
|
||||
|
||||
int
|
||||
nv04_fb_vram_init(struct drm_device *dev)
|
||||
#include <subdev/fb.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 {
|
||||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
bool
|
||||
nv04_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
u32 boot0 = nv_rd32(dev, NV04_PFB_BOOT_0);
|
||||
if (!(tile_flags & 0xff00))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
nv04_fb_init(struct nouveau_object *object)
|
||||
{
|
||||
struct nv04_fb_priv *priv = (void *)object;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_init(&priv->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows
|
||||
* nvidia reading PFB_CFG_0, then writing back its original value.
|
||||
* (which was 0x701114 in this case)
|
||||
*/
|
||||
nv_wr32(priv, NV04_PFB_CFG0, 0x1114);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nv04_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nv04_fb_priv *priv;
|
||||
u32 boot0;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
boot0 = nv_rd32(priv, NV04_PFB_BOOT_0);
|
||||
if (boot0 & 0x00000100) {
|
||||
dev_priv->vram_size = ((boot0 >> 12) & 0xf) * 2 + 2;
|
||||
dev_priv->vram_size *= 1024 * 1024;
|
||||
priv->base.ram.size = ((boot0 >> 12) & 0xf) * 2 + 2;
|
||||
priv->base.ram.size *= 1024 * 1024;
|
||||
} else {
|
||||
switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) {
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB:
|
||||
dev_priv->vram_size = 32 * 1024 * 1024;
|
||||
priv->base.ram.size = 32 * 1024 * 1024;
|
||||
break;
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB:
|
||||
dev_priv->vram_size = 16 * 1024 * 1024;
|
||||
priv->base.ram.size = 16 * 1024 * 1024;
|
||||
break;
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB:
|
||||
dev_priv->vram_size = 8 * 1024 * 1024;
|
||||
priv->base.ram.size = 8 * 1024 * 1024;
|
||||
break;
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB:
|
||||
dev_priv->vram_size = 4 * 1024 * 1024;
|
||||
priv->base.ram.size = 4 * 1024 * 1024;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((boot0 & 0x00000038) <= 0x10)
|
||||
dev_priv->vram_type = NV_MEM_TYPE_SGRAM;
|
||||
priv->base.ram.type = NV_MEM_TYPE_SGRAM;
|
||||
else
|
||||
dev_priv->vram_type = NV_MEM_TYPE_SDRAM;
|
||||
priv->base.ram.type = NV_MEM_TYPE_SDRAM;
|
||||
|
||||
return 0;
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
}
|
||||
|
||||
int
|
||||
nv04_fb_init(struct drm_device *dev)
|
||||
{
|
||||
/* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows
|
||||
* nvidia reading PFB_CFG_0, then writing back its original value.
|
||||
* (which was 0x701114 in this case)
|
||||
*/
|
||||
|
||||
nv_wr32(dev, NV04_PFB_CFG0, 0x1114);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv04_fb_takedown(struct drm_device *dev)
|
||||
{
|
||||
}
|
||||
struct nouveau_oclass
|
||||
nv04_fb_oclass = {
|
||||
.handle = NV_SUBDEV(FB, 0x04),
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv04_fb_ctor,
|
||||
.dtor = _nouveau_fb_dtor,
|
||||
.init = nv04_fb_init,
|
||||
.fini = _nouveau_fb_fini,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,104 +1,120 @@
|
|||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include <nouveau_drm.h>
|
||||
/*
|
||||
* Copyright (C) 2010 Francisco Jerez.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
|
||||
uint32_t size, uint32_t pitch, uint32_t flags)
|
||||
#include <subdev/fb.h>
|
||||
|
||||
struct nv10_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
static void
|
||||
nv10_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
|
||||
u32 flags, struct nouveau_fb_tile *tile)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
|
||||
|
||||
tile->addr = 0x80000000 | addr;
|
||||
tile->limit = max(1u, addr + size) - 1;
|
||||
tile->pitch = pitch;
|
||||
}
|
||||
|
||||
void
|
||||
nv10_fb_free_tile_region(struct drm_device *dev, int i)
|
||||
static void
|
||||
nv10_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
|
||||
|
||||
tile->addr = tile->limit = tile->pitch = tile->zcomp = 0;
|
||||
tile->addr = 0;
|
||||
tile->limit = 0;
|
||||
tile->pitch = 0;
|
||||
tile->zcomp = 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv10_fb_set_tile_region(struct drm_device *dev, int i)
|
||||
nv10_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
|
||||
|
||||
nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit);
|
||||
nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch);
|
||||
nv_wr32(dev, NV10_PFB_TILE(i), tile->addr);
|
||||
nv_wr32(pfb, 0x100244 + (i * 0x10), tile->limit);
|
||||
nv_wr32(pfb, 0x100248 + (i * 0x10), tile->pitch);
|
||||
nv_wr32(pfb, 0x100240 + (i * 0x10), tile->addr);
|
||||
}
|
||||
|
||||
int
|
||||
nv1a_fb_vram_init(struct drm_device *dev)
|
||||
static int
|
||||
nv10_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct pci_dev *bridge;
|
||||
uint32_t mem, mib;
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nv10_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
|
||||
if (!bridge) {
|
||||
NV_ERROR(dev, "no bridge device\n");
|
||||
return 0;
|
||||
}
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (dev_priv->chipset == 0x1a) {
|
||||
pci_read_config_dword(bridge, 0x7c, &mem);
|
||||
mib = ((mem >> 6) & 31) + 1;
|
||||
if (device->chipset == 0x1a || device->chipset == 0x1f) {
|
||||
struct pci_dev *bridge;
|
||||
u32 mem, mib;
|
||||
|
||||
bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
|
||||
if (!bridge) {
|
||||
nv_fatal(device, "no bridge device\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (device->chipset == 0x1a) {
|
||||
pci_read_config_dword(bridge, 0x7c, &mem);
|
||||
mib = ((mem >> 6) & 31) + 1;
|
||||
} else {
|
||||
pci_read_config_dword(bridge, 0x84, &mem);
|
||||
mib = ((mem >> 4) & 127) + 1;
|
||||
}
|
||||
|
||||
priv->base.ram.type = NV_MEM_TYPE_STOLEN;
|
||||
priv->base.ram.size = mib * 1024 * 1024;
|
||||
} else {
|
||||
pci_read_config_dword(bridge, 0x84, &mem);
|
||||
mib = ((mem >> 4) & 127) + 1;
|
||||
u32 cfg0 = nv_rd32(priv, 0x100200);
|
||||
if (cfg0 & 0x00000001)
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR1;
|
||||
else
|
||||
priv->base.ram.type = NV_MEM_TYPE_SDRAM;
|
||||
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
}
|
||||
|
||||
dev_priv->vram_size = mib * 1024 * 1024;
|
||||
return 0;
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.tile.regions = 8;
|
||||
priv->base.tile.init = nv10_fb_tile_init;
|
||||
priv->base.tile.fini = nv10_fb_tile_fini;
|
||||
priv->base.tile.prog = nv10_fb_tile_prog;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
}
|
||||
|
||||
int
|
||||
nv10_fb_vram_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
u32 fifo_data = nv_rd32(dev, NV04_PFB_FIFO_DATA);
|
||||
u32 cfg0 = nv_rd32(dev, 0x100200);
|
||||
|
||||
dev_priv->vram_size = fifo_data & NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK;
|
||||
|
||||
if (cfg0 & 0x00000001)
|
||||
dev_priv->vram_type = NV_MEM_TYPE_DDR1;
|
||||
else
|
||||
dev_priv->vram_type = NV_MEM_TYPE_SDRAM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nv10_fb_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
int i;
|
||||
|
||||
/* Turn all the tiling regions off. */
|
||||
pfb->num_tiles = NV10_PFB_TILE__SIZE;
|
||||
for (i = 0; i < pfb->num_tiles; i++)
|
||||
pfb->set_tile_region(dev, i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv10_fb_takedown(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pfb->num_tiles; i++)
|
||||
pfb->free_tile_region(dev, i);
|
||||
}
|
||||
struct nouveau_oclass
|
||||
nv10_fb_oclass = {
|
||||
.handle = NV_SUBDEV(FB, 0x10),
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv10_fb_ctor,
|
||||
.dtor = _nouveau_fb_dtor,
|
||||
.init = _nouveau_fb_init,
|
||||
.fini = _nouveau_fb_fini,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,49 +1,41 @@
|
|||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include <nouveau_drm.h>
|
||||
/*
|
||||
* Copyright (C) 2010 Francisco Jerez.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
static struct drm_mm_node *
|
||||
nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
struct drm_mm_node *mem;
|
||||
int ret;
|
||||
#include <subdev/fb.h>
|
||||
|
||||
ret = drm_mm_pre_get(&pfb->tag_heap);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
spin_lock(&dev_priv->tile.lock);
|
||||
mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0);
|
||||
if (mem)
|
||||
mem = drm_mm_get_block_atomic(mem, size, 0);
|
||||
spin_unlock(&dev_priv->tile.lock);
|
||||
|
||||
return mem;
|
||||
}
|
||||
struct nv20_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
static void
|
||||
nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node **pmem)
|
||||
nv20_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
|
||||
u32 flags, struct nouveau_fb_tile *tile)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct drm_mm_node *mem = *pmem;
|
||||
if (mem) {
|
||||
spin_lock(&dev_priv->tile.lock);
|
||||
drm_mm_put_block(mem);
|
||||
spin_unlock(&dev_priv->tile.lock);
|
||||
*pmem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
|
||||
uint32_t size, uint32_t pitch, uint32_t flags)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
|
||||
int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16);
|
||||
struct nouveau_device *device = nv_device(pfb);
|
||||
int bpp = (flags & 2) ? 32 : 16;
|
||||
|
||||
tile->addr = 0x00000001 | addr;
|
||||
tile->limit = max(1u, addr + size) - 1;
|
||||
|
@ -53,20 +45,20 @@ nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
|
|||
* compression meta-data (most likely just a bitmap determining
|
||||
* if a given tile is compressed or not).
|
||||
*/
|
||||
if (flags & NOUVEAU_GEM_TILE_ZETA) {
|
||||
tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256);
|
||||
if (tile->tag_mem) {
|
||||
size /= 256;
|
||||
if (flags & 4) {
|
||||
if (!nouveau_mm_head(&pfb->tags, 1, size, size, 1, &tile->tag)) {
|
||||
/* Enable Z compression */
|
||||
tile->zcomp = tile->tag_mem->start;
|
||||
if (dev_priv->chipset >= 0x25) {
|
||||
tile->zcomp = tile->tag->offset;
|
||||
if (device->chipset >= 0x25) {
|
||||
if (bpp == 16)
|
||||
tile->zcomp |= NV25_PFB_ZCOMP_MODE_16;
|
||||
tile->zcomp |= 0x00100000;
|
||||
else
|
||||
tile->zcomp |= NV25_PFB_ZCOMP_MODE_32;
|
||||
tile->zcomp |= 0x00200000;
|
||||
} else {
|
||||
tile->zcomp |= NV20_PFB_ZCOMP_EN;
|
||||
tile->zcomp |= 0x80000000;
|
||||
if (bpp != 16)
|
||||
tile->zcomp |= NV20_PFB_ZCOMP_MODE_32;
|
||||
tile->zcomp |= 0x04000000;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,75 +66,71 @@ nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nv20_fb_free_tile_region(struct drm_device *dev, int i)
|
||||
static void
|
||||
nv20_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
|
||||
|
||||
tile->addr = tile->limit = tile->pitch = tile->zcomp = 0;
|
||||
nv20_fb_free_tag(dev, &tile->tag_mem);
|
||||
tile->addr = 0;
|
||||
tile->limit = 0;
|
||||
tile->pitch = 0;
|
||||
tile->zcomp = 0;
|
||||
nouveau_mm_free(&pfb->tags, &tile->tag);
|
||||
}
|
||||
|
||||
void
|
||||
nv20_fb_set_tile_region(struct drm_device *dev, int i)
|
||||
static void
|
||||
nv20_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
|
||||
|
||||
nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit);
|
||||
nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch);
|
||||
nv_wr32(dev, NV10_PFB_TILE(i), tile->addr);
|
||||
nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp);
|
||||
nv_wr32(pfb, 0x100244 + (i * 0x10), tile->limit);
|
||||
nv_wr32(pfb, 0x100248 + (i * 0x10), tile->pitch);
|
||||
nv_wr32(pfb, 0x100240 + (i * 0x10), tile->addr);
|
||||
nv_wr32(pfb, 0x100300 + (i * 0x04), tile->zcomp);
|
||||
}
|
||||
|
||||
int
|
||||
nv20_fb_vram_init(struct drm_device *dev)
|
||||
static int
|
||||
nv20_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
u32 mem_size = nv_rd32(dev, 0x10020c);
|
||||
u32 pbus1218 = nv_rd32(dev, 0x001218);
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nv20_fb_priv *priv;
|
||||
u32 pbus1218;
|
||||
int ret;
|
||||
|
||||
dev_priv->vram_size = mem_size & 0xff000000;
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pbus1218 = nv_rd32(priv, 0x001218);
|
||||
switch (pbus1218 & 0x00000300) {
|
||||
case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break;
|
||||
case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_GDDR2; break;
|
||||
case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
|
||||
case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break;
|
||||
}
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nv20_fb_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
int i;
|
||||
|
||||
if (dev_priv->chipset >= 0x25)
|
||||
drm_mm_init(&pfb->tag_heap, 0, 64 * 1024);
|
||||
if (device->chipset >= 0x25)
|
||||
ret = nouveau_mm_init(&priv->base.tags, 0, 64 * 1024, 1);
|
||||
else
|
||||
drm_mm_init(&pfb->tag_heap, 0, 32 * 1024);
|
||||
ret = nouveau_mm_init(&priv->base.tags, 0, 32 * 1024, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Turn all the tiling regions off. */
|
||||
pfb->num_tiles = NV10_PFB_TILE__SIZE;
|
||||
for (i = 0; i < pfb->num_tiles; i++)
|
||||
pfb->set_tile_region(dev, i);
|
||||
|
||||
return 0;
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.tile.regions = 8;
|
||||
priv->base.tile.init = nv20_fb_tile_init;
|
||||
priv->base.tile.fini = nv20_fb_tile_fini;
|
||||
priv->base.tile.prog = nv20_fb_tile_prog;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
}
|
||||
|
||||
void
|
||||
nv20_fb_takedown(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pfb->num_tiles; i++)
|
||||
pfb->free_tile_region(dev, i);
|
||||
|
||||
drm_mm_takedown(&pfb->tag_heap);
|
||||
}
|
||||
struct nouveau_oclass
|
||||
nv20_fb_oclass = {
|
||||
.handle = NV_SUBDEV(FB, 0x20),
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv20_fb_ctor,
|
||||
.dtor = _nouveau_fb_dtor,
|
||||
.init = _nouveau_fb_init,
|
||||
.fini = _nouveau_fb_fini,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -24,50 +24,47 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include <nouveau_drm.h>
|
||||
#include <subdev/fb.h>
|
||||
|
||||
struct nv30_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
void
|
||||
nv30_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
|
||||
uint32_t size, uint32_t pitch, uint32_t flags)
|
||||
nv30_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,
|
||||
u32 flags, struct nouveau_fb_tile *tile)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
|
||||
|
||||
tile->addr = addr | 1;
|
||||
tile->limit = max(1u, addr + size) - 1;
|
||||
tile->pitch = pitch;
|
||||
}
|
||||
|
||||
void
|
||||
nv30_fb_free_tile_region(struct drm_device *dev, int i)
|
||||
nv30_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
|
||||
|
||||
tile->addr = tile->limit = tile->pitch = 0;
|
||||
tile->addr = 0;
|
||||
tile->limit = 0;
|
||||
tile->pitch = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
calc_bias(struct drm_device *dev, int k, int i, int j)
|
||||
calc_bias(struct nv30_fb_priv *priv, int k, int i, int j)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int b = (dev_priv->chipset > 0x30 ?
|
||||
nv_rd32(dev, 0x122c + 0x10 * k + 0x4 * j) >> (4 * (i ^ 1)) :
|
||||
struct nouveau_device *device = nv_device(priv);
|
||||
int b = (device->chipset > 0x30 ?
|
||||
nv_rd32(priv, 0x122c + 0x10 * k + 0x4 * j) >> (4 * (i ^ 1)) :
|
||||
0) & 0xf;
|
||||
|
||||
return 2 * (b & 0x8 ? b - 0x10 : b);
|
||||
}
|
||||
|
||||
static int
|
||||
calc_ref(struct drm_device *dev, int l, int k, int i)
|
||||
calc_ref(struct nv30_fb_priv *priv, int l, int k, int i)
|
||||
{
|
||||
int j, x = 0;
|
||||
|
||||
for (j = 0; j < 4; j++) {
|
||||
int m = (l >> (8 * i) & 0xff) + calc_bias(dev, k, i, j);
|
||||
int m = (l >> (8 * i) & 0xff) + calc_bias(priv, k, i, j);
|
||||
|
||||
x |= (0x80 | clamp(m, 0, 0x1f)) << (8 * j);
|
||||
}
|
||||
|
@ -75,42 +72,77 @@ calc_ref(struct drm_device *dev, int l, int k, int i)
|
|||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
nv30_fb_init(struct drm_device *dev)
|
||||
static int
|
||||
nv30_fb_init(struct nouveau_object *object)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
int i, j;
|
||||
struct nouveau_device *device = nv_device(object);
|
||||
struct nv30_fb_priv *priv = (void *)object;
|
||||
int ret, i, j;
|
||||
|
||||
pfb->num_tiles = NV10_PFB_TILE__SIZE;
|
||||
|
||||
/* Turn all the tiling regions off. */
|
||||
for (i = 0; i < pfb->num_tiles; i++)
|
||||
pfb->set_tile_region(dev, i);
|
||||
ret = nouveau_fb_init(&priv->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Init the memory timing regs at 0x10037c/0x1003ac */
|
||||
if (dev_priv->chipset == 0x30 ||
|
||||
dev_priv->chipset == 0x31 ||
|
||||
dev_priv->chipset == 0x35) {
|
||||
if (device->chipset == 0x30 ||
|
||||
device->chipset == 0x31 ||
|
||||
device->chipset == 0x35) {
|
||||
/* Related to ROP count */
|
||||
int n = (dev_priv->chipset == 0x31 ? 2 : 4);
|
||||
int l = nv_rd32(dev, 0x1003d0);
|
||||
int n = (device->chipset == 0x31 ? 2 : 4);
|
||||
int l = nv_rd32(priv, 0x1003d0);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (j = 0; j < 3; j++)
|
||||
nv_wr32(dev, 0x10037c + 0xc * i + 0x4 * j,
|
||||
calc_ref(dev, l, 0, j));
|
||||
nv_wr32(priv, 0x10037c + 0xc * i + 0x4 * j,
|
||||
calc_ref(priv, l, 0, j));
|
||||
|
||||
for (j = 0; j < 2; j++)
|
||||
nv_wr32(dev, 0x1003ac + 0x8 * i + 0x4 * j,
|
||||
calc_ref(dev, l, 1, j));
|
||||
nv_wr32(priv, 0x1003ac + 0x8 * i + 0x4 * j,
|
||||
calc_ref(priv, l, 1, j));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv30_fb_takedown(struct drm_device *dev)
|
||||
static int
|
||||
nv30_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nv30_fb_priv *priv;
|
||||
u32 pbus1218;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pbus1218 = nv_rd32(priv, 0x001218);
|
||||
switch (pbus1218 & 0x00000300) {
|
||||
case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
|
||||
case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break;
|
||||
}
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
priv->base.tile.regions = 8;
|
||||
priv->base.tile.init = nv30_fb_tile_init;
|
||||
priv->base.tile.fini = nv30_fb_tile_fini;
|
||||
priv->base.tile.prog = nv10_fb_tile_prog;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
nv30_fb_oclass = {
|
||||
.handle = NV_SUBDEV(FB, 0x30),
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv30_fb_ctor,
|
||||
.dtor = _nouveau_fb_dtor,
|
||||
.init = nv30_fb_init,
|
||||
.fini = _nouveau_fb_fini,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,55 +1,83 @@
|
|||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include <nouveau_drm.h>
|
||||
/*
|
||||
* Copyright (C) 2010 Francisco Jerez.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
nv40_fb_set_tile_region(struct drm_device *dev, int i)
|
||||
#include <subdev/fb.h>
|
||||
|
||||
struct nv40_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
static inline int
|
||||
nv44_graph_class(struct nouveau_device *device)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
|
||||
if ((device->chipset & 0xf0) == 0x60)
|
||||
return 1;
|
||||
|
||||
switch (dev_priv->chipset) {
|
||||
case 0x40:
|
||||
nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit);
|
||||
nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch);
|
||||
nv_wr32(dev, NV10_PFB_TILE(i), tile->addr);
|
||||
break;
|
||||
|
||||
default:
|
||||
nv_wr32(dev, NV40_PFB_TLIMIT(i), tile->limit);
|
||||
nv_wr32(dev, NV40_PFB_TSIZE(i), tile->pitch);
|
||||
nv_wr32(dev, NV40_PFB_TILE(i), tile->addr);
|
||||
break;
|
||||
}
|
||||
return !(0x0baf & (1 << (device->chipset & 0x0f)));
|
||||
}
|
||||
|
||||
static void
|
||||
nv40_fb_init_gart(struct drm_device *dev)
|
||||
nv40_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma;
|
||||
nv_wr32(pfb, 0x100604 + (i * 0x10), tile->limit);
|
||||
nv_wr32(pfb, 0x100608 + (i * 0x10), tile->pitch);
|
||||
nv_wr32(pfb, 0x100600 + (i * 0x10), tile->addr);
|
||||
}
|
||||
|
||||
if (dev_priv->gart_info.type != NOUVEAU_GART_HW) {
|
||||
nv_wr32(dev, 0x100800, 0x00000001);
|
||||
static void
|
||||
nv40_fb_init_gart(struct nv40_fb_priv *priv)
|
||||
{
|
||||
#if 0
|
||||
struct nouveau_gpuobj *gart = ndev->gart_info.sg_ctxdma;
|
||||
|
||||
if (ndev->gart_info.type != NOUVEAU_GART_HW) {
|
||||
#endif
|
||||
nv_wr32(priv, 0x100800, 0x00000001);
|
||||
#if 0
|
||||
return;
|
||||
}
|
||||
|
||||
nv_wr32(dev, 0x100800, gart->pinst | 0x00000002);
|
||||
nv_mask(dev, 0x10008c, 0x00000100, 0x00000100);
|
||||
nv_wr32(dev, 0x100820, 0x00000000);
|
||||
nv_wr32(ndev, 0x100800, gart->pinst | 0x00000002);
|
||||
nv_mask(ndev, 0x10008c, 0x00000100, 0x00000100);
|
||||
nv_wr32(ndev, 0x100820, 0x00000000);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
nv44_fb_init_gart(struct drm_device *dev)
|
||||
nv44_fb_init_gart(struct nv40_fb_priv *priv)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma;
|
||||
#if 0
|
||||
struct nouveau_gpuobj *gart = ndev->gart_info.sg_ctxdma;
|
||||
u32 vinst;
|
||||
|
||||
if (dev_priv->gart_info.type != NOUVEAU_GART_HW) {
|
||||
nv_wr32(dev, 0x100850, 0x80000000);
|
||||
nv_wr32(dev, 0x100800, 0x00000001);
|
||||
if (ndev->gart_info.type != NOUVEAU_GART_HW) {
|
||||
#endif
|
||||
nv_wr32(priv, 0x100850, 0x80000000);
|
||||
nv_wr32(priv, 0x100800, 0x00000001);
|
||||
#if 0
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -57,24 +85,60 @@ nv44_fb_init_gart(struct drm_device *dev)
|
|||
* must be allocated on 512KiB alignment, and not exceed
|
||||
* a total size of 512KiB for this to work correctly
|
||||
*/
|
||||
vinst = nv_rd32(dev, 0x10020c);
|
||||
vinst = nv_rd32(ndev, 0x10020c);
|
||||
vinst -= ((gart->pinst >> 19) + 1) << 19;
|
||||
|
||||
nv_wr32(dev, 0x100850, 0x80000000);
|
||||
nv_wr32(dev, 0x100818, dev_priv->gart_info.dummy.addr);
|
||||
nv_wr32(ndev, 0x100850, 0x80000000);
|
||||
nv_wr32(ndev, 0x100818, ndev->gart_info.dummy.addr);
|
||||
|
||||
nv_wr32(dev, 0x100804, dev_priv->gart_info.aper_size);
|
||||
nv_wr32(dev, 0x100850, 0x00008000);
|
||||
nv_mask(dev, 0x10008c, 0x00000200, 0x00000200);
|
||||
nv_wr32(dev, 0x100820, 0x00000000);
|
||||
nv_wr32(dev, 0x10082c, 0x00000001);
|
||||
nv_wr32(dev, 0x100800, vinst | 0x00000010);
|
||||
nv_wr32(ndev, 0x100804, ndev->gart_info.aper_size);
|
||||
nv_wr32(ndev, 0x100850, 0x00008000);
|
||||
nv_mask(ndev, 0x10008c, 0x00000200, 0x00000200);
|
||||
nv_wr32(ndev, 0x100820, 0x00000000);
|
||||
nv_wr32(ndev, 0x10082c, 0x00000001);
|
||||
nv_wr32(ndev, 0x100800, vinst | 0x00000010);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
nv40_fb_vram_init(struct drm_device *dev)
|
||||
static int
|
||||
nv40_fb_init(struct nouveau_object *object)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nv40_fb_priv *priv = (void *)object;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_init(&priv->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (nv_device(priv)->chipset) {
|
||||
case 0x40:
|
||||
case 0x45:
|
||||
nv_mask(priv, 0x10033c, 0x00008000, 0x00000000);
|
||||
break;
|
||||
default:
|
||||
if (nv44_graph_class(nv_device(priv)))
|
||||
nv44_fb_init_gart(priv);
|
||||
else
|
||||
nv40_fb_init_gart(priv);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nv40_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nv40_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* 0x001218 is actually present on a few other NV4X I looked at,
|
||||
* and even contains sane values matching 0x100474. From looking
|
||||
|
@ -82,82 +146,73 @@ nv40_fb_vram_init(struct drm_device *dev)
|
|||
* So, I chose to use the same regs I've seen NVIDIA reading around
|
||||
* the memory detection, hopefully that'll get us the right numbers
|
||||
*/
|
||||
if (dev_priv->chipset == 0x40) {
|
||||
u32 pbus1218 = nv_rd32(dev, 0x001218);
|
||||
if (device->chipset == 0x40) {
|
||||
u32 pbus1218 = nv_rd32(priv, 0x001218);
|
||||
switch (pbus1218 & 0x00000300) {
|
||||
case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break;
|
||||
case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break;
|
||||
case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
|
||||
case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_DDR2; break;
|
||||
}
|
||||
} else
|
||||
if (dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) {
|
||||
u32 pfb914 = nv_rd32(dev, 0x100914);
|
||||
if (device->chipset == 0x49 || device->chipset == 0x4b) {
|
||||
u32 pfb914 = nv_rd32(priv, 0x100914);
|
||||
switch (pfb914 & 0x00000003) {
|
||||
case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000001: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break;
|
||||
case 0x00000002: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 0x00000001: priv->base.ram.type = NV_MEM_TYPE_DDR2; break;
|
||||
case 0x00000002: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 0x00000003: break;
|
||||
}
|
||||
} else
|
||||
if (dev_priv->chipset != 0x4e) {
|
||||
u32 pfb474 = nv_rd32(dev, 0x100474);
|
||||
if (device->chipset != 0x4e) {
|
||||
u32 pfb474 = nv_rd32(priv, 0x100474);
|
||||
if (pfb474 & 0x00000004)
|
||||
dev_priv->vram_type = NV_MEM_TYPE_GDDR3;
|
||||
priv->base.ram.type = NV_MEM_TYPE_GDDR3;
|
||||
if (pfb474 & 0x00000002)
|
||||
dev_priv->vram_type = NV_MEM_TYPE_DDR2;
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR2;
|
||||
if (pfb474 & 0x00000001)
|
||||
dev_priv->vram_type = NV_MEM_TYPE_DDR1;
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR1;
|
||||
} else {
|
||||
dev_priv->vram_type = NV_MEM_TYPE_STOLEN;
|
||||
priv->base.ram.type = NV_MEM_TYPE_STOLEN;
|
||||
}
|
||||
|
||||
dev_priv->vram_size = nv_rd32(dev, 0x10020c) & 0xff000000;
|
||||
return 0;
|
||||
}
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
|
||||
|
||||
int
|
||||
nv40_fb_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
uint32_t tmp;
|
||||
int i;
|
||||
|
||||
if (dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) {
|
||||
if (nv44_graph_class(dev))
|
||||
nv44_fb_init_gart(dev);
|
||||
else
|
||||
nv40_fb_init_gart(dev);
|
||||
}
|
||||
|
||||
switch (dev_priv->chipset) {
|
||||
priv->base.memtype_valid = nv04_fb_memtype_valid;
|
||||
switch (device->chipset) {
|
||||
case 0x40:
|
||||
case 0x45:
|
||||
tmp = nv_rd32(dev, NV10_PFB_CLOSE_PAGE2);
|
||||
nv_wr32(dev, NV10_PFB_CLOSE_PAGE2, tmp & ~(1 << 15));
|
||||
pfb->num_tiles = NV10_PFB_TILE__SIZE;
|
||||
priv->base.tile.regions = 8;
|
||||
break;
|
||||
case 0x46: /* G72 */
|
||||
case 0x47: /* G70 */
|
||||
case 0x49: /* G71 */
|
||||
case 0x4b: /* G73 */
|
||||
case 0x4c: /* C51 (G7X version) */
|
||||
pfb->num_tiles = NV40_PFB_TILE__SIZE_1;
|
||||
case 0x46:
|
||||
case 0x47:
|
||||
case 0x49:
|
||||
case 0x4b:
|
||||
case 0x4c:
|
||||
priv->base.tile.regions = 15;
|
||||
break;
|
||||
default:
|
||||
pfb->num_tiles = NV40_PFB_TILE__SIZE_0;
|
||||
priv->base.tile.regions = 12;
|
||||
break;
|
||||
}
|
||||
priv->base.tile.init = nv30_fb_tile_init;
|
||||
priv->base.tile.fini = nv30_fb_tile_fini;
|
||||
if (device->chipset == 0x40)
|
||||
priv->base.tile.prog = nv10_fb_tile_prog;
|
||||
else
|
||||
priv->base.tile.prog = nv40_fb_tile_prog;
|
||||
|
||||
/* Turn all the tiling regions off. */
|
||||
for (i = 0; i < pfb->num_tiles; i++)
|
||||
pfb->set_tile_region(dev, i);
|
||||
|
||||
return 0;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
}
|
||||
|
||||
void
|
||||
nv40_fb_takedown(struct drm_device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
nv40_fb_oclass = {
|
||||
.handle = NV_SUBDEV(FB, 0x40),
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv40_fb_ctor,
|
||||
.dtor = _nouveau_fb_dtor,
|
||||
.init = nv40_fb_init,
|
||||
.fini = _nouveau_fb_fini,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,119 +1,335 @@
|
|||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include <nouveau_drm.h>
|
||||
#include <engine/fifo.h>
|
||||
/*
|
||||
* Copyright 2012 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Ben Skeggs
|
||||
*/
|
||||
|
||||
#include <core/object.h>
|
||||
#include <core/enum.h>
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include <subdev/bios.h>
|
||||
|
||||
struct nv50_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
struct page *r100c08_page;
|
||||
dma_addr_t r100c08;
|
||||
};
|
||||
|
||||
static void
|
||||
nv50_fb_destroy(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
struct nv50_fb_priv *priv = pfb->priv;
|
||||
static int types[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,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2,
|
||||
1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0
|
||||
};
|
||||
|
||||
if (drm_mm_initialized(&pfb->tag_heap))
|
||||
drm_mm_takedown(&pfb->tag_heap);
|
||||
static bool
|
||||
nv50_fb_memtype_valid(struct nouveau_fb *pfb, u32 memtype)
|
||||
{
|
||||
return types[(memtype & 0xff00) >> 8] != 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static u32
|
||||
nv50_vram_rblock(struct nv50_fb_priv *priv)
|
||||
{
|
||||
int i, parts, colbits, rowbitsa, rowbitsb, banks;
|
||||
u64 rowsize, predicted;
|
||||
u32 r0, r4, rt, ru, rblock_size;
|
||||
|
||||
r0 = nv_rd32(priv, 0x100200);
|
||||
r4 = nv_rd32(priv, 0x100204);
|
||||
rt = nv_rd32(priv, 0x100250);
|
||||
ru = nv_rd32(priv, 0x001540);
|
||||
nv_debug(priv, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru);
|
||||
|
||||
for (i = 0, parts = 0; i < 8; i++) {
|
||||
if (ru & (0x00010000 << i))
|
||||
parts++;
|
||||
}
|
||||
|
||||
colbits = (r4 & 0x0000f000) >> 12;
|
||||
rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
|
||||
rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
|
||||
banks = 1 << (((r4 & 0x03000000) >> 24) + 2);
|
||||
|
||||
rowsize = parts * banks * (1 << colbits) * 8;
|
||||
predicted = rowsize << rowbitsa;
|
||||
if (r0 & 0x00000004)
|
||||
predicted += rowsize << rowbitsb;
|
||||
|
||||
if (predicted != priv->base.ram.size) {
|
||||
nv_warn(priv, "memory controller reports %d MiB VRAM\n",
|
||||
(u32)(priv->base.ram.size >> 20));
|
||||
}
|
||||
|
||||
rblock_size = rowsize;
|
||||
if (rt & 1)
|
||||
rblock_size *= 3;
|
||||
|
||||
nv_debug(priv, "rblock %d bytes\n", rblock_size);
|
||||
return rblock_size;
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nouveau_bios *bios = nouveau_bios(device);
|
||||
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
|
||||
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
|
||||
struct nv50_fb_priv *priv;
|
||||
u32 tags;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (nv_rd32(priv, 0x100714) & 0x00000007) {
|
||||
case 0: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
|
||||
case 1:
|
||||
if (nouveau_fb_bios_memtype(bios) == NV_MEM_TYPE_DDR3)
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR3;
|
||||
else
|
||||
priv->base.ram.type = NV_MEM_TYPE_DDR2;
|
||||
break;
|
||||
case 2: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 3: priv->base.ram.type = NV_MEM_TYPE_GDDR4; break;
|
||||
case 4: priv->base.ram.type = NV_MEM_TYPE_GDDR5; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
priv->base.ram.size = nv_rd32(priv, 0x10020c);
|
||||
priv->base.ram.size = (priv->base.ram.size & 0xffffff00) |
|
||||
((priv->base.ram.size & 0x000000ff) << 32);
|
||||
|
||||
tags = nv_rd32(priv, 0x100320);
|
||||
if (tags) {
|
||||
ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nv_debug(priv, "%d compression tags\n", tags);
|
||||
}
|
||||
|
||||
size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
|
||||
switch (device->chipset) {
|
||||
case 0xaa:
|
||||
case 0xac:
|
||||
case 0xaf: /* IGPs, no reordering, no real VRAM */
|
||||
ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12;
|
||||
break;
|
||||
default:
|
||||
ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size,
|
||||
nv50_vram_rblock(priv) >> 12);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->base.ram.ranks = (nv_rd32(priv, 0x100200) & 0x4) ? 2 : 1;
|
||||
break;
|
||||
}
|
||||
|
||||
priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
|
||||
if (priv->r100c08_page) {
|
||||
priv->r100c08 = pci_map_page(device->pdev, priv->r100c08_page,
|
||||
0, PAGE_SIZE,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
if (pci_dma_mapping_error(device->pdev, priv->r100c08))
|
||||
nv_warn(priv, "failed 0x100c08 page map\n");
|
||||
} else {
|
||||
nv_warn(priv, "failed 0x100c08 page alloc\n");
|
||||
}
|
||||
|
||||
priv->base.memtype_valid = nv50_fb_memtype_valid;
|
||||
priv->base.ram.get = nv50_fb_vram_new;
|
||||
priv->base.ram.put = nv50_fb_vram_del;
|
||||
return nouveau_fb_created(&priv->base);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_fb_dtor(struct nouveau_object *object)
|
||||
{
|
||||
struct nouveau_device *device = nv_device(object);
|
||||
struct nv50_fb_priv *priv = (void *)object;
|
||||
|
||||
if (priv->r100c08_page) {
|
||||
pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE,
|
||||
pci_unmap_page(device->pdev, priv->r100c08, PAGE_SIZE,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
__free_page(priv->r100c08_page);
|
||||
}
|
||||
|
||||
kfree(priv);
|
||||
pfb->priv = NULL;
|
||||
nouveau_mm_fini(&priv->base.vram);
|
||||
nouveau_fb_destroy(&priv->base);
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_fb_create(struct drm_device *dev)
|
||||
nv50_fb_init(struct nouveau_object *object)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
struct nv50_fb_priv *priv;
|
||||
u32 tagmem;
|
||||
struct nouveau_device *device = nv_device(object);
|
||||
struct nv50_fb_priv *priv = (void *)object;
|
||||
int ret;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
pfb->priv = priv;
|
||||
|
||||
priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
|
||||
if (!priv->r100c08_page) {
|
||||
nv50_fb_destroy(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0,
|
||||
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||
if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) {
|
||||
nv50_fb_destroy(dev);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
tagmem = nv_rd32(dev, 0x100320);
|
||||
NV_DEBUG(dev, "%d tags available\n", tagmem);
|
||||
ret = drm_mm_init(&pfb->tag_heap, 0, tagmem);
|
||||
if (ret) {
|
||||
nv50_fb_destroy(dev);
|
||||
ret = nouveau_fb_init(&priv->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nv50_fb_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nv50_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
if (!dev_priv->engine.fb.priv) {
|
||||
ret = nv50_fb_create(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
priv = dev_priv->engine.fb.priv;
|
||||
|
||||
/* Not a clue what this is exactly. Without pointing it at a
|
||||
* scratch page, VRAM->GART blits with M2MF (as in DDX DFS)
|
||||
* cause IOMMU "read from address 0" errors (rh#561267)
|
||||
*/
|
||||
nv_wr32(dev, 0x100c08, priv->r100c08 >> 8);
|
||||
nv_wr32(priv, 0x100c08, priv->r100c08 >> 8);
|
||||
|
||||
/* This is needed to get meaningful information from 100c90
|
||||
* on traps. No idea what these values mean exactly. */
|
||||
switch (dev_priv->chipset) {
|
||||
switch (device->chipset) {
|
||||
case 0x50:
|
||||
nv_wr32(dev, 0x100c90, 0x000707ff);
|
||||
nv_wr32(priv, 0x100c90, 0x000707ff);
|
||||
break;
|
||||
case 0xa3:
|
||||
case 0xa5:
|
||||
case 0xa8:
|
||||
nv_wr32(dev, 0x100c90, 0x000d0fff);
|
||||
nv_wr32(priv, 0x100c90, 0x000d0fff);
|
||||
break;
|
||||
case 0xaf:
|
||||
nv_wr32(dev, 0x100c90, 0x089d1fff);
|
||||
nv_wr32(priv, 0x100c90, 0x089d1fff);
|
||||
break;
|
||||
default:
|
||||
nv_wr32(dev, 0x100c90, 0x001d07ff);
|
||||
nv_wr32(priv, 0x100c90, 0x001d07ff);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_fb_takedown(struct drm_device *dev)
|
||||
{
|
||||
nv50_fb_destroy(dev);
|
||||
}
|
||||
struct nouveau_oclass
|
||||
nv50_fb_oclass = {
|
||||
.handle = NV_SUBDEV(FB, 0x50),
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nv50_fb_ctor,
|
||||
.dtor = nv50_fb_dtor,
|
||||
.init = nv50_fb_init,
|
||||
.fini = _nouveau_fb_fini,
|
||||
},
|
||||
};
|
||||
|
||||
static struct nouveau_enum vm_dispatch_subclients[] = {
|
||||
{ 0x00000000, "GRCTX", NULL },
|
||||
|
@ -211,47 +427,32 @@ static struct nouveau_enum vm_fault[] = {
|
|||
};
|
||||
|
||||
void
|
||||
nv50_fb_vm_trap(struct drm_device *dev, int display)
|
||||
nv50_fb_trap(struct nouveau_fb *pfb, int display)
|
||||
{
|
||||
struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO);
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_device *device = nv_device(pfb);
|
||||
struct nv50_fb_priv *priv = (void *)pfb;
|
||||
const struct nouveau_enum *en, *cl;
|
||||
unsigned long flags;
|
||||
u32 trap[6], idx, chinst;
|
||||
u32 trap[6], idx, chan;
|
||||
u8 st0, st1, st2, st3;
|
||||
int i, ch;
|
||||
int i;
|
||||
|
||||
idx = nv_rd32(dev, 0x100c90);
|
||||
idx = nv_rd32(priv, 0x100c90);
|
||||
if (!(idx & 0x80000000))
|
||||
return;
|
||||
idx &= 0x00ffffff;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
nv_wr32(dev, 0x100c90, idx | i << 24);
|
||||
trap[i] = nv_rd32(dev, 0x100c94);
|
||||
nv_wr32(priv, 0x100c90, idx | i << 24);
|
||||
trap[i] = nv_rd32(priv, 0x100c94);
|
||||
}
|
||||
nv_wr32(dev, 0x100c90, idx | 0x80000000);
|
||||
nv_wr32(priv, 0x100c90, idx | 0x80000000);
|
||||
|
||||
if (!display)
|
||||
return;
|
||||
|
||||
/* lookup channel id */
|
||||
chinst = (trap[2] << 16) | trap[1];
|
||||
spin_lock_irqsave(&dev_priv->channels.lock, flags);
|
||||
for (ch = 0; ch < pfifo->channels; ch++) {
|
||||
struct nouveau_channel *chan = dev_priv->channels.ptr[ch];
|
||||
|
||||
if (!chan || !chan->ramin)
|
||||
continue;
|
||||
|
||||
if (chinst == chan->ramin->vinst >> 12)
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
|
||||
|
||||
/* decode status bits into something more useful */
|
||||
if (dev_priv->chipset < 0xa3 ||
|
||||
dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) {
|
||||
if (device->chipset < 0xa3 ||
|
||||
device->chipset == 0xaa || device->chipset == 0xac) {
|
||||
st0 = (trap[0] & 0x0000000f) >> 0;
|
||||
st1 = (trap[0] & 0x000000f0) >> 4;
|
||||
st2 = (trap[0] & 0x00000f00) >> 8;
|
||||
|
@ -262,10 +463,11 @@ nv50_fb_vm_trap(struct drm_device *dev, int display)
|
|||
st2 = (trap[0] & 0x00ff0000) >> 16;
|
||||
st3 = (trap[0] & 0xff000000) >> 24;
|
||||
}
|
||||
chan = (trap[2] << 16) | trap[1];
|
||||
|
||||
NV_INFO(dev, "VM: trapped %s at 0x%02x%04x%04x on ch %d [0x%08x] ",
|
||||
(trap[5] & 0x00000100) ? "read" : "write",
|
||||
trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, ch, chinst);
|
||||
nv_error(priv, "trapped %s at 0x%02x%04x%04x on channel 0x%08x ",
|
||||
(trap[5] & 0x00000100) ? "read" : "write",
|
||||
trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, chan);
|
||||
|
||||
en = nouveau_enum_find(vm_engine, st0);
|
||||
if (en)
|
||||
|
|
|
@ -1,243 +0,0 @@
|
|||
/*
|
||||
* Copyright 2010 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 "drmP.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include <core/mm.h>
|
||||
|
||||
static int types[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,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2,
|
||||
1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0
|
||||
};
|
||||
|
||||
bool
|
||||
nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags)
|
||||
{
|
||||
int type = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8;
|
||||
|
||||
if (likely(type < ARRAY_SIZE(types) && types[type]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_mm *mm = &dev_priv->engine.vram.mm;
|
||||
struct nouveau_mm_node *this;
|
||||
struct nouveau_mem *mem;
|
||||
|
||||
mem = *pmem;
|
||||
*pmem = NULL;
|
||||
if (unlikely(mem == NULL))
|
||||
return;
|
||||
|
||||
mutex_lock(&mm->mutex);
|
||||
while (!list_empty(&mem->regions)) {
|
||||
this = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
|
||||
|
||||
list_del(&this->rl_entry);
|
||||
nouveau_mm_free(mm, &this);
|
||||
}
|
||||
|
||||
if (mem->tag) {
|
||||
drm_mm_put_block(mem->tag);
|
||||
mem->tag = NULL;
|
||||
}
|
||||
mutex_unlock(&mm->mutex);
|
||||
|
||||
kfree(mem);
|
||||
}
|
||||
|
||||
int
|
||||
nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
|
||||
u32 memtype, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_mm *mm = &dev_priv->engine.vram.mm;
|
||||
struct nouveau_mm_node *r;
|
||||
struct nouveau_mem *mem;
|
||||
int comp = (memtype & 0x300) >> 8;
|
||||
int type = (memtype & 0x07f);
|
||||
int back = (memtype & 0x800);
|
||||
int ret;
|
||||
|
||||
size >>= 12;
|
||||
align >>= 12;
|
||||
ncmin >>= 12;
|
||||
if (!ncmin)
|
||||
ncmin = size;
|
||||
|
||||
mem = kzalloc(sizeof(*mem), GFP_KERNEL);
|
||||
if (!mem)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&mm->mutex);
|
||||
if (comp) {
|
||||
if (align == 16) {
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
int n = (size >> 4) * comp;
|
||||
|
||||
mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0);
|
||||
if (mem->tag)
|
||||
mem->tag = drm_mm_get_block(mem->tag, n, 0);
|
||||
}
|
||||
|
||||
if (unlikely(!mem->tag))
|
||||
comp = 0;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&mem->regions);
|
||||
mem->dev = dev_priv->dev;
|
||||
mem->memtype = (comp << 7) | type;
|
||||
mem->size = size;
|
||||
|
||||
type = types[type];
|
||||
do {
|
||||
if (back)
|
||||
ret = nouveau_mm_tail(mm, type, size, ncmin, align, &r);
|
||||
else
|
||||
ret = nouveau_mm_head(mm, type, size, ncmin, align, &r);
|
||||
|
||||
if (ret) {
|
||||
mutex_unlock(&mm->mutex);
|
||||
nv50_vram_del(dev, &mem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_add_tail(&r->rl_entry, &mem->regions);
|
||||
size -= r->length;
|
||||
} while (size);
|
||||
mutex_unlock(&mm->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_vram_rblock(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int i, parts, colbits, rowbitsa, rowbitsb, banks;
|
||||
u64 rowsize, predicted;
|
||||
u32 r0, r4, rt, ru, rblock_size;
|
||||
|
||||
r0 = nv_rd32(dev, 0x100200);
|
||||
r4 = nv_rd32(dev, 0x100204);
|
||||
rt = nv_rd32(dev, 0x100250);
|
||||
ru = nv_rd32(dev, 0x001540);
|
||||
NV_DEBUG(dev, "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 != dev_priv->vram_size) {
|
||||
NV_WARN(dev, "memory controller reports %dMiB VRAM\n",
|
||||
(u32)(dev_priv->vram_size >> 20));
|
||||
NV_WARN(dev, "we calculated %dMiB VRAM\n",
|
||||
(u32)(predicted >> 20));
|
||||
}
|
||||
|
||||
rblock_size = rowsize;
|
||||
if (rt & 1)
|
||||
rblock_size *= 3;
|
||||
|
||||
NV_DEBUG(dev, "rblock %d bytes\n", rblock_size);
|
||||
return rblock_size;
|
||||
}
|
||||
|
||||
int
|
||||
nv50_vram_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
|
||||
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
|
||||
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
|
||||
u32 pfb714 = nv_rd32(dev, 0x100714);
|
||||
u32 rblock, length;
|
||||
|
||||
switch (pfb714 & 0x00000007) {
|
||||
case 0: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break;
|
||||
case 1:
|
||||
if (nouveau_mem_vbios_type(dev) == NV_MEM_TYPE_DDR3)
|
||||
dev_priv->vram_type = NV_MEM_TYPE_DDR3;
|
||||
else
|
||||
dev_priv->vram_type = NV_MEM_TYPE_DDR2;
|
||||
break;
|
||||
case 2: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break;
|
||||
case 3: dev_priv->vram_type = NV_MEM_TYPE_GDDR4; break;
|
||||
case 4: dev_priv->vram_type = NV_MEM_TYPE_GDDR5; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x100200) & 0x4);
|
||||
dev_priv->vram_size = nv_rd32(dev, 0x10020c);
|
||||
dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
|
||||
dev_priv->vram_size &= 0xffffffff00ULL;
|
||||
|
||||
/* IGPs, no funky reordering happens here, they don't have VRAM */
|
||||
if (dev_priv->chipset == 0xaa ||
|
||||
dev_priv->chipset == 0xac ||
|
||||
dev_priv->chipset == 0xaf) {
|
||||
dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12;
|
||||
rblock = 4096 >> 12;
|
||||
} else {
|
||||
rblock = nv50_vram_rblock(dev) >> 12;
|
||||
}
|
||||
|
||||
length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
|
||||
|
||||
return nouveau_mm_init(&vram->mm, rsvd_head, length, rblock);
|
||||
}
|
||||
|
||||
void
|
||||
nv50_vram_fini(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
|
||||
|
||||
nouveau_mm_fini(&vram->mm);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2011 Red Hat Inc.
|
||||
* Copyright 2012 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -22,114 +22,224 @@
|
|||
* Authors: Ben Skeggs
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include <nouveau_drm.h>
|
||||
#include <subdev/fb.h>
|
||||
#include <subdev/bios.h>
|
||||
|
||||
struct nvc0_fb_priv {
|
||||
struct nouveau_fb base;
|
||||
struct page *r100c10_page;
|
||||
dma_addr_t r100c10;
|
||||
};
|
||||
|
||||
static inline void
|
||||
nvc0_mfb_subp_isr(struct drm_device *dev, int unit, int subp)
|
||||
{
|
||||
u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400);
|
||||
u32 stat = nv_rd32(dev, subp_base + 0x020);
|
||||
/* 0 = unsupported
|
||||
* 1 = non-compressed
|
||||
* 3 = compressed
|
||||
*/
|
||||
static const u8 types[256] = {
|
||||
1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
|
||||
3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
|
||||
3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3,
|
||||
3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0
|
||||
};
|
||||
|
||||
if (stat) {
|
||||
NV_INFO(dev, "PMFB%d_SUBP%d: 0x%08x\n", unit, subp, stat);
|
||||
nv_wr32(dev, subp_base + 0x020, stat);
|
||||
}
|
||||
static bool
|
||||
nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)
|
||||
{
|
||||
u8 memtype = (tile_flags & 0x0000ff00) >> 8;
|
||||
return likely((types[memtype] == 1));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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->memtype = type;
|
||||
mem->size = size;
|
||||
|
||||
mutex_lock(&mm->mutex);
|
||||
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(&mm->mutex);
|
||||
pfb->ram.put(pfb, &mem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_add_tail(&r->rl_entry, &mem->regions);
|
||||
size -= r->length;
|
||||
} while (size);
|
||||
mutex_unlock(&mm->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_fb_init(struct nouveau_object *object)
|
||||
{
|
||||
struct nvc0_fb_priv *priv = (void *)object;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_init(&priv->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nv_wr32(priv, 0x100c10, priv->r100c10 >> 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nvc0_mfb_isr(struct drm_device *dev)
|
||||
nvc0_fb_dtor(struct nouveau_object *object)
|
||||
{
|
||||
u32 units = nv_rd32(dev, 0x00017c);
|
||||
while (units) {
|
||||
u32 subp, unit = ffs(units) - 1;
|
||||
for (subp = 0; subp < 2; subp++)
|
||||
nvc0_mfb_subp_isr(dev, unit, subp);
|
||||
units &= ~(1 << unit);
|
||||
}
|
||||
|
||||
/* we do something horribly wrong and upset PMFB a lot, so mask off
|
||||
* interrupts from it after the first one until it's fixed
|
||||
*/
|
||||
nv_mask(dev, 0x000640, 0x02000000, 0x00000000);
|
||||
}
|
||||
|
||||
static void
|
||||
nvc0_fb_destroy(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
struct nvc0_fb_priv *priv = pfb->priv;
|
||||
|
||||
nouveau_irq_unregister(dev, 25);
|
||||
struct nouveau_device *device = nv_device(object);
|
||||
struct nvc0_fb_priv *priv = (void *)object;
|
||||
|
||||
if (priv->r100c10_page) {
|
||||
pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE,
|
||||
pci_unmap_page(device->pdev, priv->r100c10, PAGE_SIZE,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
__free_page(priv->r100c10_page);
|
||||
}
|
||||
|
||||
kfree(priv);
|
||||
pfb->priv = NULL;
|
||||
nouveau_fb_destroy(&priv->base);
|
||||
}
|
||||
|
||||
static int
|
||||
nvc0_fb_create(struct drm_device *dev)
|
||||
nvc0_vram_detect(struct nvc0_fb_priv *priv)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
struct nvc0_fb_priv *priv;
|
||||
struct nouveau_bios *bios = nouveau_bios(priv);
|
||||
struct nouveau_fb *pfb = &priv->base;
|
||||
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
|
||||
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
|
||||
u32 parts = nv_rd32(priv, 0x022438);
|
||||
u32 pmask = nv_rd32(priv, 0x022554);
|
||||
u32 bsize = nv_rd32(priv, 0x10f20c);
|
||||
u32 offset, length;
|
||||
bool uniform = true;
|
||||
int ret, part;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
pfb->priv = priv;
|
||||
nv_debug(priv, "0x100800: 0x%08x\n", nv_rd32(priv, 0x100800));
|
||||
nv_debug(priv, "parts 0x%08x mask 0x%08x\n", parts, pmask);
|
||||
|
||||
priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
|
||||
if (!priv->r100c10_page) {
|
||||
nvc0_fb_destroy(dev);
|
||||
return -ENOMEM;
|
||||
priv->base.ram.type = nouveau_fb_bios_memtype(bios);
|
||||
priv->base.ram.ranks = (nv_rd32(priv, 0x10f200) & 0x00000004) ? 2 : 1;
|
||||
|
||||
/* read amount of vram attached to each memory controller */
|
||||
for (part = 0; part < parts; part++) {
|
||||
if (!(pmask & (1 << part))) {
|
||||
u32 psize = nv_rd32(priv, 0x11020c + (part * 0x1000));
|
||||
if (psize != bsize) {
|
||||
if (psize < bsize)
|
||||
bsize = psize;
|
||||
uniform = false;
|
||||
}
|
||||
|
||||
nv_debug(priv, "%d: mem_amount 0x%08x\n", part, psize);
|
||||
priv->base.ram.size += (u64)psize << 20;
|
||||
}
|
||||
}
|
||||
|
||||
priv->r100c10 = pci_map_page(dev->pdev, priv->r100c10_page, 0,
|
||||
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||
if (pci_dma_mapping_error(dev->pdev, priv->r100c10)) {
|
||||
nvc0_fb_destroy(dev);
|
||||
return -EFAULT;
|
||||
/* if all controllers have the same amount attached, there's no holes */
|
||||
if (uniform) {
|
||||
offset = rsvd_head;
|
||||
length = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
|
||||
return nouveau_mm_init(&pfb->vram, offset, length, 1);
|
||||
}
|
||||
|
||||
/* otherwise, address lowest common amount from 0GiB */
|
||||
ret = nouveau_mm_init(&pfb->vram, rsvd_head, (bsize << 8) * parts, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* and the rest starting from (8GiB + common_size) */
|
||||
offset = (0x0200000000ULL >> 12) + (bsize << 8);
|
||||
length = (priv->base.ram.size >> 12) - (bsize << 8) - rsvd_tail;
|
||||
|
||||
ret = nouveau_mm_init(&pfb->vram, offset, length, 0);
|
||||
if (ret) {
|
||||
nouveau_mm_fini(&pfb->vram);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nouveau_irq_register(dev, 25, nvc0_mfb_isr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nvc0_fb_init(struct drm_device *dev)
|
||||
static int
|
||||
nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_device *device = nv_device(parent);
|
||||
struct nvc0_fb_priv *priv;
|
||||
int ret;
|
||||
|
||||
if (!dev_priv->engine.fb.priv) {
|
||||
ret = nvc0_fb_create(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
priv = dev_priv->engine.fb.priv;
|
||||
ret = nouveau_fb_create(parent, engine, oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nv_wr32(dev, 0x100c10, priv->r100c10 >> 8);
|
||||
nv_mask(dev, 0x17e820, 0x00100000, 0x00000000); /* NV_PLTCG_INTR_EN */
|
||||
return 0;
|
||||
priv->base.memtype_valid = nvc0_fb_memtype_valid;
|
||||
priv->base.ram.get = nvc0_fb_vram_new;
|
||||
priv->base.ram.put = nv50_fb_vram_del;
|
||||
|
||||
ret = nvc0_vram_detect(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
|
||||
if (!priv->r100c10_page)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->r100c10 = pci_map_page(device->pdev, priv->r100c10_page, 0,
|
||||
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||
if (pci_dma_mapping_error(device->pdev, priv->r100c10))
|
||||
return -EFAULT;
|
||||
|
||||
return nouveau_fb_created(&priv->base);
|
||||
}
|
||||
|
||||
void
|
||||
nvc0_fb_takedown(struct drm_device *dev)
|
||||
{
|
||||
nvc0_fb_destroy(dev);
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
nvc0_fb_oclass = {
|
||||
.handle = NV_SUBDEV(FB, 0xc0),
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nvc0_fb_ctor,
|
||||
.dtor = nvc0_fb_dtor,
|
||||
.init = nvc0_fb_init,
|
||||
.fini = _nouveau_fb_fini,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,167 +0,0 @@
|
|||
/*
|
||||
* Copyright 2010 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 "drmP.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include <core/mm.h>
|
||||
|
||||
/* 0 = unsupported
|
||||
* 1 = non-compressed
|
||||
* 3 = compressed
|
||||
*/
|
||||
static const u8 types[256] = {
|
||||
1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
|
||||
3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
|
||||
3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3,
|
||||
3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0
|
||||
};
|
||||
|
||||
bool
|
||||
nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags)
|
||||
{
|
||||
u8 memtype = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8;
|
||||
return likely((types[memtype] == 1));
|
||||
}
|
||||
|
||||
int
|
||||
nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
|
||||
u32 memtype, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_mm *mm = &dev_priv->engine.vram.mm;
|
||||
struct nouveau_mm_node *r;
|
||||
struct nouveau_mem *mem;
|
||||
int type = (memtype & 0x0ff);
|
||||
int back = (memtype & 0x800);
|
||||
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->dev = dev_priv->dev;
|
||||
mem->memtype = type;
|
||||
mem->size = size;
|
||||
|
||||
mutex_lock(&mm->mutex);
|
||||
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(&mm->mutex);
|
||||
nv50_vram_del(dev, &mem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_add_tail(&r->rl_entry, &mem->regions);
|
||||
size -= r->length;
|
||||
} while (size);
|
||||
mutex_unlock(&mm->mutex);
|
||||
|
||||
r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
|
||||
mem->offset = (u64)r->offset << 12;
|
||||
*pmem = mem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nvc0_vram_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
|
||||
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
|
||||
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
|
||||
u32 parts = nv_rd32(dev, 0x022438);
|
||||
u32 pmask = nv_rd32(dev, 0x022554);
|
||||
u32 bsize = nv_rd32(dev, 0x10f20c);
|
||||
u32 offset, length;
|
||||
bool uniform = true;
|
||||
int ret, part;
|
||||
|
||||
NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800));
|
||||
NV_DEBUG(dev, "parts 0x%08x mask 0x%08x\n", parts, pmask);
|
||||
|
||||
dev_priv->vram_type = nouveau_mem_vbios_type(dev);
|
||||
dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x10f200) & 0x00000004);
|
||||
|
||||
/* read amount of vram attached to each memory controller */
|
||||
for (part = 0; part < parts; part++) {
|
||||
if (!(pmask & (1 << part))) {
|
||||
u32 psize = nv_rd32(dev, 0x11020c + (part * 0x1000));
|
||||
if (psize != bsize) {
|
||||
if (psize < bsize)
|
||||
bsize = psize;
|
||||
uniform = false;
|
||||
}
|
||||
|
||||
NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize);
|
||||
dev_priv->vram_size += (u64)psize << 20;
|
||||
}
|
||||
}
|
||||
|
||||
/* if all controllers have the same amount attached, there's no holes */
|
||||
if (uniform) {
|
||||
offset = rsvd_head;
|
||||
length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
|
||||
return nouveau_mm_init(&vram->mm, offset, length, 1);
|
||||
}
|
||||
|
||||
/* otherwise, address lowest common amount from 0GiB */
|
||||
ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* and the rest starting from (8GiB + common_size) */
|
||||
offset = (0x0200000000ULL >> 12) + (bsize << 8);
|
||||
length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail;
|
||||
|
||||
ret = nouveau_mm_init(&vram->mm, offset, length, 0);
|
||||
if (ret) {
|
||||
nouveau_mm_fini(&vram->mm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -310,8 +310,6 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan,
|
|||
u32 size, u32 align)
|
||||
{
|
||||
struct drm_device *dev = gpuobj->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
|
||||
struct nv50_gpuobj_node *node = NULL;
|
||||
int ret;
|
||||
|
||||
|
@ -323,7 +321,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan,
|
|||
size = (size + 4095) & ~4095;
|
||||
align = max(align, (u32)4096);
|
||||
|
||||
ret = vram->get(dev, size, align, 0, 0x800, &node->vram);
|
||||
ret = nvfb_vram_get(dev, size, align, 0, 0x800, &node->vram);
|
||||
if (ret) {
|
||||
kfree(node);
|
||||
return ret;
|
||||
|
@ -339,7 +337,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan,
|
|||
ret = nouveau_vm_get(chan->vm, size, 12, flags,
|
||||
&node->chan_vma);
|
||||
if (ret) {
|
||||
vram->put(dev, &node->vram);
|
||||
nvfb_vram_put(dev, &node->vram);
|
||||
kfree(node);
|
||||
return ret;
|
||||
}
|
||||
|
@ -357,8 +355,6 @@ void
|
|||
nv50_instmem_put(struct nouveau_gpuobj *gpuobj)
|
||||
{
|
||||
struct drm_device *dev = gpuobj->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
|
||||
struct nv50_gpuobj_node *node;
|
||||
|
||||
node = gpuobj->node;
|
||||
|
@ -368,7 +364,7 @@ nv50_instmem_put(struct nouveau_gpuobj *gpuobj)
|
|||
nouveau_vm_unmap(&node->chan_vma);
|
||||
nouveau_vm_put(&node->chan_vma);
|
||||
}
|
||||
vram->put(dev, &node->vram);
|
||||
nvfb_vram_put(dev, &node->vram);
|
||||
kfree(node);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright 2012 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Ben Skeggs
|
||||
*/
|
||||
|
||||
#include <subdev/ltcg.h>
|
||||
|
||||
struct nvc0_ltcg_priv {
|
||||
struct nouveau_ltcg base;
|
||||
};
|
||||
|
||||
static void
|
||||
nvc0_ltcg_subp_isr(struct nvc0_ltcg_priv *priv, int unit, int subp)
|
||||
{
|
||||
u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400);
|
||||
u32 stat = nv_rd32(priv, subp_base + 0x020);
|
||||
|
||||
if (stat) {
|
||||
nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", unit, subp, stat);
|
||||
nv_wr32(priv, subp_base + 0x020, stat);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nvc0_ltcg_intr(struct nouveau_subdev *subdev)
|
||||
{
|
||||
struct nvc0_ltcg_priv *priv = (void *)subdev;
|
||||
u32 units;
|
||||
|
||||
units = nv_rd32(priv, 0x00017c);
|
||||
while (units) {
|
||||
u32 subp, unit = ffs(units) - 1;
|
||||
for (subp = 0; subp < 2; subp++)
|
||||
nvc0_ltcg_subp_isr(priv, unit, subp);
|
||||
units &= ~(1 << unit);
|
||||
}
|
||||
|
||||
/* we do something horribly wrong and upset PMFB a lot, so mask off
|
||||
* interrupts from it after the first one until it's fixed
|
||||
*/
|
||||
nv_mask(priv, 0x000640, 0x02000000, 0x00000000);
|
||||
}
|
||||
|
||||
static int
|
||||
nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
struct nouveau_object **pobject)
|
||||
{
|
||||
struct nvc0_ltcg_priv *priv;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_ltcg_create(parent, engine, oclass, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
|
||||
|
||||
nv_subdev(priv)->intr = nvc0_ltcg_intr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nouveau_oclass
|
||||
nvc0_ltcg_oclass = {
|
||||
.handle = NV_SUBDEV(LTCG, 0xc0),
|
||||
.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = nvc0_ltcg_ctor,
|
||||
.dtor = _nouveau_ltcg_dtor,
|
||||
.init = _nouveau_ltcg_init,
|
||||
.fini = _nouveau_ltcg_fini,
|
||||
},
|
||||
};
|
|
@ -38,6 +38,7 @@ nvc0_mc_intr[] = {
|
|||
{ 0x00008000, NVDEV_ENGINE_BSP },
|
||||
{ 0x00100000, NVDEV_SUBDEV_TIMER },
|
||||
{ 0x00200000, NVDEV_SUBDEV_GPIO },
|
||||
{ 0x02000000, NVDEV_SUBDEV_LTCG },
|
||||
{ 0x04000000, NVDEV_ENGINE_DISP },
|
||||
{ 0x80000000, NVDEV_ENGINE_SW },
|
||||
{},
|
||||
|
|
|
@ -80,8 +80,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 (dev_priv->vram_sys_base) {
|
||||
phys += dev_priv->vram_sys_base;
|
||||
if (nvfb_vram_sys_base(dev_priv->dev)) {
|
||||
phys += nvfb_vram_sys_base(dev_priv->dev);
|
||||
target = 3;
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
|
|||
phys += block << (vma->node->type - 3);
|
||||
cnt -= block;
|
||||
if (comp) {
|
||||
u32 tag = mem->tag->start + ((delta >> 16) * comp);
|
||||
u32 tag = mem->tag->offset + ((delta >> 16) * comp);
|
||||
offset_h |= (tag << 17);
|
||||
delta += block << (vma->node->type - 3);
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ static void
|
|||
set_placement_range(struct nouveau_bo *nvbo, uint32_t type)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev);
|
||||
int vram_pages = dev_priv->vram_size >> PAGE_SHIFT;
|
||||
int vram_pages = nvfb_vram_size(dev_priv->dev) >> PAGE_SHIFT;
|
||||
|
||||
if (dev_priv->card_type == NV_10 &&
|
||||
nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) &&
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <subdev/clock.h>
|
||||
#include <subdev/mc.h>
|
||||
#include <subdev/timer.h>
|
||||
#include <subdev/fb.h>
|
||||
|
||||
void *nouveau_newpriv(struct drm_device *);
|
||||
|
||||
|
@ -332,3 +333,108 @@ nv_timer_read(struct drm_device *dev)
|
|||
struct nouveau_timer *ptimer = nouveau_timer(drm->device);
|
||||
return ptimer->read(ptimer);
|
||||
}
|
||||
|
||||
int
|
||||
nvfb_tile_nr(struct drm_device *dev)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_newpriv(dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(drm->device);
|
||||
return pfb->tile.regions;
|
||||
}
|
||||
|
||||
struct nouveau_fb_tile *
|
||||
nvfb_tile(struct drm_device *dev, int i)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_newpriv(dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(drm->device);
|
||||
return &pfb->tile.region[i];
|
||||
}
|
||||
|
||||
void
|
||||
nvfb_tile_init(struct drm_device *dev, int i, u32 a, u32 b, u32 c, u32 d)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_newpriv(dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(drm->device);
|
||||
pfb->tile.init(pfb, i, a, b, c, d, &pfb->tile.region[i]);
|
||||
}
|
||||
|
||||
void
|
||||
nvfb_tile_fini(struct drm_device *dev, int i)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_newpriv(dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(drm->device);
|
||||
pfb->tile.fini(pfb, i, &pfb->tile.region[i]);
|
||||
}
|
||||
|
||||
void
|
||||
nvfb_tile_prog(struct drm_device *dev, int i)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_newpriv(dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(drm->device);
|
||||
pfb->tile.prog(pfb, i, &pfb->tile.region[i]);
|
||||
}
|
||||
|
||||
bool
|
||||
nvfb_flags_valid(struct drm_device *dev, u32 flags)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_newpriv(dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(drm->device);
|
||||
return pfb->memtype_valid(pfb, flags);
|
||||
}
|
||||
|
||||
int
|
||||
nvfb_vram_get(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
|
||||
u32 memtype, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_newpriv(dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(drm->device);
|
||||
int ret = pfb->ram.get(pfb, size, align, ncmin, memtype, pmem);
|
||||
if (ret)
|
||||
return ret;
|
||||
(*pmem)->dev = dev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nvfb_vram_put(struct drm_device *dev, struct nouveau_mem **pmem)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_newpriv(dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(drm->device);
|
||||
pfb->ram.put(pfb, pmem);
|
||||
}
|
||||
|
||||
|
||||
u64 nvfb_vram_sys_base(struct drm_device *dev)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_newpriv(dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(drm->device);
|
||||
return pfb->ram.stolen;
|
||||
}
|
||||
|
||||
u64 nvfb_vram_size(struct drm_device *dev)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_newpriv(dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(drm->device);
|
||||
return pfb->ram.size;
|
||||
}
|
||||
|
||||
int nvfb_vram_type(struct drm_device *dev)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_newpriv(dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(drm->device);
|
||||
return pfb->ram.type;
|
||||
}
|
||||
|
||||
int nvfb_vram_rank_B(struct drm_device *dev)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_newpriv(dev);
|
||||
struct nouveau_fb *pfb = nouveau_fb(drm->device);
|
||||
return pfb->ram.ranks > 1;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_fb_vm_trap(struct drm_device *dev, int disp)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_newpriv(dev);
|
||||
nv50_fb_trap(nouveau_fb(drm->device), disp);
|
||||
}
|
||||
|
|
|
@ -62,4 +62,24 @@ bool nouveau_wait_cb(struct drm_device *, u64 timeout,
|
|||
|
||||
u64 nv_timer_read(struct drm_device *);
|
||||
|
||||
int nvfb_tile_nr(struct drm_device *);
|
||||
void nvfb_tile_init(struct drm_device *, int, u32, u32, u32, u32);
|
||||
void nvfb_tile_fini(struct drm_device *, int);
|
||||
void nvfb_tile_prog(struct drm_device *, int);
|
||||
|
||||
struct nouveau_fb_tile *nvfb_tile(struct drm_device *, int);
|
||||
|
||||
struct nouveau_mem;
|
||||
int nvfb_vram_get(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
|
||||
u32 memtype, struct nouveau_mem **pmem);
|
||||
void nvfb_vram_put(struct drm_device *dev, struct nouveau_mem **pmem);
|
||||
bool nvfb_flags_valid(struct drm_device *dev, u32);
|
||||
|
||||
u64 nvfb_vram_sys_base(struct drm_device *);
|
||||
u64 nvfb_vram_size(struct drm_device *);
|
||||
int nvfb_vram_type(struct drm_device *);
|
||||
int nvfb_vram_rank_B(struct drm_device *);
|
||||
|
||||
void nv50_fb_vm_trap(struct drm_device *, int);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -137,9 +137,8 @@ nouveau_debugfs_memory_info(struct seq_file *m, void *data)
|
|||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_minor *minor = node->minor;
|
||||
struct drm_nouveau_private *dev_priv = minor->dev->dev_private;
|
||||
|
||||
seq_printf(m, "VRAM total: %dKiB\n", (int)(dev_priv->vram_size >> 10));
|
||||
seq_printf(m, "VRAM total: %dKiB\n", (int)(nvfb_vram_size(minor->dev) >> 10));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -252,7 +252,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
|
|||
|
||||
NV_INFO(dev, "Reinitialising engines...\n");
|
||||
engine->instmem.resume(dev);
|
||||
engine->fb.init(dev);
|
||||
for (i = 0; i < NVOBJ_ENGINE_NR; i++) {
|
||||
if (dev_priv->eng[i])
|
||||
dev_priv->eng[i]->init(dev, i);
|
||||
|
|
|
@ -45,6 +45,23 @@
|
|||
#include "ttm/ttm_memory.h"
|
||||
#include "ttm/ttm_module.h"
|
||||
|
||||
#define XXX_THIS_IS_A_HACK
|
||||
#include <subdev/fb.h>
|
||||
|
||||
enum blah {
|
||||
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
|
||||
};
|
||||
|
||||
struct nouveau_fpriv {
|
||||
spinlock_t lock;
|
||||
struct list_head channels;
|
||||
|
@ -76,29 +93,8 @@ struct nouveau_mem;
|
|||
#define NOUVEAU_MAX_CHANNEL_NR 4096
|
||||
#define NOUVEAU_MAX_TILE_NR 15
|
||||
|
||||
struct nouveau_mem {
|
||||
struct drm_device *dev;
|
||||
|
||||
struct nouveau_vma bar_vma;
|
||||
struct nouveau_vma vma[2];
|
||||
u8 page_shift;
|
||||
|
||||
struct drm_mm_node *tag;
|
||||
struct list_head regions;
|
||||
dma_addr_t *pages;
|
||||
u32 memtype;
|
||||
u64 offset;
|
||||
u64 size;
|
||||
struct sg_table *sg;
|
||||
};
|
||||
|
||||
struct nouveau_tile_reg {
|
||||
bool used;
|
||||
uint32_t addr;
|
||||
uint32_t limit;
|
||||
uint32_t pitch;
|
||||
uint32_t zcomp;
|
||||
struct drm_mm_node *tag_mem;
|
||||
struct nouveau_fence *fence;
|
||||
};
|
||||
|
||||
|
@ -324,21 +320,6 @@ struct nouveau_instmem_engine {
|
|||
void (*flush)(struct drm_device *);
|
||||
};
|
||||
|
||||
struct nouveau_fb_engine {
|
||||
int num_tiles;
|
||||
struct drm_mm tag_heap;
|
||||
void *priv;
|
||||
|
||||
int (*init)(struct drm_device *dev);
|
||||
void (*takedown)(struct drm_device *dev);
|
||||
|
||||
void (*init_tile_region)(struct drm_device *dev, int i,
|
||||
uint32_t addr, uint32_t size,
|
||||
uint32_t pitch, uint32_t flags);
|
||||
void (*set_tile_region)(struct drm_device *dev, int i);
|
||||
void (*free_tile_region)(struct drm_device *dev, int i);
|
||||
};
|
||||
|
||||
struct nouveau_display_engine {
|
||||
void *priv;
|
||||
int (*early_init)(struct drm_device *);
|
||||
|
@ -519,24 +500,10 @@ struct nouveau_pm_engine {
|
|||
int (*temp_get)(struct drm_device *);
|
||||
};
|
||||
|
||||
struct nouveau_vram_engine {
|
||||
struct nouveau_mm mm;
|
||||
|
||||
int (*init)(struct drm_device *);
|
||||
void (*takedown)(struct drm_device *dev);
|
||||
int (*get)(struct drm_device *, u64, u32 align, u32 size_nc,
|
||||
u32 type, struct nouveau_mem **);
|
||||
void (*put)(struct drm_device *, struct nouveau_mem **);
|
||||
|
||||
bool (*flags_valid)(struct drm_device *, u32 tile_flags);
|
||||
};
|
||||
|
||||
struct nouveau_engine {
|
||||
struct nouveau_instmem_engine instmem;
|
||||
struct nouveau_fb_engine fb;
|
||||
struct nouveau_display_engine display;
|
||||
struct nouveau_pm_engine pm;
|
||||
struct nouveau_vram_engine vram;
|
||||
};
|
||||
|
||||
enum nv04_fp_display_regs {
|
||||
|
@ -714,24 +681,6 @@ struct drm_nouveau_private {
|
|||
spinlock_t lock;
|
||||
} tile;
|
||||
|
||||
/* VRAM/fb configuration */
|
||||
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
|
||||
} vram_type;
|
||||
uint64_t vram_size;
|
||||
uint64_t vram_sys_base;
|
||||
bool vram_rank_B;
|
||||
|
||||
uint64_t fb_available_size;
|
||||
uint64_t fb_mappable_pages;
|
||||
uint64_t fb_aper_free;
|
||||
|
@ -1047,55 +996,6 @@ int nouveau_ttm_mmap(struct file *, struct vm_area_struct *);
|
|||
/* nouveau_hdmi.c */
|
||||
void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *);
|
||||
|
||||
/* nv04_fb.c */
|
||||
extern int nv04_fb_vram_init(struct drm_device *);
|
||||
extern int nv04_fb_init(struct drm_device *);
|
||||
extern void nv04_fb_takedown(struct drm_device *);
|
||||
|
||||
/* nv10_fb.c */
|
||||
extern int nv10_fb_vram_init(struct drm_device *dev);
|
||||
extern int nv1a_fb_vram_init(struct drm_device *dev);
|
||||
extern int nv10_fb_init(struct drm_device *);
|
||||
extern void nv10_fb_takedown(struct drm_device *);
|
||||
extern void nv10_fb_init_tile_region(struct drm_device *dev, int i,
|
||||
uint32_t addr, uint32_t size,
|
||||
uint32_t pitch, uint32_t flags);
|
||||
extern void nv10_fb_set_tile_region(struct drm_device *dev, int i);
|
||||
extern void nv10_fb_free_tile_region(struct drm_device *dev, int i);
|
||||
|
||||
/* nv20_fb.c */
|
||||
extern int nv20_fb_vram_init(struct drm_device *dev);
|
||||
extern int nv20_fb_init(struct drm_device *);
|
||||
extern void nv20_fb_takedown(struct drm_device *);
|
||||
extern void nv20_fb_init_tile_region(struct drm_device *dev, int i,
|
||||
uint32_t addr, uint32_t size,
|
||||
uint32_t pitch, uint32_t flags);
|
||||
extern void nv20_fb_set_tile_region(struct drm_device *dev, int i);
|
||||
extern void nv20_fb_free_tile_region(struct drm_device *dev, int i);
|
||||
|
||||
/* nv30_fb.c */
|
||||
extern int nv30_fb_init(struct drm_device *);
|
||||
extern void nv30_fb_takedown(struct drm_device *);
|
||||
extern void nv30_fb_init_tile_region(struct drm_device *dev, int i,
|
||||
uint32_t addr, uint32_t size,
|
||||
uint32_t pitch, uint32_t flags);
|
||||
extern void nv30_fb_free_tile_region(struct drm_device *dev, int i);
|
||||
|
||||
/* nv40_fb.c */
|
||||
extern int nv40_fb_vram_init(struct drm_device *dev);
|
||||
extern int nv40_fb_init(struct drm_device *);
|
||||
extern void nv40_fb_takedown(struct drm_device *);
|
||||
extern void nv40_fb_set_tile_region(struct drm_device *dev, int i);
|
||||
|
||||
/* nv50_fb.c */
|
||||
extern int nv50_fb_init(struct drm_device *);
|
||||
extern void nv50_fb_takedown(struct drm_device *);
|
||||
extern void nv50_fb_vm_trap(struct drm_device *, int display);
|
||||
|
||||
/* nvc0_fb.c */
|
||||
extern int nvc0_fb_init(struct drm_device *);
|
||||
extern void nvc0_fb_takedown(struct drm_device *);
|
||||
|
||||
/* nv04_graph.c */
|
||||
extern int nv04_graph_create(struct drm_device *);
|
||||
extern int nv04_graph_object_new(struct nouveau_channel *, int, u32, u16);
|
||||
|
@ -1488,18 +1388,6 @@ nv44_graph_class(struct drm_device *dev)
|
|||
return !(0x0baf & (1 << (dev_priv->chipset & 0x0f)));
|
||||
}
|
||||
|
||||
int nv50_vram_init(struct drm_device *);
|
||||
void nv50_vram_fini(struct drm_device *);
|
||||
int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc,
|
||||
u32 memtype, struct nouveau_mem **);
|
||||
void nv50_vram_del(struct drm_device *, struct nouveau_mem **);
|
||||
bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags);
|
||||
|
||||
int nvc0_vram_init(struct drm_device *);
|
||||
int nvc0_vram_new(struct drm_device *, u64 size, u32 align, u32 ncmin,
|
||||
u32 memtype, struct nouveau_mem **);
|
||||
bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags);
|
||||
|
||||
/* memory type/access flags, do not match hardware values */
|
||||
#define NV_MEM_ACCESS_RO 1
|
||||
#define NV_MEM_ACCESS_WO 2
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef __NOUVEAU_FB_H__
|
||||
#define __NOUVEAU_FB_H__
|
||||
#ifndef __NOUVEAU_FRB_H__
|
||||
#define __NOUVEAU_FRB_H__
|
||||
|
||||
struct nouveau_framebuffer {
|
||||
struct drm_framebuffer base;
|
||||
|
|
|
@ -475,9 +475,9 @@ int nouveau_fbcon_init(struct drm_device *dev)
|
|||
|
||||
drm_fb_helper_single_add_all_connectors(&nfbdev->helper);
|
||||
|
||||
if (dev_priv->vram_size <= 32 * 1024 * 1024)
|
||||
if (nvfb_vram_size(dev) <= 32 * 1024 * 1024)
|
||||
preferred_bpp = 8;
|
||||
else if (dev_priv->vram_size <= 64 * 1024 * 1024)
|
||||
else if (nvfb_vram_size(dev) <= 64 * 1024 * 1024)
|
||||
preferred_bpp = 16;
|
||||
else
|
||||
preferred_bpp = 32;
|
||||
|
|
|
@ -209,7 +209,7 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
|
|||
|
||||
dev_priv->ttm.bdev.dev_mapping = dev->dev_mapping;
|
||||
|
||||
if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) {
|
||||
if (!nvfb_flags_valid(dev, req->info.tile_flags)) {
|
||||
NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -48,21 +48,21 @@
|
|||
|
||||
static void
|
||||
nv10_mem_update_tile_region(struct drm_device *dev,
|
||||
struct nouveau_tile_reg *tile, uint32_t addr,
|
||||
struct nouveau_tile_reg *tilereg, uint32_t addr,
|
||||
uint32_t size, uint32_t pitch, uint32_t flags)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
int i = tile - dev_priv->tile.reg, j;
|
||||
int i = tilereg - dev_priv->tile.reg, j;
|
||||
struct nouveau_fb_tile *tile = nvfb_tile(dev, i);
|
||||
unsigned long save;
|
||||
|
||||
nouveau_fence_unref(&tile->fence);
|
||||
nouveau_fence_unref(&tilereg->fence);
|
||||
|
||||
if (tile->pitch)
|
||||
pfb->free_tile_region(dev, i);
|
||||
nvfb_tile_fini(dev, i);
|
||||
|
||||
if (pitch)
|
||||
pfb->init_tile_region(dev, i, addr, size, pitch, flags);
|
||||
nvfb_tile_init(dev, i, addr, size, pitch, flags);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->context_switch_lock, save);
|
||||
nv_wr32(dev, NV03_PFIFO_CACHES, 0);
|
||||
|
@ -70,7 +70,7 @@ nv10_mem_update_tile_region(struct drm_device *dev,
|
|||
|
||||
nouveau_wait_for_idle(dev);
|
||||
|
||||
pfb->set_tile_region(dev, i);
|
||||
nvfb_tile_prog(dev, i);
|
||||
for (j = 0; j < NVOBJ_ENGINE_NR; j++) {
|
||||
if (dev_priv->eng[j] && dev_priv->eng[j]->set_tile_region)
|
||||
dev_priv->eng[j]->set_tile_region(dev, i);
|
||||
|
@ -122,19 +122,17 @@ struct nouveau_tile_reg *
|
|||
nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size,
|
||||
uint32_t pitch, uint32_t flags)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
|
||||
struct nouveau_tile_reg *tile, *found = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pfb->num_tiles; i++) {
|
||||
for (i = 0; i < nvfb_tile_nr(dev); i++) {
|
||||
tile = nv10_mem_get_tile_region(dev, i);
|
||||
|
||||
if (pitch && !found) {
|
||||
found = tile;
|
||||
continue;
|
||||
|
||||
} else if (tile && tile->pitch) {
|
||||
} else if (tile && nvfb_tile(dev, i)->pitch) {
|
||||
/* Kill an unused tile region. */
|
||||
nv10_mem_update_tile_region(dev, tile, 0, 0, 0, 0);
|
||||
}
|
||||
|
@ -174,38 +172,11 @@ nouveau_mem_gart_fini(struct drm_device *dev)
|
|||
nouveau_sgdma_takedown(dev);
|
||||
}
|
||||
|
||||
bool
|
||||
nouveau_mem_flags_valid(struct drm_device *dev, u32 tile_flags)
|
||||
{
|
||||
if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct vram_types {
|
||||
int value;
|
||||
const char *name;
|
||||
} vram_type_map[] = {
|
||||
{ NV_MEM_TYPE_STOLEN , "stolen system memory" },
|
||||
{ NV_MEM_TYPE_SGRAM , "SGRAM" },
|
||||
{ NV_MEM_TYPE_SDRAM , "SDRAM" },
|
||||
{ NV_MEM_TYPE_DDR1 , "DDR1" },
|
||||
{ NV_MEM_TYPE_DDR2 , "DDR2" },
|
||||
{ NV_MEM_TYPE_DDR3 , "DDR3" },
|
||||
{ NV_MEM_TYPE_GDDR2 , "GDDR2" },
|
||||
{ NV_MEM_TYPE_GDDR3 , "GDDR3" },
|
||||
{ NV_MEM_TYPE_GDDR4 , "GDDR4" },
|
||||
{ NV_MEM_TYPE_GDDR5 , "GDDR5" },
|
||||
{ NV_MEM_TYPE_UNKNOWN, "unknown type" }
|
||||
};
|
||||
|
||||
int
|
||||
nouveau_mem_vram_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
|
||||
const struct vram_types *vram_type;
|
||||
int ret, dma_bits;
|
||||
|
||||
dma_bits = 32;
|
||||
|
@ -243,27 +214,7 @@ nouveau_mem_vram_init(struct drm_device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
vram_type = vram_type_map;
|
||||
while (vram_type->value != NV_MEM_TYPE_UNKNOWN) {
|
||||
if (nouveau_vram_type) {
|
||||
if (!strcasecmp(nouveau_vram_type, vram_type->name))
|
||||
break;
|
||||
dev_priv->vram_type = vram_type->value;
|
||||
} else {
|
||||
if (vram_type->value == dev_priv->vram_type)
|
||||
break;
|
||||
}
|
||||
vram_type++;
|
||||
}
|
||||
|
||||
NV_INFO(dev, "Detected %dMiB VRAM (%s)\n",
|
||||
(int)(dev_priv->vram_size >> 20), vram_type->name);
|
||||
if (dev_priv->vram_sys_base) {
|
||||
NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
|
||||
dev_priv->vram_sys_base);
|
||||
}
|
||||
|
||||
dev_priv->fb_available_size = dev_priv->vram_size;
|
||||
dev_priv->fb_available_size = nvfb_vram_size(dev);
|
||||
dev_priv->fb_mappable_pages = dev_priv->fb_available_size;
|
||||
if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1))
|
||||
dev_priv->fb_mappable_pages = pci_resource_len(dev->pdev, 1);
|
||||
|
@ -364,7 +315,6 @@ nv50_mem_timing_calc(struct drm_device *dev, u32 freq,
|
|||
struct nouveau_pm_memtiming *boot,
|
||||
struct nouveau_pm_memtiming *t)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct bit_entry P;
|
||||
uint8_t unk18 = 1, unk20 = 0, unk21 = 0, tmp7_3;
|
||||
|
||||
|
@ -418,7 +368,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 (dev_priv->vram_type == NV_MEM_TYPE_DDR2) {
|
||||
if (nvfb_vram_type(dev) == NV_MEM_TYPE_DDR2) {
|
||||
t->reg[5] |= (e->tCL + 3) << 8;
|
||||
t->reg[6] |= (t->tCWL - 2) << 8;
|
||||
t->reg[8] |= (e->tCL - 4);
|
||||
|
@ -711,7 +661,7 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq,
|
|||
break;
|
||||
}
|
||||
|
||||
switch (dev_priv->vram_type * !ret) {
|
||||
switch (nvfb_vram_type(dev) * !ret) {
|
||||
case NV_MEM_TYPE_GDDR3:
|
||||
ret = nouveau_mem_gddr3_mr(dev, freq, e, len, boot, t);
|
||||
break;
|
||||
|
@ -738,7 +688,7 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq,
|
|||
else
|
||||
dll_off = !!(ramcfg[2] & 0x40);
|
||||
|
||||
switch (dev_priv->vram_type) {
|
||||
switch (nvfb_vram_type(dev)) {
|
||||
case NV_MEM_TYPE_GDDR3:
|
||||
t->mr[1] &= ~0x00000040;
|
||||
t->mr[1] |= 0x00000040 * dll_off;
|
||||
|
@ -804,7 +754,7 @@ nouveau_mem_timing_read(struct drm_device *dev, struct nouveau_pm_memtiming *t)
|
|||
t->odt = 0;
|
||||
t->drive_strength = 0;
|
||||
|
||||
switch (dev_priv->vram_type) {
|
||||
switch (nvfb_vram_type(dev)) {
|
||||
case NV_MEM_TYPE_DDR3:
|
||||
t->odt |= (t->mr[1] & 0x200) >> 7;
|
||||
case NV_MEM_TYPE_DDR2:
|
||||
|
@ -831,7 +781,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 (dev_priv->vram_type) {
|
||||
switch (nvfb_vram_type(dev_priv->dev)) {
|
||||
case NV_MEM_TYPE_DDR2:
|
||||
tDLLK = 2000;
|
||||
mr1_dlloff = 0x00000001;
|
||||
|
@ -852,7 +802,7 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec,
|
|||
}
|
||||
|
||||
/* fetch current MRs */
|
||||
switch (dev_priv->vram_type) {
|
||||
switch (nvfb_vram_type(dev_priv->dev)) {
|
||||
case NV_MEM_TYPE_GDDR3:
|
||||
case NV_MEM_TYPE_DDR3:
|
||||
mr[2] = exec->mrg(exec, 2);
|
||||
|
@ -919,7 +869,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 (dev_priv->vram_type == NV_MEM_TYPE_GDDR3)
|
||||
if (nvfb_vram_type(dev_priv->dev) == NV_MEM_TYPE_GDDR3)
|
||||
exec->precharge(exec);
|
||||
}
|
||||
|
||||
|
@ -982,11 +932,10 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man,
|
|||
struct ttm_mem_reg *mem)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
|
||||
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
|
||||
nouveau_mem_node_cleanup(mem->mm_node);
|
||||
vram->put(dev, (struct nouveau_mem **)&mem->mm_node);
|
||||
nvfb_vram_put(dev, (struct nouveau_mem **)&mem->mm_node);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -996,7 +945,6 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
|
|||
struct ttm_mem_reg *mem)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
|
||||
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
struct nouveau_bo *nvbo = nouveau_bo(bo);
|
||||
struct nouveau_mem *node;
|
||||
|
@ -1006,7 +954,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 = vram->get(dev, mem->num_pages << PAGE_SHIFT,
|
||||
ret = nvfb_vram_get(dev, mem->num_pages << PAGE_SHIFT,
|
||||
mem->page_alignment << PAGE_SHIFT, size_nc,
|
||||
(nvbo->tile_flags >> 8) & 0x3ff, &node);
|
||||
if (ret) {
|
||||
|
|
|
@ -61,8 +61,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->instmem.map = nv04_instmem_map;
|
||||
engine->instmem.unmap = nv04_instmem_unmap;
|
||||
engine->instmem.flush = nv04_instmem_flush;
|
||||
engine->fb.init = nv04_fb_init;
|
||||
engine->fb.takedown = nv04_fb_takedown;
|
||||
engine->display.early_init = nv04_display_early_init;
|
||||
engine->display.late_takedown = nv04_display_late_takedown;
|
||||
engine->display.create = nv04_display_create;
|
||||
|
@ -72,9 +70,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->pm.clocks_get = nv04_pm_clocks_get;
|
||||
engine->pm.clocks_pre = nv04_pm_clocks_pre;
|
||||
engine->pm.clocks_set = nv04_pm_clocks_set;
|
||||
engine->vram.init = nv04_fb_vram_init;
|
||||
engine->vram.takedown = nouveau_stub_takedown;
|
||||
engine->vram.flags_valid = nouveau_mem_flags_valid;
|
||||
break;
|
||||
case 0x10:
|
||||
engine->instmem.init = nv04_instmem_init;
|
||||
|
@ -86,11 +81,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->instmem.map = nv04_instmem_map;
|
||||
engine->instmem.unmap = nv04_instmem_unmap;
|
||||
engine->instmem.flush = nv04_instmem_flush;
|
||||
engine->fb.init = nv10_fb_init;
|
||||
engine->fb.takedown = nv10_fb_takedown;
|
||||
engine->fb.init_tile_region = nv10_fb_init_tile_region;
|
||||
engine->fb.set_tile_region = nv10_fb_set_tile_region;
|
||||
engine->fb.free_tile_region = nv10_fb_free_tile_region;
|
||||
engine->display.early_init = nv04_display_early_init;
|
||||
engine->display.late_takedown = nv04_display_late_takedown;
|
||||
engine->display.create = nv04_display_create;
|
||||
|
@ -100,13 +90,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->pm.clocks_get = nv04_pm_clocks_get;
|
||||
engine->pm.clocks_pre = nv04_pm_clocks_pre;
|
||||
engine->pm.clocks_set = nv04_pm_clocks_set;
|
||||
if (dev_priv->chipset == 0x1a ||
|
||||
dev_priv->chipset == 0x1f)
|
||||
engine->vram.init = nv1a_fb_vram_init;
|
||||
else
|
||||
engine->vram.init = nv10_fb_vram_init;
|
||||
engine->vram.takedown = nouveau_stub_takedown;
|
||||
engine->vram.flags_valid = nouveau_mem_flags_valid;
|
||||
break;
|
||||
case 0x20:
|
||||
engine->instmem.init = nv04_instmem_init;
|
||||
|
@ -118,11 +101,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->instmem.map = nv04_instmem_map;
|
||||
engine->instmem.unmap = nv04_instmem_unmap;
|
||||
engine->instmem.flush = nv04_instmem_flush;
|
||||
engine->fb.init = nv20_fb_init;
|
||||
engine->fb.takedown = nv20_fb_takedown;
|
||||
engine->fb.init_tile_region = nv20_fb_init_tile_region;
|
||||
engine->fb.set_tile_region = nv20_fb_set_tile_region;
|
||||
engine->fb.free_tile_region = nv20_fb_free_tile_region;
|
||||
engine->display.early_init = nv04_display_early_init;
|
||||
engine->display.late_takedown = nv04_display_late_takedown;
|
||||
engine->display.create = nv04_display_create;
|
||||
|
@ -132,9 +110,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->pm.clocks_get = nv04_pm_clocks_get;
|
||||
engine->pm.clocks_pre = nv04_pm_clocks_pre;
|
||||
engine->pm.clocks_set = nv04_pm_clocks_set;
|
||||
engine->vram.init = nv20_fb_vram_init;
|
||||
engine->vram.takedown = nouveau_stub_takedown;
|
||||
engine->vram.flags_valid = nouveau_mem_flags_valid;
|
||||
break;
|
||||
case 0x30:
|
||||
engine->instmem.init = nv04_instmem_init;
|
||||
|
@ -146,11 +121,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->instmem.map = nv04_instmem_map;
|
||||
engine->instmem.unmap = nv04_instmem_unmap;
|
||||
engine->instmem.flush = nv04_instmem_flush;
|
||||
engine->fb.init = nv30_fb_init;
|
||||
engine->fb.takedown = nv30_fb_takedown;
|
||||
engine->fb.init_tile_region = nv30_fb_init_tile_region;
|
||||
engine->fb.set_tile_region = nv10_fb_set_tile_region;
|
||||
engine->fb.free_tile_region = nv30_fb_free_tile_region;
|
||||
engine->display.early_init = nv04_display_early_init;
|
||||
engine->display.late_takedown = nv04_display_late_takedown;
|
||||
engine->display.create = nv04_display_create;
|
||||
|
@ -162,9 +132,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->pm.clocks_set = nv04_pm_clocks_set;
|
||||
engine->pm.voltage_get = nouveau_voltage_gpio_get;
|
||||
engine->pm.voltage_set = nouveau_voltage_gpio_set;
|
||||
engine->vram.init = nv20_fb_vram_init;
|
||||
engine->vram.takedown = nouveau_stub_takedown;
|
||||
engine->vram.flags_valid = nouveau_mem_flags_valid;
|
||||
break;
|
||||
case 0x40:
|
||||
case 0x60:
|
||||
|
@ -177,11 +144,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->instmem.map = nv04_instmem_map;
|
||||
engine->instmem.unmap = nv04_instmem_unmap;
|
||||
engine->instmem.flush = nv04_instmem_flush;
|
||||
engine->fb.init = nv40_fb_init;
|
||||
engine->fb.takedown = nv40_fb_takedown;
|
||||
engine->fb.init_tile_region = nv30_fb_init_tile_region;
|
||||
engine->fb.set_tile_region = nv40_fb_set_tile_region;
|
||||
engine->fb.free_tile_region = nv30_fb_free_tile_region;
|
||||
engine->display.early_init = nv04_display_early_init;
|
||||
engine->display.late_takedown = nv04_display_late_takedown;
|
||||
engine->display.create = nv04_display_create;
|
||||
|
@ -196,9 +158,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->pm.temp_get = nv40_temp_get;
|
||||
engine->pm.pwm_get = nv40_pm_pwm_get;
|
||||
engine->pm.pwm_set = nv40_pm_pwm_set;
|
||||
engine->vram.init = nv40_fb_vram_init;
|
||||
engine->vram.takedown = nouveau_stub_takedown;
|
||||
engine->vram.flags_valid = nouveau_mem_flags_valid;
|
||||
break;
|
||||
case 0x50:
|
||||
case 0x80: /* gotta love NVIDIA's consistency.. */
|
||||
|
@ -216,8 +175,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->instmem.flush = nv50_instmem_flush;
|
||||
else
|
||||
engine->instmem.flush = nv84_instmem_flush;
|
||||
engine->fb.init = nv50_fb_init;
|
||||
engine->fb.takedown = nv50_fb_takedown;
|
||||
engine->display.early_init = nv50_display_early_init;
|
||||
engine->display.late_takedown = nv50_display_late_takedown;
|
||||
engine->display.create = nv50_display_create;
|
||||
|
@ -253,11 +210,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->pm.temp_get = nv40_temp_get;
|
||||
engine->pm.pwm_get = nv50_pm_pwm_get;
|
||||
engine->pm.pwm_set = nv50_pm_pwm_set;
|
||||
engine->vram.init = nv50_vram_init;
|
||||
engine->vram.takedown = nv50_vram_fini;
|
||||
engine->vram.get = nv50_vram_new;
|
||||
engine->vram.put = nv50_vram_del;
|
||||
engine->vram.flags_valid = nv50_vram_flags_valid;
|
||||
break;
|
||||
case 0xc0:
|
||||
engine->instmem.init = nvc0_instmem_init;
|
||||
|
@ -269,19 +221,12 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->instmem.map = nv50_instmem_map;
|
||||
engine->instmem.unmap = nv50_instmem_unmap;
|
||||
engine->instmem.flush = nv84_instmem_flush;
|
||||
engine->fb.init = nvc0_fb_init;
|
||||
engine->fb.takedown = nvc0_fb_takedown;
|
||||
engine->display.early_init = nv50_display_early_init;
|
||||
engine->display.late_takedown = nv50_display_late_takedown;
|
||||
engine->display.create = nv50_display_create;
|
||||
engine->display.destroy = nv50_display_destroy;
|
||||
engine->display.init = nv50_display_init;
|
||||
engine->display.fini = nv50_display_fini;
|
||||
engine->vram.init = nvc0_vram_init;
|
||||
engine->vram.takedown = nv50_vram_fini;
|
||||
engine->vram.get = nvc0_vram_new;
|
||||
engine->vram.put = nv50_vram_del;
|
||||
engine->vram.flags_valid = nvc0_vram_flags_valid;
|
||||
engine->pm.temp_get = nv84_temp_get;
|
||||
engine->pm.clocks_get = nvc0_pm_clocks_get;
|
||||
engine->pm.clocks_pre = nvc0_pm_clocks_pre;
|
||||
|
@ -301,19 +246,12 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->instmem.map = nv50_instmem_map;
|
||||
engine->instmem.unmap = nv50_instmem_unmap;
|
||||
engine->instmem.flush = nv84_instmem_flush;
|
||||
engine->fb.init = nvc0_fb_init;
|
||||
engine->fb.takedown = nvc0_fb_takedown;
|
||||
engine->display.early_init = nouveau_stub_init;
|
||||
engine->display.late_takedown = nouveau_stub_takedown;
|
||||
engine->display.create = nvd0_display_create;
|
||||
engine->display.destroy = nvd0_display_destroy;
|
||||
engine->display.init = nvd0_display_init;
|
||||
engine->display.fini = nvd0_display_fini;
|
||||
engine->vram.init = nvc0_vram_init;
|
||||
engine->vram.takedown = nv50_vram_fini;
|
||||
engine->vram.get = nvc0_vram_new;
|
||||
engine->vram.put = nv50_vram_del;
|
||||
engine->vram.flags_valid = nvc0_vram_flags_valid;
|
||||
engine->pm.temp_get = nv84_temp_get;
|
||||
engine->pm.clocks_get = nvc0_pm_clocks_get;
|
||||
engine->pm.clocks_pre = nvc0_pm_clocks_pre;
|
||||
|
@ -331,19 +269,12 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->instmem.map = nv50_instmem_map;
|
||||
engine->instmem.unmap = nv50_instmem_unmap;
|
||||
engine->instmem.flush = nv84_instmem_flush;
|
||||
engine->fb.init = nvc0_fb_init;
|
||||
engine->fb.takedown = nvc0_fb_takedown;
|
||||
engine->display.early_init = nouveau_stub_init;
|
||||
engine->display.late_takedown = nouveau_stub_takedown;
|
||||
engine->display.create = nvd0_display_create;
|
||||
engine->display.destroy = nvd0_display_destroy;
|
||||
engine->display.init = nvd0_display_init;
|
||||
engine->display.fini = nvd0_display_fini;
|
||||
engine->vram.init = nvc0_vram_init;
|
||||
engine->vram.takedown = nv50_vram_fini;
|
||||
engine->vram.get = nvc0_vram_new;
|
||||
engine->vram.put = nv50_vram_del;
|
||||
engine->vram.flags_valid = nvc0_vram_flags_valid;
|
||||
break;
|
||||
default:
|
||||
NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
|
||||
|
@ -488,18 +419,9 @@ nouveau_card_init(struct drm_device *dev)
|
|||
nv_mask(dev, 0x00088080, 0x00000800, 0x00000000);
|
||||
}
|
||||
|
||||
/* PFB */
|
||||
ret = engine->fb.init(dev);
|
||||
if (ret)
|
||||
goto out_bios;
|
||||
|
||||
ret = engine->vram.init(dev);
|
||||
if (ret)
|
||||
goto out_fb;
|
||||
|
||||
ret = nouveau_gpuobj_init(dev);
|
||||
if (ret)
|
||||
goto out_vram;
|
||||
goto out_bios;
|
||||
|
||||
ret = engine->instmem.init(dev);
|
||||
if (ret)
|
||||
|
@ -734,10 +656,6 @@ out_instmem:
|
|||
engine->instmem.takedown(dev);
|
||||
out_gpuobj:
|
||||
nouveau_gpuobj_takedown(dev);
|
||||
out_vram:
|
||||
engine->vram.takedown(dev);
|
||||
out_fb:
|
||||
engine->fb.takedown(dev);
|
||||
out_bios:
|
||||
nouveau_bios_takedown(dev);
|
||||
out_display_early:
|
||||
|
@ -788,9 +706,6 @@ static void nouveau_card_takedown(struct drm_device *dev)
|
|||
engine->instmem.takedown(dev);
|
||||
nouveau_gpuobj_takedown(dev);
|
||||
|
||||
engine->vram.takedown(dev);
|
||||
engine->fb.takedown(dev);
|
||||
|
||||
nouveau_bios_takedown(dev);
|
||||
engine->display.late_takedown(dev);
|
||||
|
||||
|
|
|
@ -26,51 +26,12 @@
|
|||
*/
|
||||
|
||||
#include <linux/ratelimit.h>
|
||||
|
||||
#include "nouveau_util.h"
|
||||
|
||||
#include <core/enum.h>
|
||||
|
||||
static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20);
|
||||
|
||||
void
|
||||
nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value)
|
||||
{
|
||||
while (bf->name) {
|
||||
if (value & bf->mask) {
|
||||
printk(" %s", bf->name);
|
||||
value &= ~bf->mask;
|
||||
}
|
||||
|
||||
bf++;
|
||||
}
|
||||
|
||||
if (value)
|
||||
printk(" (unknown bits 0x%08x)", value);
|
||||
}
|
||||
|
||||
const struct nouveau_enum *
|
||||
nouveau_enum_find(const struct nouveau_enum *en, u32 value)
|
||||
{
|
||||
while (en->name) {
|
||||
if (en->value == value)
|
||||
return en;
|
||||
en++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_enum_print(const struct nouveau_enum *en, u32 value)
|
||||
{
|
||||
en = nouveau_enum_find(en, value);
|
||||
if (en) {
|
||||
printk("%s", en->name);
|
||||
return;
|
||||
}
|
||||
|
||||
printk("(unknown enum 0x%08x)", value);
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_ratelimit(void)
|
||||
{
|
||||
|
|
|
@ -28,21 +28,7 @@
|
|||
#ifndef __NOUVEAU_UTIL_H__
|
||||
#define __NOUVEAU_UTIL_H__
|
||||
|
||||
struct nouveau_bitfield {
|
||||
u32 mask;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct nouveau_enum {
|
||||
u32 value;
|
||||
const char *name;
|
||||
void *data;
|
||||
};
|
||||
|
||||
void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value);
|
||||
void nouveau_enum_print(const struct nouveau_enum *, u32 value);
|
||||
const struct nouveau_enum *
|
||||
nouveau_enum_find(const struct nouveau_enum *, u32 value);
|
||||
#include <core/enum.h>
|
||||
|
||||
int nouveau_ratelimit(void);
|
||||
|
||||
|
|
|
@ -300,24 +300,24 @@ nv50_evo_create(struct drm_device *dev)
|
|||
|
||||
/* create some default objects for the scanout memtypes we support */
|
||||
ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM, 0x0000,
|
||||
0, dev_priv->vram_size, NULL);
|
||||
0, nvfb_vram_size(dev), NULL);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM_LP, 0x80000000,
|
||||
0, dev_priv->vram_size, NULL);
|
||||
0, nvfb_vram_size(dev), NULL);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 |
|
||||
(dev_priv->chipset < 0xc0 ? 0x7a00 : 0xfe00),
|
||||
0, dev_priv->vram_size, NULL);
|
||||
0, nvfb_vram_size(dev), NULL);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 |
|
||||
(dev_priv->chipset < 0xc0 ? 0x7000 : 0xfe00),
|
||||
0, dev_priv->vram_size, NULL);
|
||||
0, nvfb_vram_size(dev), NULL);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
@ -352,21 +352,21 @@ nv50_evo_create(struct drm_device *dev)
|
|||
goto err;
|
||||
|
||||
ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000,
|
||||
0, dev_priv->vram_size, NULL);
|
||||
0, nvfb_vram_size(dev), NULL);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 |
|
||||
(dev_priv->chipset < 0xc0 ?
|
||||
0x7a00 : 0xfe00),
|
||||
0, dev_priv->vram_size, NULL);
|
||||
0, nvfb_vram_size(dev), NULL);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 |
|
||||
(dev_priv->chipset < 0xc0 ?
|
||||
0x7000 : 0xfe00),
|
||||
0, dev_priv->vram_size, NULL);
|
||||
0, nvfb_vram_size(dev), NULL);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
|
|
@ -471,17 +471,16 @@ mclk_mrg(struct nouveau_mem_exec_func *exec, int mr)
|
|||
static void
|
||||
mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = exec->dev->dev_private;
|
||||
struct nv50_pm_state *info = exec->priv;
|
||||
struct hwsq_ucode *hwsq = &info->mclk_hwsq;
|
||||
|
||||
if (mr <= 1) {
|
||||
if (dev_priv->vram_rank_B)
|
||||
if (nvfb_vram_rank_B(exec->dev))
|
||||
hwsq_wr32(hwsq, 0x1002c8 + ((mr - 0) * 4), data);
|
||||
hwsq_wr32(hwsq, 0x1002c0 + ((mr - 0) * 4), data);
|
||||
} else
|
||||
if (mr <= 3) {
|
||||
if (dev_priv->vram_rank_B)
|
||||
if (nvfb_vram_rank_B(exec->dev))
|
||||
hwsq_wr32(hwsq, 0x1002e8 + ((mr - 2) * 4), data);
|
||||
hwsq_wr32(hwsq, 0x1002e0 + ((mr - 2) * 4), data);
|
||||
}
|
||||
|
|
|
@ -361,15 +361,13 @@ mclk_mrg(struct nouveau_mem_exec_func *exec, int mr)
|
|||
static void
|
||||
mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = exec->dev->dev_private;
|
||||
|
||||
if (mr <= 1) {
|
||||
if (dev_priv->vram_rank_B)
|
||||
if (nvfb_vram_rank_B(exec->dev))
|
||||
nv_wr32(exec->dev, 0x1002c8 + ((mr - 0) * 4), data);
|
||||
nv_wr32(exec->dev, 0x1002c0 + ((mr - 0) * 4), data);
|
||||
} else
|
||||
if (mr <= 3) {
|
||||
if (dev_priv->vram_rank_B)
|
||||
if (nvfb_vram_rank_B(exec->dev))
|
||||
nv_wr32(exec->dev, 0x1002e8 + ((mr - 2) * 4), data);
|
||||
nv_wr32(exec->dev, 0x1002e0 + ((mr - 2) * 4), data);
|
||||
}
|
||||
|
|
|
@ -459,8 +459,7 @@ static u32
|
|||
mclk_mrg(struct nouveau_mem_exec_func *exec, int mr)
|
||||
{
|
||||
struct drm_device *dev = exec->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
if (dev_priv->vram_type != NV_MEM_TYPE_GDDR5) {
|
||||
if (nvfb_vram_type(dev) != NV_MEM_TYPE_GDDR5) {
|
||||
if (mr <= 1)
|
||||
return nv_rd32(dev, 0x10f300 + ((mr - 0) * 4));
|
||||
return nv_rd32(dev, 0x10f320 + ((mr - 2) * 4));
|
||||
|
@ -478,16 +477,15 @@ static void
|
|||
mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data)
|
||||
{
|
||||
struct drm_device *dev = exec->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
if (dev_priv->vram_type != NV_MEM_TYPE_GDDR5) {
|
||||
if (nvfb_vram_type(dev) != NV_MEM_TYPE_GDDR5) {
|
||||
if (mr <= 1) {
|
||||
nv_wr32(dev, 0x10f300 + ((mr - 0) * 4), data);
|
||||
if (dev_priv->vram_rank_B)
|
||||
if (nvfb_vram_rank_B(dev))
|
||||
nv_wr32(dev, 0x10f308 + ((mr - 0) * 4), data);
|
||||
} else
|
||||
if (mr <= 3) {
|
||||
nv_wr32(dev, 0x10f320 + ((mr - 2) * 4), data);
|
||||
if (dev_priv->vram_rank_B)
|
||||
if (nvfb_vram_rank_B(dev))
|
||||
nv_wr32(dev, 0x10f328 + ((mr - 2) * 4), data);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -2077,7 +2077,7 @@ nvd0_display_create(struct drm_device *dev)
|
|||
|
||||
nv_wo32(disp->mem, dmao + 0x20, 0x00000049);
|
||||
nv_wo32(disp->mem, dmao + 0x24, 0x00000000);
|
||||
nv_wo32(disp->mem, dmao + 0x28, (dev_priv->vram_size - 1) >> 8);
|
||||
nv_wo32(disp->mem, dmao + 0x28, (nvfb_vram_size(dev) - 1) >> 8);
|
||||
nv_wo32(disp->mem, dmao + 0x2c, 0x00000000);
|
||||
nv_wo32(disp->mem, dmao + 0x30, 0x00000000);
|
||||
nv_wo32(disp->mem, dmao + 0x34, 0x00000000);
|
||||
|
@ -2087,7 +2087,7 @@ nvd0_display_create(struct drm_device *dev)
|
|||
|
||||
nv_wo32(disp->mem, dmao + 0x40, 0x00000009);
|
||||
nv_wo32(disp->mem, dmao + 0x44, 0x00000000);
|
||||
nv_wo32(disp->mem, dmao + 0x48, (dev_priv->vram_size - 1) >> 8);
|
||||
nv_wo32(disp->mem, dmao + 0x48, (nvfb_vram_size(dev) - 1) >> 8);
|
||||
nv_wo32(disp->mem, dmao + 0x4c, 0x00000000);
|
||||
nv_wo32(disp->mem, dmao + 0x50, 0x00000000);
|
||||
nv_wo32(disp->mem, dmao + 0x54, 0x00000000);
|
||||
|
@ -2097,7 +2097,7 @@ nvd0_display_create(struct drm_device *dev)
|
|||
|
||||
nv_wo32(disp->mem, dmao + 0x60, 0x0fe00009);
|
||||
nv_wo32(disp->mem, dmao + 0x64, 0x00000000);
|
||||
nv_wo32(disp->mem, dmao + 0x68, (dev_priv->vram_size - 1) >> 8);
|
||||
nv_wo32(disp->mem, dmao + 0x68, (nvfb_vram_size(dev) - 1) >> 8);
|
||||
nv_wo32(disp->mem, dmao + 0x6c, 0x00000000);
|
||||
nv_wo32(disp->mem, dmao + 0x70, 0x00000000);
|
||||
nv_wo32(disp->mem, dmao + 0x74, 0x00000000);
|
||||
|
|
Загрузка…
Ссылка в новой задаче