From 47057302f075578618ea36fc3c4c97a5a6f97f00 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 16 Nov 2012 13:58:48 +1000 Subject: [PATCH] drm/nvd0/disp: support creation of fb dma objects on older chipsets Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvd0_display.c | 167 ++++++++++++++++++++++++++------- 1 file changed, 131 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index b979e3c..9d001c9 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -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; } -- 2.7.4