}
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;
}