drm/nvd0/disp: support creation of fb dma objects on older chipsets
authorBen Skeggs <bskeggs@redhat.com>
Fri, 16 Nov 2012 03:58:48 +0000 (13:58 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 28 Nov 2012 23:57:56 +0000 (09:57 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nvd0_display.c

index b979e3c..9d001c9 100644 (file)
@@ -142,89 +142,184 @@ nvd0_dmac_destroy(struct nouveau_object *core, struct nvd0_dmac *dmac)
 }
 
 static int
-nvd0_dmac_create(struct nouveau_object *core, u32 bclass, u8 head,
-                void *data, u32 size, u64 syncbuf,
-                struct nvd0_dmac *dmac)
+nv50_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
 {
        struct nouveau_fb *pfb = nouveau_fb(core);
        struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
        struct nouveau_object *object;
-       u32 pushbuf = *(u32 *)data;
-       dma_addr_t handle;
-       void *ptr;
-       int ret;
-
-       ptr = pci_alloc_consistent(nv_device(core)->pdev, PAGE_SIZE, &handle);
-       if (!ptr)
-               return -ENOMEM;
+       int ret = nouveau_object_new(client, parent, NvEvoVRAM_LP,
+                                    NV_DMA_IN_MEMORY_CLASS,
+                                    &(struct nv_dma_class) {
+                                       .flags = NV_DMA_TARGET_VRAM |
+                                                NV_DMA_ACCESS_RDWR,
+                                       .start = 0,
+                                       .limit = pfb->ram.size - 1,
+                                       .conf0 = NV50_DMA_CONF0_ENABLE |
+                                                NV50_DMA_CONF0_PART_256,
+                                    }, sizeof(struct nv_dma_class), &object);
+       if (ret)
+               return ret;
 
-       ret = nouveau_object_new(client, NVDRM_DEVICE, pushbuf,
-                                NV_DMA_FROM_MEMORY_CLASS,
+       ret = nouveau_object_new(client, parent, NvEvoFB16,
+                                NV_DMA_IN_MEMORY_CLASS,
                                 &(struct nv_dma_class) {
-                                       .flags = NV_DMA_TARGET_PCI_US |
-                                                NV_DMA_ACCESS_RD,
-                                       .start = handle + 0x0000,
-                                       .limit = handle + 0x0fff,
+                                       .flags = NV_DMA_TARGET_VRAM |
+                                                NV_DMA_ACCESS_RDWR,
+                                       .start = 0,
+                                       .limit = pfb->ram.size - 1,
+                                       .conf0 = NV50_DMA_CONF0_ENABLE | 0x70 |
+                                                NV50_DMA_CONF0_PART_256,
                                 }, sizeof(struct nv_dma_class), &object);
        if (ret)
                return ret;
 
-       ret = nvd0_chan_create(core, bclass, head, data, size, &dmac->base);
+       ret = nouveau_object_new(client, parent, NvEvoFB32,
+                                NV_DMA_IN_MEMORY_CLASS,
+                                &(struct nv_dma_class) {
+                                       .flags = NV_DMA_TARGET_VRAM |
+                                                NV_DMA_ACCESS_RDWR,
+                                       .start = 0,
+                                       .limit = pfb->ram.size - 1,
+                                       .conf0 = NV50_DMA_CONF0_ENABLE | 0x7a |
+                                                NV50_DMA_CONF0_PART_256,
+                                }, sizeof(struct nv_dma_class), &object);
+       return ret;
+}
+
+static int
+nvc0_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
+{
+       struct nouveau_fb *pfb = nouveau_fb(core);
+       struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
+       struct nouveau_object *object;
+       int ret = nouveau_object_new(client, parent, NvEvoVRAM_LP,
+                                    NV_DMA_IN_MEMORY_CLASS,
+                                    &(struct nv_dma_class) {
+                                       .flags = NV_DMA_TARGET_VRAM |
+                                                NV_DMA_ACCESS_RDWR,
+                                       .start = 0,
+                                       .limit = pfb->ram.size - 1,
+                                       .conf0 = NVC0_DMA_CONF0_ENABLE,
+                                    }, sizeof(struct nv_dma_class), &object);
        if (ret)
                return ret;
 
-       dmac->handle = handle;
-       dmac->ptr = ptr;
-
-       ret = nouveau_object_new(client, dmac->base.handle, NvEvoSync,
+       ret = nouveau_object_new(client, parent, NvEvoFB16,
                                 NV_DMA_IN_MEMORY_CLASS,
                                 &(struct nv_dma_class) {
                                        .flags = NV_DMA_TARGET_VRAM |
                                                 NV_DMA_ACCESS_RDWR,
-                                       .start = syncbuf + 0x0000,
-                                       .limit = syncbuf + 0x0fff,
+                                       .start = 0,
+                                       .limit = pfb->ram.size - 1,
+                                       .conf0 = NVC0_DMA_CONF0_ENABLE | 0xfe,
                                 }, sizeof(struct nv_dma_class), &object);
        if (ret)
-               goto out;
+               return ret;
 
-       ret = nouveau_object_new(client, dmac->base.handle, NvEvoVRAM,
+       ret = nouveau_object_new(client, parent, NvEvoFB32,
                                 NV_DMA_IN_MEMORY_CLASS,
                                 &(struct nv_dma_class) {
                                        .flags = NV_DMA_TARGET_VRAM |
                                                 NV_DMA_ACCESS_RDWR,
                                        .start = 0,
                                        .limit = pfb->ram.size - 1,
+                                       .conf0 = NVC0_DMA_CONF0_ENABLE | 0xfe,
                                 }, sizeof(struct nv_dma_class), &object);
+       return ret;
+}
+
+static int
+nvd0_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
+{
+       struct nouveau_fb *pfb = nouveau_fb(core);
+       struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
+       struct nouveau_object *object;
+       int ret = nouveau_object_new(client, parent, NvEvoVRAM_LP,
+                                    NV_DMA_IN_MEMORY_CLASS,
+                                    &(struct nv_dma_class) {
+                                       .flags = NV_DMA_TARGET_VRAM |
+                                                NV_DMA_ACCESS_RDWR,
+                                       .start = 0,
+                                       .limit = pfb->ram.size - 1,
+                                       .conf0 = NVD0_DMA_CONF0_ENABLE |
+                                                NVD0_DMA_CONF0_PAGE_LP,
+                                    }, sizeof(struct nv_dma_class), &object);
        if (ret)
-               goto out;
+               return ret;
 
-       ret = nouveau_object_new(client, dmac->base.handle, NvEvoVRAM_LP,
+       ret = nouveau_object_new(client, parent, NvEvoFB32,
                                 NV_DMA_IN_MEMORY_CLASS,
                                 &(struct nv_dma_class) {
                                        .flags = NV_DMA_TARGET_VRAM |
                                                 NV_DMA_ACCESS_RDWR,
                                        .start = 0,
                                        .limit = pfb->ram.size - 1,
-                                       .conf0 = NVD0_DMA_CONF0_ENABLE |
+                                       .conf0 = NVD0_DMA_CONF0_ENABLE | 0xfe |
                                                 NVD0_DMA_CONF0_PAGE_LP,
                                 }, sizeof(struct nv_dma_class), &object);
+       return ret;
+}
+
+static int
+nvd0_dmac_create(struct nouveau_object *core, u32 bclass, u8 head,
+                void *data, u32 size, u64 syncbuf,
+                struct nvd0_dmac *dmac)
+{
+       struct nouveau_fb *pfb = nouveau_fb(core);
+       struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
+       struct nouveau_object *object;
+       u32 pushbuf = *(u32 *)data;
+       int ret;
+
+       dmac->ptr = pci_alloc_consistent(nv_device(core)->pdev, PAGE_SIZE,
+                                       &dmac->handle);
+       if (!dmac->ptr)
+               return -ENOMEM;
+
+       ret = nouveau_object_new(client, NVDRM_DEVICE, pushbuf,
+                                NV_DMA_FROM_MEMORY_CLASS,
+                                &(struct nv_dma_class) {
+                                       .flags = NV_DMA_TARGET_PCI_US |
+                                                NV_DMA_ACCESS_RD,
+                                       .start = dmac->handle + 0x0000,
+                                       .limit = dmac->handle + 0x0fff,
+                                }, sizeof(struct nv_dma_class), &object);
        if (ret)
-               goto out;
+               return ret;
+
+       ret = nvd0_chan_create(core, bclass, head, data, size, &dmac->base);
+       if (ret)
+               return ret;
+
+       ret = nouveau_object_new(client, dmac->base.handle, NvEvoSync,
+                                NV_DMA_IN_MEMORY_CLASS,
+                                &(struct nv_dma_class) {
+                                       .flags = NV_DMA_TARGET_VRAM |
+                                                NV_DMA_ACCESS_RDWR,
+                                       .start = syncbuf + 0x0000,
+                                       .limit = syncbuf + 0x0fff,
+                                }, sizeof(struct nv_dma_class), &object);
+       if (ret)
+               return ret;
 
-       ret = nouveau_object_new(client, dmac->base.handle, NvEvoFB32,
+       ret = nouveau_object_new(client, dmac->base.handle, NvEvoVRAM,
                                 NV_DMA_IN_MEMORY_CLASS,
                                 &(struct nv_dma_class) {
                                        .flags = NV_DMA_TARGET_VRAM |
                                                 NV_DMA_ACCESS_RDWR,
                                        .start = 0,
                                        .limit = pfb->ram.size - 1,
-                                       .conf0 = 0x00fe |
-                                                NVD0_DMA_CONF0_ENABLE |
-                                                NVD0_DMA_CONF0_PAGE_LP,
                                 }, sizeof(struct nv_dma_class), &object);
-out:
        if (ret)
-               nvd0_dmac_destroy(core, dmac);
+               return ret;
+
+       if (nv_device(core)->card_type < NV_C0)
+               ret = nv50_dmac_create_fbdma(core, dmac->base.handle);
+       else
+       if (nv_device(core)->card_type < NV_D0)
+               ret = nvc0_dmac_create_fbdma(core, dmac->base.handle);
+       else
+               ret = nvd0_dmac_create_fbdma(core, dmac->base.handle);
        return ret;
 }