diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-07-11 13:05:01 +0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-10-03 07:12:49 +0400 |
commit | 861d21074bbb141b0cc165a61c11f571571cda12 (patch) | |
tree | fd5755cab318f77276044a40bcc274a6f8fe1ec1 | |
parent | 0134a97979a0abc1c756b0fe491e074693c2bdf5 (diff) | |
download | linux-861d21074bbb141b0cc165a61c11f571571cda12.tar.xz |
drm/nouveau/fb: merge fb/vram and port to subdev interfaces
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
49 files changed, 1691 insertions, 1345 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 0615e954d238..5e18a53e2c0c 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -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 diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index 3079f080d40e..23ae4591b7bd 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c index 19e303b423af..d006658e6468 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c @@ -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); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c index 718ecf761823..dd31156e3029 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -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); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 4ad9759f821e..ab3af6d15381 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -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 */ diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c index 4a14a6763dac..eb5455fed1bf 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c @@ -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); diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h new file mode 100644 index 000000000000..91dbdc16ac94 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h @@ -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 diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h new file mode 100644 index 000000000000..f351f63bc654 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h @@ -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 diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h index 7c1fc2114fec..6d3764b416f4 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h @@ -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]; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index aa43bd5c2374..66b7156281c9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -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"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index 1926c33fb6f8..cf81479725ad 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -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"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index 88729c308565..e97280cd43b0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -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"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index 4feea8804a78..ddd3ab6cb733 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -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"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index 8f683613788d..c7ea921e0309 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -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"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index e844525d5694..e60cdf26ebf9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -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"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 56d1950c9b77..8de67307eea7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -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"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index ab5e05291465..919a10280d7e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -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"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/base.c b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c new file mode 100644 index 000000000000..f0086de8af31 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c @@ -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; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c index eef48440fbec..eb06836b69f7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c @@ -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) +{ + if (!(tile_flags & 0xff00)) + return true; + + return false; +} + +static int +nv04_fb_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 boot0 = nv_rd32(dev, NV04_PFB_BOOT_0); + 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; -} - -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; + priv->base.memtype_valid = nv04_fb_memtype_valid; + return nouveau_fb_created(&priv->base); } -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, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c index 09af63b55f59..f037a422d2f4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c @@ -1,104 +1,120 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include <nouveau_drm.h> - -void -nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch, uint32_t flags) +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include <subdev/fb.h> + +struct 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; - - bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); - if (!bridge) { - NV_ERROR(dev, "no bridge device\n"); - return 0; - } - - if (dev_priv->chipset == 0x1a) { - pci_read_config_dword(bridge, 0x7c, &mem); - mib = ((mem >> 6) & 31) + 1; + struct nouveau_device *device = nv_device(parent); + struct nv10_fb_priv *priv; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + if (device->chipset == 0x1a || device->chipset == 0x1f) { + struct pci_dev *bridge; + u32 mem, mib; + + bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); + if (!bridge) { + nv_fatal(device, "no bridge device\n"); + return 0; + } + + if (device->chipset == 0x1a) { + pci_read_config_dword(bridge, 0x7c, &mem); + mib = ((mem >> 6) & 31) + 1; + } else { + pci_read_config_dword(bridge, 0x84, &mem); + mib = ((mem >> 4) & 127) + 1; + } + + priv->base.ram.type = NV_MEM_TYPE_STOLEN; + priv->base.ram.size = mib * 1024 * 1024; } else { - 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; - dev_priv->vram_size = mib * 1024 * 1024; - return 0; -} - -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); + priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000; + } - 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); } -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, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c index a7f056c367e4..4b3578fcb7fb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c @@ -1,49 +1,41 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include <nouveau_drm.h> - -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; - - 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; -} +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include <subdev/fb.h> + +struct 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; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - dev_priv->vram_size = mem_size & 0xff000000; + 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); - - /* 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; + ret = nouveau_mm_init(&priv->base.tags, 0, 32 * 1024, 1); + if (ret) + return ret; + + priv->base.memtype_valid = nv04_fb_memtype_valid; + priv->base.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, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c index 30639a065273..cba67bc91390 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c @@ -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; - - pfb->num_tiles = NV10_PFB_TILE__SIZE; + struct nouveau_device *device = nv_device(object); + struct nv30_fb_priv *priv = (void *)object; + int ret, i, j; - /* 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, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c index e08c2e1c8f1f..84aa71c47128 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c @@ -1,55 +1,83 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include <nouveau_drm.h> - -void -nv40_fb_set_tile_region(struct drm_device *dev, int i) +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include <subdev/fb.h> + +struct 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; + return !(0x0baf & (1 << (device->chipset & 0x0f))); +} - 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; - } +static void +nv40_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) +{ + nv_wr32(pfb, 0x100604 + (i * 0x10), tile->limit); + nv_wr32(pfb, 0x100608 + (i * 0x10), tile->pitch); + nv_wr32(pfb, 0x100600 + (i * 0x10), tile->addr); } static void -nv40_fb_init_gart(struct drm_device *dev) +nv40_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; - if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { - nv_wr32(dev, 0x100800, 0x00000001); + 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(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 +} + +static int +nv40_fb_init(struct nouveau_object *object) +{ + 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; + } - 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); + return 0; } -int -nv40_fb_vram_init(struct drm_device *dev) +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 drm_nouveau_private *dev_priv = dev->dev_private; + 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; -} - -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); - } + priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000; - 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; } - - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) - pfb->set_tile_region(dev, i); - - return 0; + 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; + + 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, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index a145b1c81ecb..eaf18fb2c306 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -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) +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 +}; + +static bool +nv50_fb_memtype_valid(struct nouveau_fb *pfb, u32 memtype) { - 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; + return types[(memtype & 0xff00) >> 8] != 0; +} - if (drm_mm_initialized(&pfb->tag_heap)) - drm_mm_takedown(&pfb->tag_heap); +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; - if (priv->r100c08_page) { - pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - __free_page(priv->r100c08_page); + 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; } - kfree(priv); - pfb->priv = NULL; + 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; } -static int -nv50_fb_create(struct drm_device *dev) +void +nv50_fb_vram_del(struct nouveau_fb *pfb, struct nouveau_mem **pmem) { - 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; - int ret; + struct nv50_fb_priv *priv = (void *)pfb; + struct nouveau_mm_node *this; + struct nouveau_mem *mem; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - pfb->priv = priv; + mem = *pmem; + *pmem = NULL; + if (unlikely(mem == NULL)) + return; - priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (!priv->r100c08_page) { - nv50_fb_destroy(dev); - return -ENOMEM; + 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); } - 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; + 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++; } - 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); - return ret; + 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)); } - return 0; + rblock_size = rowsize; + if (rt & 1) + rblock_size *= 3; + + nv_debug(priv, "rblock %d bytes\n", rblock_size); + return rblock_size; } -int -nv50_fb_init(struct drm_device *dev) +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 drm_nouveau_private *dev_priv = dev->dev_private; + 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; - if (!dev_priv->engine.fb.priv) { - ret = nv50_fb_create(dev); + 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 = dev_priv->engine.fb.priv; + + 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(device->pdev, priv->r100c08, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + __free_page(priv->r100c08_page); + } + + nouveau_mm_fini(&priv->base.vram); + nouveau_fb_destroy(&priv->base); +} + +static int +nv50_fb_init(struct nouveau_object *object) +{ + struct nouveau_device *device = nv_device(object); + struct nv50_fb_priv *priv = (void *)object; + int ret; + + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; /* 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) diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c deleted file mode 100644 index 84b99b608b2b..000000000000 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c +++ /dev/null @@ -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); -} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c index f054331e37d8..9f59f2bf0079 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c @@ -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) +/* 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 +}; + +static bool +nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags) { - u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400); - u32 stat = nv_rd32(dev, subp_base + 0x020); + u8 memtype = (tile_flags & 0x0000ff00) >> 8; + return likely((types[memtype] == 1)); +} - if (stat) { - NV_INFO(dev, "PMFB%d_SUBP%d: 0x%08x\n", unit, subp, stat); - nv_wr32(dev, subp_base + 0x020, stat); - } +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 void -nvc0_mfb_isr(struct drm_device *dev) +static int +nvc0_fb_init(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); - } + struct nvc0_fb_priv *priv = (void *)object; + int ret; + + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; - /* 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); + nv_wr32(priv, 0x100c10, priv->r100c10 >> 8); + return 0; } static void -nvc0_fb_destroy(struct drm_device *dev) +nvc0_fb_dtor(struct nouveau_object *object) { - 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; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - pfb->priv = priv; + struct nouveau_bios *bios = nouveau_bios(priv); + struct nouveau_fb *pfb = &priv->base; + const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ + const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ + u32 parts = nv_rd32(priv, 0x022438); + u32 pmask = nv_rd32(priv, 0x022554); + u32 bsize = nv_rd32(priv, 0x10f20c); + u32 offset, length; + bool uniform = true; + int ret, part; + + nv_debug(priv, "0x100800: 0x%08x\n", nv_rd32(priv, 0x100800)); + nv_debug(priv, "parts 0x%08x mask 0x%08x\n", parts, pmask); + + priv->base.ram.type = nouveau_fb_bios_memtype(bios); + priv->base.ram.ranks = (nv_rd32(priv, 0x10f200) & 0x00000004) ? 2 : 1; + + /* read amount of vram attached to each memory controller */ + for (part = 0; part < parts; part++) { + if (!(pmask & (1 << part))) { + u32 psize = nv_rd32(priv, 0x11020c + (part * 0x1000)); + if (psize != bsize) { + if (psize < bsize) + bsize = psize; + uniform = false; + } + + nv_debug(priv, "%d: mem_amount 0x%08x\n", part, psize); + priv->base.ram.size += (u64)psize << 20; + } + } - priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (!priv->r100c10_page) { - nvc0_fb_destroy(dev); - return -ENOMEM; + /* 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); } - 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; + /* 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; -void -nvc0_fb_takedown(struct drm_device *dev) -{ - nvc0_fb_destroy(dev); + 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); } + + +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, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c deleted file mode 100644 index f363234a3f44..000000000000 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c +++ /dev/null @@ -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; -} diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c index 5965eb7cf390..24d077a1d842 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c @@ -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); } diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c new file mode 100644 index 000000000000..7c2840cc2bbf --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c @@ -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, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c index 3fa39bb9a724..bd9e99463ff7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c @@ -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 }, {}, diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c index eeac72f40201..7e46826de0e9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c @@ -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); } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index d95275437a4b..f63785c2aae0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -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) && diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.c b/drivers/gpu/drm/nouveau/nouveau_compat.c index 7880ebb9a7d9..3d65c1763311 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.c +++ b/drivers/gpu/drm/nouveau/nouveau_compat.c @@ -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); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.h b/drivers/gpu/drm/nouveau/nouveau_compat.h index c9622ebf5cbe..d047a2046959 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.h +++ b/drivers/gpu/drm/nouveau/nouveau_compat.h @@ -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 diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c index 188c92b327e2..6564b547973e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c @@ -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; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 7223a4f69231..3f660a94dd18 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -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); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index b4595990f5e8..c7bc6ecad601 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -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 diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h index f3fb649fe454..d767567977ee 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fb.h +++ b/drivers/gpu/drm/nouveau/nouveau_fb.h @@ -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; diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 9b078033ec19..f3f0b4c362cb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index c8bb9f230222..96a34bce54ce 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -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; } diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 689d3e708057..4aea1c4c46ef 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -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) { diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 3b11962d7d6d..d8d9e5c527a4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -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); diff --git a/drivers/gpu/drm/nouveau/nouveau_util.c b/drivers/gpu/drm/nouveau/nouveau_util.c index e51b51503baa..6bff634c95fe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_util.c +++ b/drivers/gpu/drm/nouveau/nouveau_util.c @@ -26,50 +26,11 @@ */ #include <linux/ratelimit.h> - #include "nouveau_util.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); -} +#include <core/enum.h> -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); -} +static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); int nouveau_ratelimit(void) diff --git a/drivers/gpu/drm/nouveau/nouveau_util.h b/drivers/gpu/drm/nouveau/nouveau_util.h index b97719fbb739..114293758f8c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_util.h +++ b/drivers/gpu/drm/nouveau/nouveau_util.h @@ -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); diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c index 5731cb3df67f..7a1424243665 100644 --- a/drivers/gpu/drm/nouveau/nv50_evo.c +++ b/drivers/gpu/drm/nouveau/nv50_evo.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index 378ca8ca9d6a..142cd4e83767 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c @@ -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); } diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c index 847c616de12f..2f7ee50440ae 100644 --- a/drivers/gpu/drm/nouveau/nva3_pm.c +++ b/drivers/gpu/drm/nouveau/nva3_pm.c @@ -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); } diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c index 4a21a7264c3c..a14711c25176 100644 --- a/drivers/gpu/drm/nouveau/nvc0_pm.c +++ b/drivers/gpu/drm/nouveau/nvc0_pm.c @@ -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 { diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index d26dd02f3d13..8d9fc00718f0 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -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); |