summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-08-10 04:10:25 +1000
committerBen Skeggs <bskeggs@redhat.com>2014-08-10 05:28:06 +1000
commit410f3ec63570bea8efe00826a2b83ceb353553b1 (patch)
tree0a91f07fe4e2507573d0ffcf02ad58318a43d245 /drivers/gpu/drm
parent867920f8c920bcaa5a6fa5ebad4596669b82ba80 (diff)
drm/nv50/kms: don't assume same class versions for all channels
One of the next commits will remove some of the class IDs, leaving only the ones used by NVIDIA which, presumably, mark where functionality changes actually happened. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c214
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;