drm/nvc0: initial support for tiled buffer objects
authorBen Skeggs <bskeggs@redhat.com>
Wed, 8 Dec 2010 01:19:30 +0000 (11:19 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 21 Dec 2010 07:18:42 +0000 (17:18 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_dma.h
drivers/gpu/drm/nouveau/nv50_crtc.c
drivers/gpu/drm/nouveau/nv50_evo.c
drivers/gpu/drm/nouveau/nvc0_vram.c

index 5dc639e0c969a2ce2df3b98b1b8b06b126b3b811..74d0ef41118dd613da5b60a40a43c8458c67e161 100644 (file)
@@ -120,9 +120,6 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
        align >>= PAGE_SHIFT;
 
        if (!nvbo->no_vm && dev_priv->chan_vm) {
-               if (dev_priv->card_type == NV_C0)
-                       page_shift = 12;
-
                ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift,
                                     NV_MEM_ACCESS_RW, &nvbo->vma);
                if (ret) {
index c118a331b5bc080305d9c76891c5809cfa01252a..c36f1763feaace442608126fff9c15ff49d148eb 100644 (file)
@@ -77,7 +77,8 @@ enum {
        /* G80+ display objects */
        NvEvoVRAM       = 0x01000000,
        NvEvoFB16       = 0x01000001,
-       NvEvoFB32       = 0x01000002
+       NvEvoFB32       = 0x01000002,
+       NvEvoVRAM_LP    = 0x01000003
 };
 
 #define NV_MEMORY_TO_MEMORY_FORMAT                                    0x00000039
index 2c346f797285e973645dc893747288a4d4466e08..9023c4dbb449e0dc78b78108dab3a10945ca0c74 100644 (file)
@@ -115,15 +115,16 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked)
                OUT_RING(evo, 0);
                BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1);
                if (dev_priv->chipset != 0x50)
-                       if (nv_crtc->fb.tile_flags == 0x7a00)
+                       if (nv_crtc->fb.tile_flags == 0x7a00 ||
+                           nv_crtc->fb.tile_flags == 0xfe00)
                                OUT_RING(evo, NvEvoFB32);
                        else
                        if (nv_crtc->fb.tile_flags == 0x7000)
                                OUT_RING(evo, NvEvoFB16);
                        else
-                               OUT_RING(evo, NvEvoVRAM);
+                               OUT_RING(evo, NvEvoVRAM_LP);
                else
-                       OUT_RING(evo, NvEvoVRAM);
+                       OUT_RING(evo, NvEvoVRAM_LP);
        }
 
        nv_crtc->fb.blanked = blanked;
@@ -555,13 +556,14 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
                        return ret;
 
                BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1);
-               if (nv_crtc->fb.tile_flags == 0x7a00)
+               if (nv_crtc->fb.tile_flags == 0x7a00 ||
+                   nv_crtc->fb.tile_flags == 0xfe00)
                        OUT_RING(evo, NvEvoFB32);
                else
                if (nv_crtc->fb.tile_flags == 0x7000)
                        OUT_RING(evo, NvEvoFB16);
                else
-                       OUT_RING(evo, NvEvoVRAM);
+                       OUT_RING(evo, NvEvoVRAM_LP);
        }
 
        ret = RING_SPACE(evo, 12);
@@ -575,8 +577,10 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
        if (!nv_crtc->fb.tile_flags) {
                OUT_RING(evo, drm_fb->pitch | (1 << 20));
        } else {
-               OUT_RING(evo, ((drm_fb->pitch / 4) << 4) |
-                                 fb->nvbo->tile_mode);
+               u32 tile_mode = fb->nvbo->tile_mode;
+               if (dev_priv->card_type >= NV_C0)
+                       tile_mode >>= 4;
+               OUT_RING(evo, ((drm_fb->pitch / 4) << 4) | tile_mode);
        }
        if (dev_priv->chipset == 0x50)
                OUT_RING(evo, (nv_crtc->fb.tile_flags << 8) | format);
index 887b2a97e2a208df8ff5a29183fb6cba16a06219..14e24e906ee89bcaf9ddcfefc980b1f2712b36a0 100644 (file)
@@ -53,7 +53,8 @@ nv50_evo_channel_del(struct nouveau_channel **pevo)
 
 int
 nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name,
-                   u32 tile_flags, u32 magic_flags, u32 offset, u32 limit)
+                   u32 tile_flags, u32 magic_flags, u32 offset, u32 limit,
+                   u32 flags5)
 {
        struct drm_nouveau_private *dev_priv = evo->dev->dev_private;
        struct drm_device *dev = evo->dev;
@@ -70,10 +71,7 @@ nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name,
        nv_wo32(obj,  8, offset);
        nv_wo32(obj, 12, 0x00000000);
        nv_wo32(obj, 16, 0x00000000);
-       if (dev_priv->card_type < NV_C0)
-               nv_wo32(obj, 20, 0x00010000);
-       else
-               nv_wo32(obj, 20, 0x00020000);
+       nv_wo32(obj, 20, flags5);
        dev_priv->engine.instmem.flush(dev);
 
        ret = nouveau_ramht_insert(evo, name, obj);
@@ -264,9 +262,31 @@ nv50_evo_create(struct drm_device *dev)
        }
 
        /* create some default objects for the scanout memtypes we support */
+       if (dev_priv->card_type >= NV_C0) {
+               ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0xfe, 0x19,
+                                         0, 0xffffffff, 0x00000000);
+               if (ret) {
+                       nv50_evo_channel_del(&dev_priv->evo);
+                       return ret;
+               }
+
+               ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19,
+                                         0, dev_priv->vram_size, 0x00020000);
+               if (ret) {
+                       nv50_evo_channel_del(&dev_priv->evo);
+                       return ret;
+               }
+
+               ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19,
+                                         0, dev_priv->vram_size, 0x00000000);
+               if (ret) {
+                       nv50_evo_channel_del(&dev_priv->evo);
+                       return ret;
+               }
+       } else
        if (dev_priv->chipset != 0x50) {
                ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB16, 0x70, 0x19,
-                                         0, 0xffffffff);
+                                         0, 0xffffffff, 0x00010000);
                if (ret) {
                        nv50_evo_channel_del(&dev_priv->evo);
                        return ret;
@@ -274,18 +294,25 @@ nv50_evo_create(struct drm_device *dev)
 
 
                ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0x7a, 0x19,
-                                         0, 0xffffffff);
+                                         0, 0xffffffff, 0x00010000);
                if (ret) {
                        nv50_evo_channel_del(&dev_priv->evo);
                        return ret;
                }
-       }
 
-       ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19,
-                                 0, dev_priv->vram_size);
-       if (ret) {
-               nv50_evo_channel_del(&dev_priv->evo);
-               return ret;
+               ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19,
+                                         0, dev_priv->vram_size, 0x00010000);
+               if (ret) {
+                       nv50_evo_channel_del(&dev_priv->evo);
+                       return ret;
+               }
+
+               ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19,
+                                         0, dev_priv->vram_size, 0x00010000);
+               if (ret) {
+                       nv50_evo_channel_del(&dev_priv->evo);
+                       return ret;
+               }
        }
 
        return 0;
index 41fcae5ffba4c627de5382996c13fc0a22bf7c2e..858eda5dedd1a79c5bb049c44804a2ed626f9039 100644 (file)
 bool
 nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags)
 {
-       if (likely(!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)))
+       switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) {
+       case 0x0000:
+       case 0xfe00:
+       case 0xdb00:
+       case 0x1100:
                return true;
+       default:
+               break;
+       }
+
        return false;
 }