diff options
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 214 |
1 files changed, 166 insertions, 48 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 4f50add8e6dd..2d9a02c4b87e 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -68,19 +68,17 @@ struct nv50_chan { }; static int -nv50_chan_create(struct nvif_object *disp, u32 bclass, u8 head, +nv50_chan_create(struct nvif_object *disp, const u32 *oclass, u8 head, void *data, u32 size, struct nv50_chan *chan) { - const u32 oclass = EVO_CHAN_OCLASS(bclass, disp); - const u32 handle = EVO_CHAN_HANDLE(bclass, head); - int ret; - - ret = nvif_object_init(disp, NULL, handle, oclass, data, size, - &chan->user); - if (ret) - return ret; - - return 0; + while (oclass[0]) { + int ret = nvif_object_init(disp, NULL, (oclass[0] << 16) | head, + oclass[0], data, size, + &chan->user); + if (oclass++, ret == 0) + return ret; + } + return -ENOSYS; } static void @@ -104,10 +102,72 @@ nv50_pioc_destroy(struct nv50_pioc *pioc) } static int -nv50_pioc_create(struct nvif_object *disp, u32 bclass, u8 head, +nv50_pioc_create(struct nvif_object *disp, const u32 *oclass, u8 head, void *data, u32 size, struct nv50_pioc *pioc) { - return nv50_chan_create(disp, bclass, head, data, size, &pioc->base); + return nv50_chan_create(disp, oclass, head, data, size, &pioc->base); +} + +/****************************************************************************** + * Cursor Immediate + *****************************************************************************/ + +struct nv50_curs { + struct nv50_pioc base; +}; + +static int +nv50_curs_create(struct nvif_object *disp, int head, struct nv50_curs *curs) +{ + struct nv50_display_curs_class args = { + .head = head, + }; + static const u32 oclass[] = { + GM107_DISP_CURS_CLASS, + NVF0_DISP_CURS_CLASS, + NVE0_DISP_CURS_CLASS, + NVD0_DISP_CURS_CLASS, + NVA3_DISP_CURS_CLASS, + NV94_DISP_CURS_CLASS, + NVA0_DISP_CURS_CLASS, + NV84_DISP_CURS_CLASS, + NV50_DISP_CURS_CLASS, + 0 + }; + + return nv50_pioc_create(disp, oclass, head, &args, sizeof(args), + &curs->base); +} + +/****************************************************************************** + * Overlay Immediate + *****************************************************************************/ + +struct nv50_oimm { + struct nv50_pioc base; +}; + +static int +nv50_oimm_create(struct nvif_object *disp, int head, struct nv50_oimm *oimm) +{ + struct nv50_display_oimm_class args = { + .head = head, + }; + static const u32 oclass[] = { + GM107_DISP_OIMM_CLASS, + NVF0_DISP_OIMM_CLASS, + NVE0_DISP_OIMM_CLASS, + NVD0_DISP_OIMM_CLASS, + NVA3_DISP_OIMM_CLASS, + NV94_DISP_OIMM_CLASS, + NVA0_DISP_OIMM_CLASS, + NV84_DISP_OIMM_CLASS, + NV50_DISP_OIMM_CLASS, + 0 + }; + + return nv50_pioc_create(disp, oclass, head, &args, sizeof(args), + &oimm->base); } /****************************************************************************** @@ -143,7 +203,7 @@ nv50_dmac_destroy(struct nv50_dmac *dmac, struct nvif_object *disp) } static int -nv50_dmac_create(struct nvif_object *disp, u32 bclass, u8 head, +nv50_dmac_create(struct nvif_object *disp, const u32 *oclass, u8 head, void *data, u32 size, u64 syncbuf, struct nv50_dmac *dmac) { @@ -170,7 +230,7 @@ nv50_dmac_create(struct nvif_object *disp, u32 bclass, u8 head, if (ret) return ret; - ret = nv50_chan_create(disp, bclass, head, data, size, &dmac->base); + ret = nv50_chan_create(disp, oclass, head, data, size, &dmac->base); nvif_object_fini(&pushbuf); if (ret) return ret; @@ -202,13 +262,40 @@ nv50_dmac_create(struct nvif_object *disp, u32 bclass, u8 head, return ret; } +/****************************************************************************** + * Core + *****************************************************************************/ + struct nv50_mast { struct nv50_dmac base; }; -struct nv50_curs { - struct nv50_pioc base; -}; +static int +nv50_core_create(struct nvif_object *disp, u64 syncbuf, struct nv50_mast *core) +{ + struct nv50_display_mast_class args = { + .pushbuf = EVO_PUSH_HANDLE(MAST, 0), + }; + static const u32 oclass[] = { + GM107_DISP_MAST_CLASS, + NVF0_DISP_MAST_CLASS, + NVE0_DISP_MAST_CLASS, + NVD0_DISP_MAST_CLASS, + NVA3_DISP_MAST_CLASS, + NV94_DISP_MAST_CLASS, + NVA0_DISP_MAST_CLASS, + NV84_DISP_MAST_CLASS, + NV50_DISP_MAST_CLASS, + 0 + }; + + return nv50_dmac_create(disp, oclass, 0, &args, sizeof(args), syncbuf, + &core->base); +} + +/****************************************************************************** + * Base + *****************************************************************************/ struct nv50_sync { struct nv50_dmac base; @@ -216,13 +303,63 @@ struct nv50_sync { u32 data; }; +static int +nv50_base_create(struct nvif_object *disp, int head, u64 syncbuf, + struct nv50_sync *base) +{ + struct nv50_display_sync_class args = { + .pushbuf = EVO_PUSH_HANDLE(SYNC, head), + .head = head, + }; + static const u32 oclass[] = { + GM107_DISP_SYNC_CLASS, + NVF0_DISP_SYNC_CLASS, + NVE0_DISP_SYNC_CLASS, + NVD0_DISP_SYNC_CLASS, + NVA3_DISP_SYNC_CLASS, + NV94_DISP_SYNC_CLASS, + NVA0_DISP_SYNC_CLASS, + NV84_DISP_SYNC_CLASS, + NV50_DISP_SYNC_CLASS, + 0 + }; + + return nv50_dmac_create(disp, oclass, head, &args, sizeof(args), + syncbuf, &base->base); +} + +/****************************************************************************** + * Overlay + *****************************************************************************/ + struct nv50_ovly { struct nv50_dmac base; }; -struct nv50_oimm { - struct nv50_pioc base; -}; +static int +nv50_ovly_create(struct nvif_object *disp, int head, u64 syncbuf, + struct nv50_ovly *ovly) +{ + struct nv50_display_ovly_class args = { + .pushbuf = EVO_PUSH_HANDLE(OVLY, head), + .head = head, + }; + static const u32 oclass[] = { + GM107_DISP_OVLY_CLASS, + NVF0_DISP_OVLY_CLASS, + NVE0_DISP_OVLY_CLASS, + NVD0_DISP_OVLY_CLASS, + NVA3_DISP_OVLY_CLASS, + NV94_DISP_OVLY_CLASS, + NVA0_DISP_OVLY_CLASS, + NV84_DISP_OVLY_CLASS, + NV50_DISP_OVLY_CLASS, + 0 + }; + + return nv50_dmac_create(disp, oclass, head, &args, sizeof(args), + syncbuf, &ovly->base); +} struct nv50_head { struct nouveau_crtc base; @@ -1276,11 +1413,7 @@ nv50_crtc_create(struct drm_device *dev, int index) nv50_crtc_lut_load(crtc); /* allocate cursor resources */ - ret = nv50_pioc_create(disp->disp, NV50_DISP_CURS_CLASS, index, - &(struct nv50_display_curs_class) { - .head = index, - }, sizeof(struct nv50_display_curs_class), - &head->curs.base); + ret = nv50_curs_create(disp->disp, index, &head->curs); if (ret) goto out; @@ -1301,12 +1434,8 @@ nv50_crtc_create(struct drm_device *dev, int index) goto out; /* allocate page flip / sync resources */ - ret = nv50_dmac_create(disp->disp, NV50_DISP_SYNC_CLASS, index, - &(struct nv50_display_sync_class) { - .pushbuf = EVO_PUSH_HANDLE(SYNC, index), - .head = index, - }, sizeof(struct nv50_display_sync_class), - disp->sync->bo.offset, &head->sync.base); + ret = nv50_base_create(disp->disp, index, disp->sync->bo.offset, + &head->sync); if (ret) goto out; @@ -1314,20 +1443,12 @@ nv50_crtc_create(struct drm_device *dev, int index) head->sync.data = 0x00000000; /* allocate overlay resources */ - ret = nv50_pioc_create(disp->disp, NV50_DISP_OIMM_CLASS, index, - &(struct nv50_display_oimm_class) { - .head = index, - }, sizeof(struct nv50_display_oimm_class), - &head->oimm.base); + ret = nv50_oimm_create(disp->disp, index, &head->oimm); if (ret) goto out; - ret = nv50_dmac_create(disp->disp, NV50_DISP_OVLY_CLASS, index, - &(struct nv50_display_ovly_class) { - .pushbuf = EVO_PUSH_HANDLE(OVLY, index), - .head = index, - }, sizeof(struct nv50_display_ovly_class), - disp->sync->bo.offset, &head->ovly.base); + ret = nv50_ovly_create(disp->disp, index, disp->sync->bo.offset, + &head->ovly); if (ret) goto out; @@ -2288,11 +2409,8 @@ nv50_display_create(struct drm_device *dev) goto out; /* allocate master evo channel */ - ret = nv50_dmac_create(disp->disp, NV50_DISP_MAST_CLASS, 0, - &(struct nv50_display_mast_class) { - .pushbuf = EVO_PUSH_HANDLE(MAST, 0), - }, sizeof(struct nv50_display_mast_class), - disp->sync->bo.offset, &disp->mast.base); + ret = nv50_core_create(disp->disp, disp->sync->bo.offset, + &disp->mast); if (ret) goto out; |