diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/core/engine/disp/nv50.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | 153 |
1 files changed, 82 insertions, 71 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index ca8ce9cace7f..4f1ed8928c82 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -43,14 +43,16 @@ * EVO channel base class ******************************************************************************/ -int +static int nv50_disp_chan_create_(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, int chid, + struct nouveau_oclass *oclass, int head, int length, void **pobject) { + const struct nv50_disp_chan_impl *impl = (void *)oclass->ofuncs; struct nv50_disp_base *base = (void *)parent; struct nv50_disp_chan *chan; + int chid = impl->chid + head; int ret; if (base->chan & (1 << chid)) @@ -63,12 +65,14 @@ nv50_disp_chan_create_(struct nouveau_object *parent, chan = *pobject; if (ret) return ret; - chan->chid = chid; + + nv_parent(chan)->object_attach = impl->attach; + nv_parent(chan)->object_detach = impl->detach; return 0; } -void +static void nv50_disp_chan_destroy(struct nv50_disp_chan *chan) { struct nv50_disp_base *base = (void *)nv_object(chan)->parent; @@ -115,16 +119,16 @@ nv50_disp_dmac_object_detach(struct nouveau_object *parent, int cookie) nouveau_ramht_remove(base->ramht, cookie); } -int +static int nv50_disp_dmac_create_(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, u32 pushbuf, int chid, + struct nouveau_oclass *oclass, u32 pushbuf, int head, int length, void **pobject) { struct nv50_disp_dmac *dmac; int ret; - ret = nv50_disp_chan_create_(parent, engine, oclass, chid, + ret = nv50_disp_chan_create_(parent, engine, oclass, head, length, pobject); dmac = *pobject; if (ret) @@ -397,7 +401,7 @@ nv50_disp_mast_mthd_chan = { } }; -static int +int nv50_disp_mast_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -416,8 +420,6 @@ nv50_disp_mast_ctor(struct nouveau_object *parent, if (ret) return ret; - nv_parent(mast)->object_attach = nv50_disp_dmac_object_attach; - nv_parent(mast)->object_detach = nv50_disp_dmac_object_detach; return 0; } @@ -479,14 +481,17 @@ nv50_disp_mast_fini(struct nouveau_object *object, bool suspend) return nv50_disp_chan_fini(&mast->base, suspend); } -struct nouveau_ofuncs +struct nv50_disp_chan_impl nv50_disp_mast_ofuncs = { - .ctor = nv50_disp_mast_ctor, - .dtor = nv50_disp_dmac_dtor, - .init = nv50_disp_mast_init, - .fini = nv50_disp_mast_fini, - .rd32 = nv50_disp_chan_rd32, - .wr32 = nv50_disp_chan_wr32, + .base.ctor = nv50_disp_mast_ctor, + .base.dtor = nv50_disp_dmac_dtor, + .base.init = nv50_disp_mast_init, + .base.fini = nv50_disp_mast_fini, + .base.rd32 = nv50_disp_chan_rd32, + .base.wr32 = nv50_disp_chan_wr32, + .chid = 0, + .attach = nv50_disp_dmac_object_attach, + .detach = nv50_disp_dmac_object_detach, }; /******************************************************************************* @@ -543,39 +548,40 @@ nv50_disp_sync_mthd_chan = { } }; -static int +int nv50_disp_sync_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nv50_display_sync_class *args = data; + struct nv50_disp_priv *priv = (void *)engine; struct nv50_disp_dmac *dmac; int ret; - if (size < sizeof(*args) || args->head > 1) + if (size < sizeof(*args) || args->head >= priv->head.nr) return -EINVAL; ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf, - 1 + args->head, sizeof(*dmac), - (void **)&dmac); + args->head, sizeof(*dmac), (void **)&dmac); *pobject = nv_object(dmac); if (ret) return ret; - nv_parent(dmac)->object_attach = nv50_disp_dmac_object_attach; - nv_parent(dmac)->object_detach = nv50_disp_dmac_object_detach; return 0; } -struct nouveau_ofuncs +struct nv50_disp_chan_impl nv50_disp_sync_ofuncs = { - .ctor = nv50_disp_sync_ctor, - .dtor = nv50_disp_dmac_dtor, - .init = nv50_disp_dmac_init, - .fini = nv50_disp_dmac_fini, - .rd32 = nv50_disp_chan_rd32, - .wr32 = nv50_disp_chan_wr32, + .base.ctor = nv50_disp_sync_ctor, + .base.dtor = nv50_disp_dmac_dtor, + .base.init = nv50_disp_dmac_init, + .base.fini = nv50_disp_dmac_fini, + .base.rd32 = nv50_disp_chan_rd32, + .base.wr32 = nv50_disp_chan_wr32, + .chid = 1, + .attach = nv50_disp_dmac_object_attach, + .detach = nv50_disp_dmac_object_detach, }; /******************************************************************************* @@ -620,39 +626,40 @@ nv50_disp_ovly_mthd_chan = { } }; -static int +int nv50_disp_ovly_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nv50_display_ovly_class *args = data; + struct nv50_disp_priv *priv = (void *)engine; struct nv50_disp_dmac *dmac; int ret; - if (size < sizeof(*args) || args->head > 1) + if (size < sizeof(*args) || args->head >= priv->head.nr) return -EINVAL; ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf, - 3 + args->head, sizeof(*dmac), - (void **)&dmac); + args->head, sizeof(*dmac), (void **)&dmac); *pobject = nv_object(dmac); if (ret) return ret; - nv_parent(dmac)->object_attach = nv50_disp_dmac_object_attach; - nv_parent(dmac)->object_detach = nv50_disp_dmac_object_detach; return 0; } -struct nouveau_ofuncs +struct nv50_disp_chan_impl nv50_disp_ovly_ofuncs = { - .ctor = nv50_disp_ovly_ctor, - .dtor = nv50_disp_dmac_dtor, - .init = nv50_disp_dmac_init, - .fini = nv50_disp_dmac_fini, - .rd32 = nv50_disp_chan_rd32, - .wr32 = nv50_disp_chan_wr32, + .base.ctor = nv50_disp_ovly_ctor, + .base.dtor = nv50_disp_dmac_dtor, + .base.init = nv50_disp_dmac_init, + .base.fini = nv50_disp_dmac_fini, + .base.rd32 = nv50_disp_chan_rd32, + .base.wr32 = nv50_disp_chan_wr32, + .chid = 3, + .attach = nv50_disp_dmac_object_attach, + .detach = nv50_disp_dmac_object_detach, }; /******************************************************************************* @@ -662,14 +669,14 @@ nv50_disp_ovly_ofuncs = { static int nv50_disp_pioc_create_(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, int chid, + struct nouveau_oclass *oclass, int head, int length, void **pobject) { - return nv50_disp_chan_create_(parent, engine, oclass, chid, + return nv50_disp_chan_create_(parent, engine, oclass, head, length, pobject); } -static void +void nv50_disp_pioc_dtor(struct nouveau_object *object) { struct nv50_disp_pioc *pioc = (void *)object; @@ -727,20 +734,21 @@ nv50_disp_pioc_fini(struct nouveau_object *object, bool suspend) * EVO immediate overlay channel objects ******************************************************************************/ -static int +int nv50_disp_oimm_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nv50_display_oimm_class *args = data; + struct nv50_disp_priv *priv = (void *)engine; struct nv50_disp_pioc *pioc; int ret; - if (size < sizeof(*args) || args->head > 1) + if (size < sizeof(*args) || args->head >= priv->head.nr) return -EINVAL; - ret = nv50_disp_pioc_create_(parent, engine, oclass, 5 + args->head, + ret = nv50_disp_pioc_create_(parent, engine, oclass, args->head, sizeof(*pioc), (void **)&pioc); *pobject = nv_object(pioc); if (ret) @@ -749,34 +757,36 @@ nv50_disp_oimm_ctor(struct nouveau_object *parent, return 0; } -struct nouveau_ofuncs +struct nv50_disp_chan_impl nv50_disp_oimm_ofuncs = { - .ctor = nv50_disp_oimm_ctor, - .dtor = nv50_disp_pioc_dtor, - .init = nv50_disp_pioc_init, - .fini = nv50_disp_pioc_fini, - .rd32 = nv50_disp_chan_rd32, - .wr32 = nv50_disp_chan_wr32, + .base.ctor = nv50_disp_oimm_ctor, + .base.dtor = nv50_disp_pioc_dtor, + .base.init = nv50_disp_pioc_init, + .base.fini = nv50_disp_pioc_fini, + .base.rd32 = nv50_disp_chan_rd32, + .base.wr32 = nv50_disp_chan_wr32, + .chid = 5, }; /******************************************************************************* * EVO cursor channel objects ******************************************************************************/ -static int +int nv50_disp_curs_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nv50_display_curs_class *args = data; + struct nv50_disp_priv *priv = (void *)engine; struct nv50_disp_pioc *pioc; int ret; - if (size < sizeof(*args) || args->head > 1) + if (size < sizeof(*args) || args->head >= priv->head.nr) return -EINVAL; - ret = nv50_disp_pioc_create_(parent, engine, oclass, 7 + args->head, + ret = nv50_disp_pioc_create_(parent, engine, oclass, args->head, sizeof(*pioc), (void **)&pioc); *pobject = nv_object(pioc); if (ret) @@ -785,14 +795,15 @@ nv50_disp_curs_ctor(struct nouveau_object *parent, return 0; } -struct nouveau_ofuncs +struct nv50_disp_chan_impl nv50_disp_curs_ofuncs = { - .ctor = nv50_disp_curs_ctor, - .dtor = nv50_disp_pioc_dtor, - .init = nv50_disp_pioc_init, - .fini = nv50_disp_pioc_fini, - .rd32 = nv50_disp_chan_rd32, - .wr32 = nv50_disp_chan_wr32, + .base.ctor = nv50_disp_curs_ctor, + .base.dtor = nv50_disp_pioc_dtor, + .base.init = nv50_disp_pioc_init, + .base.fini = nv50_disp_pioc_fini, + .base.rd32 = nv50_disp_chan_rd32, + .base.wr32 = nv50_disp_chan_wr32, + .chid = 7, }; /******************************************************************************* @@ -966,11 +977,11 @@ nv50_disp_base_oclass[] = { static struct nouveau_oclass nv50_disp_sclass[] = { - { NV50_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs }, - { NV50_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs }, - { NV50_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs }, - { NV50_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs }, - { NV50_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs }, + { NV50_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs.base }, + { NV50_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs.base }, + { NV50_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs.base }, + { NV50_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs.base }, + { NV50_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs.base }, {} }; |