aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c193
1 files changed, 132 insertions, 61 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
index 83549702bbc1..472357f499ad 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
@@ -66,14 +66,15 @@ nv50_disp_root_scanoutpos(NV50_DISP_MTHD_V0)
}
int
-nv50_disp_root_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
+nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
{
- const struct nv50_disp_impl *impl = (void *)nv_oclass(object->engine);
union {
struct nv50_disp_mthd_v0 v0;
struct nv50_disp_mthd_v1 v1;
} *args = data;
- struct nv50_disp *disp = (void *)object->engine;
+ struct nv50_disp_root *root = nv50_disp_root(object);
+ struct nv50_disp *disp = root->disp;
+ const struct nv50_disp_impl *impl = (void *)nv_oclass(object->engine);
struct nvkm_output *outp = NULL;
struct nvkm_output *temp;
u16 type, mask = 0;
@@ -187,48 +188,127 @@ nv50_disp_root_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
return -EINVAL;
}
+static int
+nv50_disp_root_dmac_new_(const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
+{
+ const struct nv50_disp_dmac_oclass *sclass = oclass->priv;
+ struct nv50_disp_root *root = nv50_disp_root(oclass->parent);
+ return sclass->ctor(sclass->func, sclass->mthd, root, sclass->chid,
+ oclass, data, size, pobject);
+}
+
+static int
+nv50_disp_root_pioc_new_(const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
+{
+ const struct nv50_disp_pioc_oclass *sclass = oclass->priv;
+ struct nv50_disp_root *root = nv50_disp_root(oclass->parent);
+ return sclass->ctor(sclass->func, sclass->mthd, root, sclass->chid,
+ oclass, data, size, pobject);
+}
+
+static int
+nv50_disp_root_child_get_(struct nvkm_object *object, int index,
+ struct nvkm_oclass *sclass)
+{
+ struct nv50_disp_root *root = nv50_disp_root(object);
+
+ if (index < ARRAY_SIZE(root->func->dmac)) {
+ sclass->base = root->func->dmac[index]->base;
+ sclass->priv = root->func->dmac[index];
+ sclass->ctor = nv50_disp_root_dmac_new_;
+ return 0;
+ }
+
+ index -= ARRAY_SIZE(root->func->dmac);
+
+ if (index < ARRAY_SIZE(root->func->pioc)) {
+ sclass->base = root->func->pioc[index]->base;
+ sclass->priv = root->func->pioc[index];
+ sclass->ctor = nv50_disp_root_pioc_new_;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int
+nv50_disp_root_fini_(struct nvkm_object *object, bool suspend)
+{
+ struct nv50_disp_root *root = nv50_disp_root(object);
+ root->func->fini(root);
+ return 0;
+}
+
+static int
+nv50_disp_root_init_(struct nvkm_object *object)
+{
+ struct nv50_disp_root *root = nv50_disp_root(object);
+ return root->func->init(root);
+}
+
+static void *
+nv50_disp_root_dtor_(struct nvkm_object *object)
+{
+ struct nv50_disp_root *root = nv50_disp_root(object);
+ nvkm_ramht_del(&root->ramht);
+ nvkm_gpuobj_del(&root->instmem);
+ return root;
+}
+
+static const struct nvkm_object_func
+nv50_disp_root_ = {
+ .dtor = nv50_disp_root_dtor_,
+ .init = nv50_disp_root_init_,
+ .fini = nv50_disp_root_fini_,
+ .mthd = nv50_disp_root_mthd_,
+ .ntfy = nvkm_disp_ntfy,
+ .sclass = nv50_disp_root_child_get_,
+};
+
int
-nv50_disp_root_ctor(struct nvkm_object *parent,
- struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+nv50_disp_root_new_(const struct nv50_disp_root_func *func,
+ struct nvkm_disp *base, const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
{
- struct nv50_disp *disp = (void *)engine;
+ struct nv50_disp *disp = nv50_disp(base);
struct nv50_disp_root *root;
struct nvkm_device *device = disp->base.engine.subdev.device;
- struct nvkm_gpuobj *instmem = (void *)parent;
int ret;
- ret = nvkm_parent_create(parent, engine, oclass, 0,
- disp->sclass, 0, &root);
- *pobject = nv_object(root);
+ if (!(root = kzalloc(sizeof(*root), GFP_KERNEL)))
+ return -ENOMEM;
+ *pobject = &root->object;
+
+ nvkm_object_ctor(&nv50_disp_root_, oclass, &root->object);
+ root->func = func;
+ root->disp = disp;
+
+ ret = nvkm_gpuobj_new(disp->base.engine.subdev.device, 0x10000, 0x10000,
+ false, NULL, &root->instmem);
if (ret)
return ret;
-
- return nvkm_ramht_new(device, 0x1000, 0, instmem, &root->ramht);
+ return nvkm_ramht_new(device, 0x1000, 0, root->instmem, &root->ramht);
}
void
-nv50_disp_root_dtor(struct nvkm_object *object)
+nv50_disp_root_fini(struct nv50_disp_root *root)
{
- struct nv50_disp_root *root = (void *)object;
- nvkm_ramht_del(&root->ramht);
- nvkm_parent_destroy(&root->base);
+ struct nvkm_device *device = root->disp->base.engine.subdev.device;
+ /* disable all interrupts */
+ nvkm_wr32(device, 0x610024, 0x00000000);
+ nvkm_wr32(device, 0x610020, 0x00000000);
}
-static int
-nv50_disp_root_init(struct nvkm_object *object)
+int
+nv50_disp_root_init(struct nv50_disp_root *root)
{
- struct nv50_disp *disp = (void *)object->engine;
- struct nv50_disp_root *root = (void *)object;
+ struct nv50_disp *disp = root->disp;
struct nvkm_device *device = disp->base.engine.subdev.device;
- int ret, i;
u32 tmp;
-
- ret = nvkm_parent_init(&root->base);
- if (ret)
- return ret;
+ int i;
/* The below segments of code copying values from one register to
* another appear to inform EVO of the display capabilities or
@@ -279,7 +359,7 @@ nv50_disp_root_init(struct nvkm_object *object)
}
/* point at display engine memory area (hash table, objects) */
- nvkm_wr32(device, 0x610010, (root->ramht->gpuobj->addr >> 8) | 9);
+ nvkm_wr32(device, 0x610010, (root->instmem->addr >> 8) | 9);
/* enable supervisor interrupts, disable everything else */
nvkm_wr32(device, 0x61002c, 0x00000370);
@@ -287,42 +367,33 @@ nv50_disp_root_init(struct nvkm_object *object)
return 0;
}
-static int
-nv50_disp_root_fini(struct nvkm_object *object, bool suspend)
-{
- struct nv50_disp *disp = (void *)object->engine;
- struct nv50_disp_root *root = (void *)object;
- struct nvkm_device *device = disp->base.engine.subdev.device;
-
- /* disable all interrupts */
- nvkm_wr32(device, 0x610024, 0x00000000);
- nvkm_wr32(device, 0x610020, 0x00000000);
-
- return nvkm_parent_fini(&root->base, suspend);
-}
-
-struct nvkm_ofuncs
-nv50_disp_root_ofuncs = {
- .ctor = nv50_disp_root_ctor,
- .dtor = nv50_disp_root_dtor,
+static const struct nv50_disp_root_func
+nv50_disp_root = {
.init = nv50_disp_root_init,
.fini = nv50_disp_root_fini,
- .mthd = nv50_disp_root_mthd,
- .ntfy = nvkm_disp_ntfy,
+ .dmac = {
+ &nv50_disp_core_oclass,
+ &nv50_disp_base_oclass,
+ &nv50_disp_ovly_oclass,
+ },
+ .pioc = {
+ &nv50_disp_oimm_oclass,
+ &nv50_disp_curs_oclass,
+ },
};
-struct nvkm_oclass
-nv50_disp_root_oclass[] = {
- { NV50_DISP, &nv50_disp_root_ofuncs },
- {}
-};
+static int
+nv50_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
+{
+ return nv50_disp_root_new_(&nv50_disp_root, disp, oclass,
+ data, size, pobject);
+}
-struct nvkm_oclass
-nv50_disp_sclass[] = {
- { NV50_DISP_CORE_CHANNEL_DMA, &nv50_disp_core_ofuncs.base },
- { NV50_DISP_BASE_CHANNEL_DMA, &nv50_disp_base_ofuncs.base },
- { NV50_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
- { NV50_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
- { NV50_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
- {}
+const struct nvkm_disp_oclass
+nv50_disp_root_oclass = {
+ .base.oclass = NV50_DISP,
+ .base.minver = -1,
+ .base.maxver = -1,
+ .ctor = nv50_disp_root_new,
};