diff options
73 files changed, 2346 insertions, 1053 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h b/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h new file mode 100644 index 000000000000..bd52236cc2f4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h @@ -0,0 +1,22 @@ +#ifndef __NVKM_OPROXY_H__ +#define __NVKM_OPROXY_H__ +#define nvkm_oproxy(p) container_of((p), struct nvkm_oproxy, base) +#include <core/object.h> + +struct nvkm_oproxy { + const struct nvkm_oproxy_func *func; + struct nvkm_object base; + struct nvkm_object *object; +}; + +struct nvkm_oproxy_func { + void (*dtor[2])(struct nvkm_oproxy *); + int (*init[2])(struct nvkm_oproxy *); + int (*fini[2])(struct nvkm_oproxy *, bool suspend); +}; + +void nvkm_oproxy_ctor(const struct nvkm_oproxy_func *, + const struct nvkm_oclass *, struct nvkm_oproxy *); +int nvkm_oproxy_new_(const struct nvkm_oproxy_func *, + const struct nvkm_oclass *, struct nvkm_oproxy **); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h index 2df776525b83..026a18ab4d90 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h @@ -1,10 +1,14 @@ #ifndef __NVKM_DISP_H__ #define __NVKM_DISP_H__ +#define nvkm_disp(p) container_of((p), struct nvkm_disp, engine) #include <core/engine.h> #include <core/event.h> struct nvkm_disp { struct nvkm_engine engine; + const struct nvkm_disp_func *func; + + struct nvkm_oproxy *client; struct list_head outp; struct list_head conn; @@ -13,6 +17,10 @@ struct nvkm_disp { struct nvkm_event vblank; }; +struct nvkm_disp_func { + const struct nvkm_disp_oclass *root; +}; + extern struct nvkm_oclass *nv04_disp_oclass; extern struct nvkm_oclass *nv50_disp_oclass; extern struct nvkm_oclass *g84_disp_oclass; diff --git a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild index 98cf39f732c1..e56c8eb9b054 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild @@ -11,6 +11,7 @@ nvkm-y += nvkm/core/mm.o nvkm-y += nvkm/core/namedb.o nvkm-y += nvkm/core/notify.o nvkm-y += nvkm/core/object.o +nvkm-y += nvkm/core/oproxy.o nvkm-y += nvkm/core/option.o nvkm-y += nvkm/core/parent.o nvkm-y += nvkm/core/ramht.o diff --git a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c new file mode 100644 index 000000000000..b2b743587168 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c @@ -0,0 +1,198 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include <core/oproxy.h> + +static int +nvkm_oproxy_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) +{ + return nvkm_object_mthd(nvkm_oproxy(object)->object, mthd, data, size); +} + +static int +nvkm_oproxy_ntfy(struct nvkm_object *object, u32 mthd, + struct nvkm_event **pevent) +{ + return nvkm_object_ntfy(nvkm_oproxy(object)->object, mthd, pevent); +} + +static int +nvkm_oproxy_map(struct nvkm_object *object, u64 *addr, u32 *size) +{ + return nvkm_object_map(nvkm_oproxy(object)->object, addr, size); +} + +static int +nvkm_oproxy_rd08(struct nvkm_object *object, u64 addr, u8 *data) +{ + return nvkm_object_rd08(nvkm_oproxy(object)->object, addr, data); +} + +static int +nvkm_oproxy_rd16(struct nvkm_object *object, u64 addr, u16 *data) +{ + return nvkm_object_rd16(nvkm_oproxy(object)->object, addr, data); +} + +static int +nvkm_oproxy_rd32(struct nvkm_object *object, u64 addr, u32 *data) +{ + return nvkm_object_rd32(nvkm_oproxy(object)->object, addr, data); +} + +static int +nvkm_oproxy_wr08(struct nvkm_object *object, u64 addr, u8 data) +{ + return nvkm_object_wr08(nvkm_oproxy(object)->object, addr, data); +} + +static int +nvkm_oproxy_wr16(struct nvkm_object *object, u64 addr, u16 data) +{ + return nvkm_object_wr16(nvkm_oproxy(object)->object, addr, data); +} + +static int +nvkm_oproxy_wr32(struct nvkm_object *object, u64 addr, u32 data) +{ + return nvkm_object_wr32(nvkm_oproxy(object)->object, addr, data); +} + +static int +nvkm_oproxy_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) +{ + return nvkm_object_bind(nvkm_oproxy(object)->object, + parent, align, pgpuobj); +} + +static int +nvkm_oproxy_sclass(struct nvkm_object *object, int index, + struct nvkm_oclass *oclass) +{ + struct nvkm_oproxy *oproxy = nvkm_oproxy(object); + oclass->parent = oproxy->object; + if (oproxy->object->oclass) + return -ENOSYS; + if (!oproxy->object->func->sclass) + return -ENODEV; + return oproxy->object->func->sclass(oproxy->object, index, oclass); +} + +static int +nvkm_oproxy_fini(struct nvkm_object *object, bool suspend) +{ + struct nvkm_oproxy *oproxy = nvkm_oproxy(object); + int ret; + + if (oproxy->func->fini[0]) { + ret = oproxy->func->fini[0](oproxy, suspend); + if (ret && suspend) + return ret; + } + + ret = nvkm_object_fini(oproxy->object, suspend); + if (ret && suspend) + return ret; + + if (oproxy->func->fini[1]) { + ret = oproxy->func->fini[1](oproxy, suspend); + if (ret && suspend) + return ret; + } + + return 0; +} + +static int +nvkm_oproxy_init(struct nvkm_object *object) +{ + struct nvkm_oproxy *oproxy = nvkm_oproxy(object); + int ret; + + if (oproxy->func->init[0]) { + ret = oproxy->func->init[0](oproxy); + if (ret) + return ret; + } + + ret = nvkm_object_init(oproxy->object); + if (ret) + return ret; + + if (oproxy->func->init[1]) { + ret = oproxy->func->init[1](oproxy); + if (ret) + return ret; + } + + return 0; +} + +static void * +nvkm_oproxy_dtor(struct nvkm_object *object) +{ + struct nvkm_oproxy *oproxy = nvkm_oproxy(object); + if (oproxy->func->dtor[0]) + oproxy->func->dtor[0](oproxy); + nvkm_object_ref(NULL, &oproxy->object); + if (oproxy->func->dtor[1]) + oproxy->func->dtor[1](oproxy); + return oproxy; +} + +static const struct nvkm_object_func +nvkm_oproxy_func = { + .dtor = nvkm_oproxy_dtor, + .init = nvkm_oproxy_init, + .fini = nvkm_oproxy_fini, + .mthd = nvkm_oproxy_mthd, + .ntfy = nvkm_oproxy_ntfy, + .map = nvkm_oproxy_map, + .rd08 = nvkm_oproxy_rd08, + .rd16 = nvkm_oproxy_rd16, + .rd32 = nvkm_oproxy_rd32, + .wr08 = nvkm_oproxy_wr08, + .wr16 = nvkm_oproxy_wr16, + .wr32 = nvkm_oproxy_wr32, + .bind = nvkm_oproxy_bind, + .sclass = nvkm_oproxy_sclass, +}; + +void +nvkm_oproxy_ctor(const struct nvkm_oproxy_func *func, + const struct nvkm_oclass *oclass, struct nvkm_oproxy *oproxy) +{ + nvkm_object_ctor(&nvkm_oproxy_func, oclass, &oproxy->base); + oproxy->func = func; +} + +int +nvkm_oproxy_new_(const struct nvkm_oproxy_func *func, + const struct nvkm_oclass *oclass, struct nvkm_oproxy **poproxy) +{ + if (!(*poproxy = kzalloc(sizeof(**poproxy), GFP_KERNEL))) + return -ENOMEM; + nvkm_oproxy_ctor(func, oclass, *poproxy); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild index 75fc7e62fb74..04f60452011e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild @@ -53,17 +53,27 @@ nvkm-y += nvkm/engine/disp/dmacgf119.o nvkm-y += nvkm/engine/disp/basenv50.o nvkm-y += nvkm/engine/disp/baseg84.o +nvkm-y += nvkm/engine/disp/basegt200.o +nvkm-y += nvkm/engine/disp/basegt215.o nvkm-y += nvkm/engine/disp/basegf119.o +nvkm-y += nvkm/engine/disp/basegk104.o +nvkm-y += nvkm/engine/disp/basegk110.o nvkm-y += nvkm/engine/disp/corenv50.o nvkm-y += nvkm/engine/disp/coreg84.o nvkm-y += nvkm/engine/disp/coreg94.o +nvkm-y += nvkm/engine/disp/coregt200.o +nvkm-y += nvkm/engine/disp/coregt215.o nvkm-y += nvkm/engine/disp/coregf119.o nvkm-y += nvkm/engine/disp/coregk104.o +nvkm-y += nvkm/engine/disp/coregk110.o +nvkm-y += nvkm/engine/disp/coregm107.o +nvkm-y += nvkm/engine/disp/coregm204.o nvkm-y += nvkm/engine/disp/ovlynv50.o nvkm-y += nvkm/engine/disp/ovlyg84.o nvkm-y += nvkm/engine/disp/ovlygt200.o +nvkm-y += nvkm/engine/disp/ovlygt215.o nvkm-y += nvkm/engine/disp/ovlygf119.o nvkm-y += nvkm/engine/disp/ovlygk104.o @@ -71,7 +81,13 @@ nvkm-y += nvkm/engine/disp/piocnv50.o nvkm-y += nvkm/engine/disp/piocgf119.o nvkm-y += nvkm/engine/disp/cursnv50.o +nvkm-y += nvkm/engine/disp/cursg84.o +nvkm-y += nvkm/engine/disp/cursgt215.o nvkm-y += nvkm/engine/disp/cursgf119.o +nvkm-y += nvkm/engine/disp/cursgk104.o nvkm-y += nvkm/engine/disp/oimmnv50.o +nvkm-y += nvkm/engine/disp/oimmg84.o +nvkm-y += nvkm/engine/disp/oimmgt215.o nvkm-y += nvkm/engine/disp/oimmgf119.o +nvkm-y += nvkm/engine/disp/oimmgk104.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c index fea8516220f3..165f9d47d11d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c @@ -25,7 +25,9 @@ #include "conn.h" #include "outp.h" +#include <core/client.h> #include <core/notify.h> +#include <core/oproxy.h> #include <subdev/bios.h> #include <subdev/bios/dcb.h> @@ -114,6 +116,66 @@ nvkm_disp_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **event) return -EINVAL; } +static void +nvkm_disp_class_del(struct nvkm_oproxy *oproxy) +{ + struct nvkm_disp *disp = nvkm_disp(oproxy->base.engine); + mutex_lock(&disp->engine.subdev.mutex); + if (disp->client == oproxy) + disp->client = NULL; + mutex_unlock(&disp->engine.subdev.mutex); +} + +static const struct nvkm_oproxy_func +nvkm_disp_class = { + .dtor[1] = nvkm_disp_class_del, +}; + +static int +nvkm_disp_class_new(struct nvkm_device *device, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + const struct nvkm_disp_oclass *sclass = oclass->engn; + struct nvkm_disp *disp = nvkm_disp(oclass->engine); + struct nvkm_oproxy *oproxy; + int ret; + + ret = nvkm_oproxy_new_(&nvkm_disp_class, oclass, &oproxy); + if (ret) + return ret; + *pobject = &oproxy->base; + + mutex_lock(&disp->engine.subdev.mutex); + if (disp->client) { + mutex_unlock(&disp->engine.subdev.mutex); + return -EBUSY; + } + disp->client = oproxy; + mutex_unlock(&disp->engine.subdev.mutex); + + return sclass->ctor(disp, oclass, data, size, &oproxy->object); +} + +static const struct nvkm_device_oclass +nvkm_disp_sclass = { + .ctor = nvkm_disp_class_new, +}; + +static int +nvkm_disp_class_get(struct nvkm_oclass *oclass, int index, + const struct nvkm_device_oclass **class) +{ + struct nvkm_disp *disp = nvkm_disp(oclass->engine); + if (index == 0) { + oclass->base = disp->func->root->base; + oclass->engn = disp->func->root; + *class = &nvkm_disp_sclass; + return 0; + } + return 1; +} + int _nvkm_disp_fini(struct nvkm_object *object, bool suspend) { @@ -180,6 +242,11 @@ _nvkm_disp_dtor(struct nvkm_object *object) nvkm_engine_destroy(&disp->engine); } +static const struct nvkm_engine_func +nvkm_disp = { + .base.sclass = nvkm_disp_class_get, +}; + int nvkm_disp_create_(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, int heads, const char *intname, @@ -203,6 +270,7 @@ nvkm_disp_create_(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; + disp->engine.func = &nvkm_disp; INIT_LIST_HEAD(&disp->outp); INIT_LIST_HEAD(&disp->conn); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c index c476ed0d70ae..6d17630a3dee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c @@ -22,6 +22,9 @@ * Authors: Ben Skeggs */ #include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> static const struct nv50_disp_mthd_list g84_disp_base_mthd_base = { @@ -53,13 +56,25 @@ g84_disp_base_mthd_base = { } }; -const struct nv50_disp_mthd_chan -g84_disp_base_mthd_chan = { +const struct nv50_disp_chan_mthd +g84_disp_base_chan_mthd = { .name = "Base", .addr = 0x000540, + .prev = 0x000004, .data = { { "Global", 1, &g84_disp_base_mthd_base }, { "Image", 2, &nv50_disp_base_mthd_image }, {} } }; + +const struct nv50_disp_dmac_oclass +g84_disp_base_oclass = { + .base.oclass = G82_DISP_BASE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_base_new, + .func = &nv50_disp_dmac_func, + .mthd = &g84_disp_base_chan_mthd, + .chid = 1, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c index d3c37b49d31c..ebcb925e9d90 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c @@ -22,6 +22,9 @@ * Authors: Ben Skeggs */ #include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> static const struct nv50_disp_mthd_list gf119_disp_base_mthd_base = { @@ -87,10 +90,11 @@ gf119_disp_base_mthd_image = { } }; -const struct nv50_disp_mthd_chan -gf119_disp_base_mthd_chan = { +const struct nv50_disp_chan_mthd +gf119_disp_base_chan_mthd = { .name = "Base", .addr = 0x001000, + .prev = -0x020000, .data = { { "Global", 1, &gf119_disp_base_mthd_base }, { "Image", 2, &gf119_disp_base_mthd_image }, @@ -98,17 +102,13 @@ gf119_disp_base_mthd_chan = { } }; -struct nv50_disp_chan_impl -gf119_disp_base_ofuncs = { - .base.ctor = nv50_disp_base_ctor, - .base.dtor = nv50_disp_dmac_dtor, - .base.init = gf119_disp_dmac_init, - .base.fini = gf119_disp_dmac_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, +const struct nv50_disp_dmac_oclass +gf119_disp_base_oclass = { + .base.oclass = GF110_DISP_BASE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_base_new, + .func = &gf119_disp_dmac_func, + .mthd = &gf119_disp_base_chan_mthd, .chid = 1, - .attach = gf119_disp_dmac_object_attach, - .detach = gf119_disp_dmac_object_detach, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk104.c new file mode 100644 index 000000000000..780a1d973634 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk104.c @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_dmac_oclass +gk104_disp_base_oclass = { + .base.oclass = GK104_DISP_BASE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_base_new, + .func = &gf119_disp_dmac_func, + .mthd = &gf119_disp_base_chan_mthd, + .chid = 1, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk110.c new file mode 100644 index 000000000000..d8bdd246c8ed --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk110.c @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_dmac_oclass +gk110_disp_base_oclass = { + .base.oclass = GK110_DISP_BASE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_base_new, + .func = &gf119_disp_dmac_func, + .mthd = &gf119_disp_base_chan_mthd, + .chid = 1, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt200.c new file mode 100644 index 000000000000..93451e46570c --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt200.c @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_dmac_oclass +gt200_disp_base_oclass = { + .base.oclass = GT200_DISP_BASE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_base_new, + .func = &nv50_disp_dmac_func, + .mthd = &g84_disp_base_chan_mthd, + .chid = 1, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt215.c new file mode 100644 index 000000000000..08e2b1fa3806 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt215.c @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_dmac_oclass +gt215_disp_base_oclass = { + .base.oclass = GT214_DISP_BASE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_base_new, + .func = &nv50_disp_dmac_func, + .mthd = &g84_disp_base_chan_mthd, + .chid = 1, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c index cfb1eac55958..52775d88dd8f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c @@ -22,12 +22,44 @@ * Authors: Ben Skeggs */ #include "dmacnv50.h" +#include "rootnv50.h" #include <core/client.h> #include <nvif/class.h> #include <nvif/unpack.h> +int +nv50_disp_base_new(const struct nv50_disp_dmac_func *func, + const struct nv50_disp_chan_mthd *mthd, + struct nv50_disp_root *root, int chid, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + union { + struct nv50_disp_base_channel_dma_v0 v0; + } *args = data; + struct nvkm_object *parent = oclass->parent; + struct nv50_disp *disp = root->disp; + int head, ret; + u64 push; + + nvif_ioctl(parent, "create disp base channel dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create disp base channel dma vers %d " + "pushbuf %016llx head %d\n", + args->v0.version, args->v0.pushbuf, args->v0.head); + if (args->v0.head > disp->head.nr) + return -EINVAL; + push = args->v0.pushbuf; + head = args->v0.head; + } else + return ret; + + return nv50_disp_dmac_new_(func, mthd, root, chid + head, + head, push, oclass, pobject); +} + static const struct nv50_disp_mthd_list nv50_disp_base_mthd_base = { .mthd = 0x0000, @@ -67,10 +99,11 @@ nv50_disp_base_mthd_image = { } }; -const struct nv50_disp_mthd_chan -nv50_disp_base_mthd_chan = { +static const struct nv50_disp_chan_mthd +nv50_disp_base_chan_mthd = { .name = "Base", .addr = 0x000540, + .prev = 0x000004, .data = { { "Global", 1, &nv50_disp_base_mthd_base }, { "Image", 2, &nv50_disp_base_mthd_image }, @@ -78,50 +111,13 @@ nv50_disp_base_mthd_chan = { } }; -int -nv50_disp_base_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_base_channel_dma_v0 v0; - } *args = data; - struct nv50_disp *disp = (void *)engine; - struct nv50_disp_dmac *dmac; - int ret; - - nvif_ioctl(parent, "create disp base channel dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nvif_ioctl(parent, "create disp base channel dma vers %d " - "pushbuf %016llx head %d\n", - args->v0.version, args->v0.pushbuf, args->v0.head); - if (args->v0.head > disp->head.nr) - return -EINVAL; - } else - return ret; - - ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf, - args->v0.head, sizeof(*dmac), - (void **)&dmac); - *pobject = nv_object(dmac); - if (ret) - return ret; - - return 0; -} - -struct nv50_disp_chan_impl -nv50_disp_base_ofuncs = { - .base.ctor = nv50_disp_base_ctor, - .base.dtor = nv50_disp_dmac_dtor, - .base.init = nv50_disp_dmac_init, - .base.fini = nv50_disp_dmac_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, +const struct nv50_disp_dmac_oclass +nv50_disp_base_oclass = { + .base.oclass = NV50_DISP_BASE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_base_new, + .func = &nv50_disp_dmac_func, + .mthd = &nv50_disp_base_chan_mthd, .chid = 1, - .attach = nv50_disp_dmac_object_attach, - .detach = nv50_disp_dmac_object_detach, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c index 2999996497ff..c9cbfbd2a1ae 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c @@ -24,6 +24,10 @@ #include "channv50.h" #include "rootnv50.h" +#include <core/client.h> +#include <core/ramht.h> +#include <engine/dma.h> + #include <nvif/class.h> #include <nvif/event.h> #include <nvif/unpack.h> @@ -58,39 +62,38 @@ nv50_disp_mthd_list(struct nv50_disp *disp, int debug, u32 base, int c, } void -nv50_disp_mthd_chan(struct nv50_disp *disp, int debug, int head, - const struct nv50_disp_mthd_chan *chan) +nv50_disp_chan_mthd(struct nv50_disp_chan *chan, int debug) { - struct nvkm_object *object = nv_object(disp); - const struct nv50_disp_impl *impl = (void *)object->oclass; - const struct nv50_disp_mthd_list *list; + struct nv50_disp *disp = chan->root->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; + const struct nv50_disp_chan_mthd *mthd = chan->mthd; + const struct nv50_disp_mthd_list *list; int i, j; - if (debug > nv_subdev(disp)->debug) + if (debug > subdev->debug) return; - for (i = 0; (list = chan->data[i].mthd) != NULL; i++) { - u32 base = head * chan->addr; - for (j = 0; j < chan->data[i].nr; j++, base += list->addr) { - const char *cname = chan->name; + for (i = 0; (list = mthd->data[i].mthd) != NULL; i++) { + u32 base = chan->head * mthd->addr; + for (j = 0; j < mthd->data[i].nr; j++, base += list->addr) { + const char *cname = mthd->name; const char *sname = ""; char cname_[16], sname_[16]; - if (chan->addr) { + if (mthd->addr) { snprintf(cname_, sizeof(cname_), "%s %d", - chan->name, head); + mthd->name, chan->chid); cname = cname_; } - if (chan->data[i].nr > 1) { + if (mthd->data[i].nr > 1) { snprintf(sname_, sizeof(sname_), " - %s %d", - chan->data[i].name, j); + mthd->data[i].name, j); sname = sname_; } nvkm_printk_(subdev, debug, info, "%s%s:\n", cname, sname); - nv50_disp_mthd_list(disp, debug, base, impl->mthd.prev, + nv50_disp_mthd_list(disp, debug, base, mthd->prev, list, j); } } @@ -127,7 +130,7 @@ int nv50_disp_chan_uevent_ctor(struct nvkm_object *object, void *data, u32 size, struct nvkm_notify *notify) { - struct nv50_disp_dmac *dmac = (void *)object; + struct nv50_disp_chan *chan = nv50_disp_chan(object); union { struct nvif_notify_uevent_req none; } *args = data; @@ -136,7 +139,7 @@ nv50_disp_chan_uevent_ctor(struct nvkm_object *object, void *data, u32 size, if (nvif_unvers(args->none)) { notify->size = sizeof(struct nvif_notify_uevent_rep); notify->types = 1; - notify->index = dmac->base.chid; + notify->index = chan->chid; return 0; } @@ -151,10 +154,31 @@ nv50_disp_chan_uevent = { }; int +nv50_disp_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data) +{ + struct nv50_disp_chan *chan = nv50_disp_chan(object); + struct nv50_disp *disp = chan->root->disp; + struct nvkm_device *device = disp->base.engine.subdev.device; + *data = nvkm_rd32(device, 0x640000 + (chan->chid * 0x1000) + addr); + return 0; +} + +int +nv50_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data) +{ + struct nv50_disp_chan *chan = nv50_disp_chan(object); + struct nv50_disp *disp = chan->root->disp; + struct nvkm_device *device = disp->base.engine.subdev.device; + nvkm_wr32(device, 0x640000 + (chan->chid * 0x1000) + addr, data); + return 0; +} + +int nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **pevent) { - struct nv50_disp *disp = (void *)object->engine; + struct nv50_disp_chan *chan = nv50_disp_chan(object); + struct nv50_disp *disp = chan->root->disp; switch (type) { case NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT: *pevent = &disp->uevent; @@ -168,62 +192,110 @@ nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type, int nv50_disp_chan_map(struct nvkm_object *object, u64 *addr, u32 *size) { - struct nv50_disp_chan *chan = (void *)object; - *addr = nv_device_resource_start(nv_device(object), 0) + + struct nv50_disp_chan *chan = nv50_disp_chan(object); + struct nv50_disp *disp = chan->root->disp; + struct nvkm_device *device = disp->base.engine.subdev.device; + *addr = nv_device_resource_start(device, 0) + 0x640000 + (chan->chid * 0x1000); *size = 0x001000; return 0; } -u32 -nv50_disp_chan_rd32(struct nvkm_object *object, u64 addr) +static int +nv50_disp_chan_child_new(const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) { - struct nv50_disp_chan *chan = (void *)object; - struct nvkm_device *device = object->engine->subdev.device; - return nvkm_rd32(device, 0x640000 + (chan->chid * 0x1000) + addr); + struct nv50_disp_chan *chan = nv50_disp_chan(oclass->parent); + return chan->func->child_new(chan, oclass, data, size, pobject); } -void -nv50_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data) +static int +nv50_disp_chan_child_get(struct nvkm_object *object, int index, + struct nvkm_oclass *oclass) { - struct nv50_disp_chan *chan = (void *)object; - struct nvkm_device *device = object->engine->subdev.device; - nvkm_wr32(device, 0x640000 + (chan->chid * 0x1000) + addr, data); + struct nv50_disp_chan *chan = nv50_disp_chan(object); + if (chan->func->child_get) { + int ret = chan->func->child_get(chan, index, oclass); + if (ret == 0) + oclass->ctor = nv50_disp_chan_child_new; + return ret; + } + return -EINVAL; } -void -nv50_disp_chan_destroy(struct nv50_disp_chan *chan) +static int +nv50_disp_chan_fini(struct nvkm_object *object, bool suspend) { - struct nv50_disp_root *root = (void *)nv_object(chan)->parent; - root->chan &= ~(1 << chan->chid); - nvkm_namedb_destroy(&chan->base); + struct nv50_disp_chan *chan = nv50_disp_chan(object); + chan->func->fini(chan); + return 0; } -int -nv50_disp_chan_create_(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, int head, - int length, void **pobject) +static int +nv50_disp_chan_init(struct nvkm_object *object) { - const struct nv50_disp_chan_impl *impl = (void *)oclass->ofuncs; - struct nv50_disp_root *root = (void *)parent; - struct nv50_disp_chan *chan; - int chid = impl->chid + head; - int ret; + struct nv50_disp_chan *chan = nv50_disp_chan(object); + return chan->func->init(chan); +} - if (root->chan & (1 << chid)) - return -EBUSY; - root->chan |= (1 << chid); +static void * +nv50_disp_chan_dtor(struct nvkm_object *object) +{ + struct nv50_disp_chan *chan = nv50_disp_chan(object); + struct nv50_disp *disp = chan->root->disp; + if (chan->chid >= 0) + disp->chan[chan->chid] = NULL; + return chan->func->dtor ? chan->func->dtor(chan) : chan; +} - ret = nvkm_namedb_create_(parent, engine, oclass, 0, NULL, - (1ULL << NVDEV_ENGINE_DMAOBJ), - length, pobject); - chan = *pobject; - if (ret) - return ret; +static const struct nvkm_object_func +nv50_disp_chan = { + .dtor = nv50_disp_chan_dtor, + .init = nv50_disp_chan_init, + .fini = nv50_disp_chan_fini, + .rd32 = nv50_disp_chan_rd32, + .wr32 = nv50_disp_chan_wr32, + .ntfy = nv50_disp_chan_ntfy, + .map = nv50_disp_chan_map, + .sclass = nv50_disp_chan_child_get, +}; + +int +nv50_disp_chan_ctor(const struct nv50_disp_chan_func *func, + const struct nv50_disp_chan_mthd *mthd, + struct nv50_disp_root *root, int chid, int head, + const struct nvkm_oclass *oclass, + struct nv50_disp_chan *chan) +{ + struct nv50_disp *disp = root->disp; + + nvkm_object_ctor(&nv50_disp_chan, oclass, &chan->object); + chan->func = func; + chan->mthd = mthd; + chan->root = root; chan->chid = chid; + chan->head = head; - nv_parent(chan)->object_attach = impl->attach; - nv_parent(chan)->object_detach = impl->detach; + if (disp->chan[chan->chid]) { + chan->chid = -1; + return -EBUSY; + } + disp->chan[chan->chid] = chan; return 0; } + +int +nv50_disp_chan_new_(const struct nv50_disp_chan_func *func, + const struct nv50_disp_chan_mthd *mthd, + struct nv50_disp_root *root, int chid, int head, + const struct nvkm_oclass *oclass, + struct nvkm_object **pobject) +{ + struct nv50_disp_chan *chan; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->object; + + return nv50_disp_chan_ctor(func, mthd, root, chid, head, oclass, chan); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h index 982d1bfe9a6b..aee374884c96 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h @@ -1,28 +1,40 @@ #ifndef __NV50_DISP_CHAN_H__ #define __NV50_DISP_CHAN_H__ +#define nv50_disp_chan(p) container_of((p), struct nv50_disp_chan, object) #include "nv50.h" -struct nv50_disp_chan_impl { - struct nvkm_ofuncs base; +struct nv50_disp_chan { + const struct nv50_disp_chan_func *func; + const struct nv50_disp_chan_mthd *mthd; + struct nv50_disp_root *root; int chid; - int (*attach)(struct nvkm_object *, struct nvkm_object *, u32); - void (*detach)(struct nvkm_object *, int); -}; + int head; -#include <core/namedb.h> + struct nvkm_object object; +}; -struct nv50_disp_chan { - struct nvkm_namedb base; - int chid; +struct nv50_disp_chan_func { + void *(*dtor)(struct nv50_disp_chan *); + int (*init)(struct nv50_disp_chan *); + void (*fini)(struct nv50_disp_chan *); + int (*child_get)(struct nv50_disp_chan *, int index, + struct nvkm_oclass *); + int (*child_new)(struct nv50_disp_chan *, const struct nvkm_oclass *, + void *data, u32 size, struct nvkm_object **); }; -int nv50_disp_chan_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, int, void **); -void nv50_disp_chan_destroy(struct nv50_disp_chan *); -int nv50_disp_chan_ntfy(struct nvkm_object *, u32, struct nvkm_event **); -int nv50_disp_chan_map(struct nvkm_object *, u64 *, u32 *); -u32 nv50_disp_chan_rd32(struct nvkm_object *, u64); -void nv50_disp_chan_wr32(struct nvkm_object *, u64, u32); +int nv50_disp_chan_ctor(const struct nv50_disp_chan_func *, + const struct nv50_disp_chan_mthd *, + struct nv50_disp_root *, int chid, int head, + const struct nvkm_oclass *, struct nv50_disp_chan *); +int nv50_disp_chan_new_(const struct nv50_disp_chan_func *, + const struct nv50_disp_chan_mthd *, + struct nv50_disp_root *, int chid, int head, + const struct nvkm_oclass *, struct nvkm_object **); + +extern const struct nv50_disp_chan_func nv50_disp_pioc_func; +extern const struct nv50_disp_chan_func gf119_disp_pioc_func; + extern const struct nvkm_event_func nv50_disp_chan_uevent; int nv50_disp_chan_uevent_ctor(struct nvkm_object *, void *, u32, struct nvkm_notify *); @@ -30,24 +42,6 @@ void nv50_disp_chan_uevent_send(struct nv50_disp *, int); extern const struct nvkm_event_func gf119_disp_chan_uevent; -#define nv50_disp_chan_init(a) \ - nvkm_namedb_init(&(a)->base) -#define nv50_disp_chan_fini(a,b) \ - nvkm_namedb_fini(&(a)->base, (b)) - -struct nv50_disp_pioc { - struct nv50_disp_chan base; -}; - -int nv50_disp_pioc_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, int, void **); -void nv50_disp_pioc_dtor(struct nvkm_object *); -int nv50_disp_pioc_init(struct nvkm_object *); -int nv50_disp_pioc_fini(struct nvkm_object *, bool); - -int gf119_disp_pioc_init(struct nvkm_object *); -int gf119_disp_pioc_fini(struct nvkm_object *, bool); - struct nv50_disp_mthd_list { u32 mthd; u32 addr; @@ -58,9 +52,10 @@ struct nv50_disp_mthd_list { } data[]; }; -struct nv50_disp_mthd_chan { +struct nv50_disp_chan_mthd { const char *name; u32 addr; + s32 prev; struct { const char *name; int nr; @@ -68,36 +63,65 @@ struct nv50_disp_mthd_chan { } data[]; }; -void nv50_disp_mthd_chan(struct nv50_disp *, int debug, int head, - const struct nv50_disp_mthd_chan *); +void nv50_disp_chan_mthd(struct nv50_disp_chan *, int debug); -extern const struct nv50_disp_mthd_chan nv50_disp_core_mthd_chan; extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_base; extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_sor; extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_pior; -extern const struct nv50_disp_mthd_chan nv50_disp_base_mthd_chan; extern const struct nv50_disp_mthd_list nv50_disp_base_mthd_image; -extern const struct nv50_disp_mthd_chan nv50_disp_ovly_mthd_chan; -extern const struct nv50_disp_mthd_list nv50_disp_ovly_mthd_base; -extern const struct nv50_disp_mthd_chan g84_disp_core_mthd_chan; +extern const struct nv50_disp_chan_mthd g84_disp_core_chan_mthd; extern const struct nv50_disp_mthd_list g84_disp_core_mthd_dac; extern const struct nv50_disp_mthd_list g84_disp_core_mthd_head; -extern const struct nv50_disp_mthd_chan g84_disp_base_mthd_chan; -extern const struct nv50_disp_mthd_chan g84_disp_ovly_mthd_chan; - -extern const struct nv50_disp_mthd_chan g94_disp_core_mthd_chan; +extern const struct nv50_disp_chan_mthd g84_disp_base_chan_mthd; +extern const struct nv50_disp_chan_mthd g84_disp_ovly_chan_mthd; -extern const struct nv50_disp_mthd_chan gt200_disp_ovly_mthd_chan; +extern const struct nv50_disp_chan_mthd g94_disp_core_chan_mthd; -extern const struct nv50_disp_mthd_chan gf119_disp_core_mthd_chan; extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_base; extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_dac; extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_sor; extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_pior; -extern const struct nv50_disp_mthd_chan gf119_disp_base_mthd_chan; -extern const struct nv50_disp_mthd_chan gf119_disp_ovly_mthd_chan; +extern const struct nv50_disp_chan_mthd gf119_disp_base_chan_mthd; + +extern const struct nv50_disp_chan_mthd gk104_disp_core_chan_mthd; + +struct nv50_disp_pioc_oclass { + int (*ctor)(const struct nv50_disp_chan_func *, + const struct nv50_disp_chan_mthd *, + struct nv50_disp_root *, int chid, + const struct nvkm_oclass *, void *data, u32 size, + struct nvkm_object **); + struct nvkm_sclass base; + const struct nv50_disp_chan_func *func; + const struct nv50_disp_chan_mthd *mthd; + int chid; +}; + +extern const struct nv50_disp_pioc_oclass nv50_disp_oimm_oclass; +extern const struct nv50_disp_pioc_oclass nv50_disp_curs_oclass; + +extern const struct nv50_disp_pioc_oclass g84_disp_oimm_oclass; +extern const struct nv50_disp_pioc_oclass g84_disp_curs_oclass; + +extern const struct nv50_disp_pioc_oclass gt215_disp_oimm_oclass; +extern const struct nv50_disp_pioc_oclass gt215_disp_curs_oclass; + +extern const struct nv50_disp_pioc_oclass gf119_disp_oimm_oclass; +extern const struct nv50_disp_pioc_oclass gf119_disp_curs_oclass; + +extern const struct nv50_disp_pioc_oclass gk104_disp_oimm_oclass; +extern const struct nv50_disp_pioc_oclass gk104_disp_curs_oclass; + -extern const struct nv50_disp_mthd_chan gk104_disp_core_mthd_chan; -extern const struct nv50_disp_mthd_chan gk104_disp_ovly_mthd_chan; +int nv50_disp_curs_new(const struct nv50_disp_chan_func *, + const struct nv50_disp_chan_mthd *, + struct nv50_disp_root *, int chid, + const struct nvkm_oclass *, void *data, u32 size, + struct nvkm_object **); +int nv50_disp_oimm_new(const struct nv50_disp_chan_func *, + const struct nv50_disp_chan_mthd *, + struct nv50_disp_root *, int chid, + const struct nvkm_oclass *, void *data, u32 size, + struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c index 29b020f025e3..1baa5c34b327 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c @@ -22,6 +22,9 @@ * Authors: Ben Skeggs */ #include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> const struct nv50_disp_mthd_list g84_disp_core_mthd_dac = { @@ -87,10 +90,11 @@ g84_disp_core_mthd_head = { } }; -const struct nv50_disp_mthd_chan -g84_disp_core_mthd_chan = { +const struct nv50_disp_chan_mthd +g84_disp_core_chan_mthd = { .name = "Core", .addr = 0x000000, + .prev = 0x000004, .data = { { "Global", 1, &nv50_disp_core_mthd_base }, { "DAC", 3, &g84_disp_core_mthd_dac }, @@ -100,3 +104,14 @@ g84_disp_core_mthd_chan = { {} } }; + +const struct nv50_disp_dmac_oclass +g84_disp_core_oclass = { + .base.oclass = G82_DISP_CORE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_core_new, + .func = &nv50_disp_core_func, + .mthd = &g84_disp_core_chan_mthd, + .chid = 0, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c index 81455256ebb1..019379a3a01c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c @@ -22,6 +22,9 @@ * Authors: Ben Skeggs */ #include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> const struct nv50_disp_mthd_list g94_disp_core_mthd_sor = { @@ -33,10 +36,11 @@ g94_disp_core_mthd_sor = { } }; -const struct nv50_disp_mthd_chan -g94_disp_core_mthd_chan = { +const struct nv50_disp_chan_mthd +g94_disp_core_chan_mthd = { .name = "Core", .addr = 0x000000, + .prev = 0x000004, .data = { { "Global", 1, &nv50_disp_core_mthd_base }, { "DAC", 3, &g84_disp_core_mthd_dac }, @@ -46,3 +50,14 @@ g94_disp_core_mthd_chan = { {} } }; + +const struct nv50_disp_dmac_oclass +g94_disp_core_oclass = { + .base.oclass = GT206_DISP_CORE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_core_new, + .func = &nv50_disp_core_func, + .mthd = &g94_disp_core_chan_mthd, + .chid = 0, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c index 87f5c43115c1..6b1dc703dac7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c @@ -22,9 +22,14 @@ * Authors: Ben Skeggs */ #include "dmacnv50.h" +#include "rootnv50.h" +#include <core/client.h> #include <subdev/timer.h> +#include <nvif/class.h> +#include <nvif/unpack.h> + const struct nv50_disp_mthd_list gf119_disp_core_mthd_base = { .mthd = 0x0000, @@ -151,10 +156,11 @@ gf119_disp_core_mthd_head = { } }; -const struct nv50_disp_mthd_chan -gf119_disp_core_mthd_chan = { +static const struct nv50_disp_chan_mthd +gf119_disp_core_chan_mthd = { .name = "Core", .addr = 0x000000, + .prev = -0x020000, .data = { { "Global", 1, &gf119_disp_core_mthd_base }, { "DAC", 3, &gf119_disp_core_mthd_dac }, @@ -165,11 +171,10 @@ gf119_disp_core_mthd_chan = { } }; -static int -gf119_disp_core_fini(struct nvkm_object *object, bool suspend) +static void +gf119_disp_core_fini(struct nv50_disp_dmac *chan) { - struct nv50_disp *disp = (void *)object->engine; - struct nv50_disp_dmac *mast = (void *)object; + struct nv50_disp *disp = chan->base.root->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; @@ -182,35 +187,25 @@ gf119_disp_core_fini(struct nvkm_object *object, bool suspend) ) < 0) { nvkm_error(subdev, "core fini: %08x\n", nvkm_rd32(device, 0x610490)); - if (suspend) - return -EBUSY; } /* disable error reporting and completion notification */ nvkm_mask(device, 0x610090, 0x00000001, 0x00000000); nvkm_mask(device, 0x6100a0, 0x00000001, 0x00000000); - - return nv50_disp_chan_fini(&mast->base, suspend); } static int -gf119_disp_core_init(struct nvkm_object *object) +gf119_disp_core_init(struct nv50_disp_dmac *chan) { - struct nv50_disp *disp = (void *)object->engine; - struct nv50_disp_dmac *mast = (void *)object; + struct nv50_disp *disp = chan->base.root->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int ret; - - ret = nv50_disp_chan_init(&mast->base); - if (ret) - return ret; /* enable error reporting */ nvkm_mask(device, 0x6100a0, 0x00000001, 0x00000001); /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610494, mast->push); + nvkm_wr32(device, 0x610494, chan->push); nvkm_wr32(device, 0x610498, 0x00010000); nvkm_wr32(device, 0x61049c, 0x00000001); nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); @@ -230,17 +225,20 @@ gf119_disp_core_init(struct nvkm_object *object) return 0; } -struct nv50_disp_chan_impl -gf119_disp_core_ofuncs = { - .base.ctor = nv50_disp_core_ctor, - .base.dtor = nv50_disp_dmac_dtor, - .base.init = gf119_disp_core_init, - .base.fini = gf119_disp_core_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, +const struct nv50_disp_dmac_func +gf119_disp_core_func = { + .init = gf119_disp_core_init, + .fini = gf119_disp_core_fini, + .bind = gf119_disp_dmac_bind, +}; + +const struct nv50_disp_dmac_oclass +gf119_disp_core_oclass = { + .base.oclass = GF110_DISP_CORE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_core_new, + .func = &gf119_disp_core_func, + .mthd = &gf119_disp_core_chan_mthd, .chid = 0, - .attach = gf119_disp_dmac_object_attach, - .detach = gf119_disp_dmac_object_detach, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c index 6662cc6d70a3..088ab222e823 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c @@ -22,6 +22,9 @@ * Authors: Ben Skeggs */ #include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> static const struct nv50_disp_mthd_list gk104_disp_core_mthd_head = { @@ -102,10 +105,11 @@ gk104_disp_core_mthd_head = { } }; -const struct nv50_disp_mthd_chan -gk104_disp_core_mthd_chan = { +const struct nv50_disp_chan_mthd +gk104_disp_core_chan_mthd = { .name = "Core", .addr = 0x000000, + .prev = -0x020000, .data = { { "Global", 1, &gf119_disp_core_mthd_base }, { "DAC", 3, &gf119_disp_core_mthd_dac }, @@ -115,3 +119,14 @@ gk104_disp_core_mthd_chan = { {} } }; + +const struct nv50_disp_dmac_oclass +gk104_disp_core_oclass = { + .base.oclass = GK104_DISP_CORE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_core_new, + .func = &gf119_disp_core_func, + .mthd = &gk104_disp_core_chan_mthd, + .chid = 0, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk110.c new file mode 100644 index 000000000000..df0f45c20108 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk110.c @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_dmac_oclass +gk110_disp_core_oclass = { + .base.oclass = GK110_DISP_CORE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_core_new, + .func = &gf119_disp_core_func, + .mthd = &gk104_disp_core_chan_mthd, + .chid = 0, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm107.c new file mode 100644 index 000000000000..9e27f8fd98b6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm107.c @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_dmac_oclass +gm107_disp_core_oclass = { + .base.oclass = GM107_DISP_CORE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_core_new, + .func = &gf119_disp_core_func, + .mthd = &gk104_disp_core_chan_mthd, + .chid = 0, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm204.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm204.c new file mode 100644 index 000000000000..222f4a822f4d --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm204.c @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_dmac_oclass +gm204_disp_core_oclass = { + .base.oclass = GM204_DISP_CORE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_core_new, + .func = &gf119_disp_core_func, + .mthd = &gk104_disp_core_chan_mthd, + .chid = 0, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt200.c new file mode 100644 index 000000000000..b234547708fc --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt200.c @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_dmac_oclass +gt200_disp_core_oclass = { + .base.oclass = GT200_DISP_CORE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_core_new, + .func = &nv50_disp_core_func, + .mthd = &g84_disp_core_chan_mthd, + .chid = 0, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt215.c new file mode 100644 index 000000000000..8f5ba2018975 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt215.c @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_dmac_oclass +gt215_disp_core_oclass = { + .base.oclass = GT214_DISP_CORE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_core_new, + .func = &nv50_disp_core_func, + .mthd = &g94_disp_core_chan_mthd, + .chid = 0, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c index 624b79510175..db4a9b3e0e09 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "dmacnv50.h" +#include "rootnv50.h" #include <core/client.h> #include <subdev/timer.h> @@ -29,6 +30,33 @@ #include <nvif/class.h> #include <nvif/unpack.h> +int +nv50_disp_core_new(const struct nv50_disp_dmac_func *func, + const struct nv50_disp_chan_mthd *mthd, + struct nv50_disp_root *root, int chid, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + union { + struct nv50_disp_core_channel_dma_v0 v0; + } *args = data; + struct nvkm_object *parent = oclass->parent; + u64 push; + int ret; + + nvif_ioctl(parent, "create disp core channel dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create disp core channel dma vers %d " + "pushbuf %016llx\n", + args->v0.version, args->v0.pushbuf); + push = args->v0.pushbuf; + } else + return ret; + + return nv50_disp_dmac_new_(func, mthd, root, chid, 0, + push, oclass, pobject); +} + const struct nv50_disp_mthd_list nv50_disp_core_mthd_base = { .mthd = 0x0000, @@ -121,10 +149,11 @@ nv50_disp_core_mthd_head = { } }; -const struct nv50_disp_mthd_chan -nv50_disp_core_mthd_chan = { +static const struct nv50_disp_chan_mthd +nv50_disp_core_chan_mthd = { .name = "Core", .addr = 0x000000, + .prev = 0x000004, .data = { { "Global", 1, &nv50_disp_core_mthd_base }, { "DAC", 3, &nv50_disp_core_mthd_dac }, @@ -135,11 +164,10 @@ nv50_disp_core_mthd_chan = { } }; -static int -nv50_disp_core_fini(struct nvkm_object *object, bool suspend) +static void +nv50_disp_core_fini(struct nv50_disp_dmac *chan) { - struct nv50_disp *disp = (void *)object->engine; - struct nv50_disp_dmac *mast = (void *)object; + struct nv50_disp *disp = chan->base.root->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; @@ -152,28 +180,18 @@ nv50_disp_core_fini(struct nvkm_object *object, bool suspend) ) < 0) { nvkm_error(subdev, "core fini: %08x\n", nvkm_rd32(device, 0x610200)); - if (suspend) - return -EBUSY; } /* disable error reporting and completion notifications */ nvkm_mask(device, 0x610028, 0x00010001, 0x00000000); - - return nv50_disp_chan_fini(&mast->base, suspend); } static int -nv50_disp_core_init(struct nvkm_object *object) +nv50_disp_core_init(struct nv50_disp_dmac *chan) { - struct nv50_disp *disp = (void *)object->engine; - struct nv50_disp_dmac *mast = (void *)object; + struct nv50_disp *disp = chan->base.root->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int ret; - - ret = nv50_disp_chan_init(&mast->base); - if (ret) - return ret; /* enable error reporting */ nvkm_mask(device, 0x610028, 0x00010000, 0x00010000); @@ -185,7 +203,7 @@ nv50_disp_core_init(struct nvkm_object *object) nvkm_mask(device, 0x610200, 0x00600000, 0x00600000); /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610204, mast->push); + nvkm_wr32(device, 0x610204, chan->push); nvkm_wr32(device, 0x610208, 0x00010000); nvkm_wr32(device, 0x61020c, 0x00000000); nvkm_mask(device, 0x610200, 0x00000010, 0x00000010); @@ -205,46 +223,20 @@ nv50_disp_core_init(struct nvkm_object *object) return 0; } -int -nv50_disp_core_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_core_channel_dma_v0 v0; - } *args = data; - struct nv50_disp_dmac *mast; - int ret; - - nvif_ioctl(parent, "create disp core channel dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nvif_ioctl(parent, "create disp core channel dma vers %d " - "pushbuf %016llx\n", - args->v0.version, args->v0.pushbuf); - } else - return ret; - - ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf, - 0, sizeof(*mast), (void **)&mast); - *pobject = nv_object(mast); - if (ret) - return ret; - - return 0; -} +const struct nv50_disp_dmac_func +nv50_disp_core_func = { + .init = nv50_disp_core_init, + .fini = nv50_disp_core_fini, + .bind = nv50_disp_dmac_bind, +}; -struct nv50_disp_chan_impl -nv50_disp_core_ofuncs = { - .base.ctor = nv50_disp_core_ctor, - .base.dtor = nv50_disp_dmac_dtor, - .base.init = nv50_disp_core_init, - .base.fini = nv50_disp_core_fini, - .base.map = nv50_disp_chan_map, - .base.ntfy = nv50_disp_chan_ntfy, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, +const struct nv50_disp_dmac_oclass +nv50_disp_core_oclass = { + .base.oclass = NV50_DISP_CORE_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_core_new, + .func = &nv50_disp_core_func, + .mthd = &nv50_disp_core_chan_mthd, .chid = 0, - .attach = nv50_disp_dmac_object_attach, - .detach = nv50_disp_dmac_object_detach, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c new file mode 100644 index 000000000000..dd99fc7060b1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c @@ -0,0 +1,37 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "channv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_pioc_oclass +g84_disp_curs_oclass = { + .base.oclass = G82_DISP_CURSOR, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_curs_new, + .func = &nv50_disp_pioc_func, + .chid = 7, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c index 5537a4ae4e15..2a1574e06ad6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c @@ -22,16 +22,16 @@ * Authors: Ben Skeggs */ #include "channv50.h" +#include "rootnv50.h" -struct nv50_disp_chan_impl -gf119_disp_curs_ofuncs = { - .base.ctor = nv50_disp_curs_ctor, - .base.dtor = nv50_disp_pioc_dtor, - .base.init = gf119_disp_pioc_init, - .base.fini = gf119_disp_pioc_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, +#include <nvif/class.h> + +const struct nv50_disp_pioc_oclass +gf119_disp_curs_oclass = { + .base.oclass = GF110_DISP_CURSOR, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_curs_new, + .func = &gf119_disp_pioc_func, .chid = 13, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c new file mode 100644 index 000000000000..28e8f06c9472 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c @@ -0,0 +1,37 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ +#include "channv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_pioc_oclass +gk104_disp_curs_oclass = { + .base.oclass = GK104_DISP_CURSOR, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_curs_new, + .func = &gf119_disp_pioc_func, + .chid = 13, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c new file mode 100644 index 000000000000..d8a4b9ca139c --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c @@ -0,0 +1,37 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "channv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_pioc_oclass +gt215_disp_curs_oclass = { + .base.oclass = GT214_DISP_CURSOR, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_curs_new, + .func = &nv50_disp_pioc_func, + .chid = 7, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c index 2b4e877347cb..f3ce583fbcf2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "channv50.h" +#include "rootnv50.h" #include <core/client.h> @@ -29,17 +30,18 @@ #include <nvif/unpack.h> int -nv50_disp_curs_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_disp_curs_new(const struct nv50_disp_chan_func *func, + const struct nv50_disp_chan_mthd *mthd, + struct nv50_disp_root *root, int chid, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) { union { struct nv50_disp_cursor_v0 v0; } *args = data; - struct nv50_disp *disp = (void *)engine; - struct nv50_disp_pioc *pioc; - int ret; + struct nvkm_object *parent = oclass->parent; + struct nv50_disp *disp = root->disp; + int head, ret; nvif_ioctl(parent, "create disp cursor size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { @@ -47,27 +49,20 @@ nv50_disp_curs_ctor(struct nvkm_object *parent, args->v0.version, args->v0.head); if (args->v0.head > disp->head.nr) return -EINVAL; + head = args->v0.head; } else return ret; - ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head, - sizeof(*pioc), (void **)&pioc); - *pobject = nv_object(pioc); - if (ret) - return ret; - - return 0; + return nv50_disp_chan_new_(func, mthd, root, chid + head, + head, oclass, pobject); } -struct nv50_disp_chan_impl -nv50_disp_curs_ofuncs = { - .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.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, +const struct nv50_disp_pioc_oclass +nv50_disp_curs_oclass = { + .base.oclass = NV50_DISP_CURSOR, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_curs_new, + .func = &nv50_disp_pioc_func, .chid = 7, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c index 6add32fa24d8..876b14549a58 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c @@ -27,32 +27,22 @@ #include <core/ramht.h> #include <subdev/timer.h> -void -gf119_disp_dmac_object_detach(struct nvkm_object *parent, int cookie) -{ - struct nv50_disp_root *root = (void *)parent->parent; - nvkm_ramht_remove(root->ramht, cookie); -} - int -gf119_disp_dmac_object_attach(struct nvkm_object *parent, - struct nvkm_object *object, u32 name) +gf119_disp_dmac_bind(struct nv50_disp_dmac *chan, + struct nvkm_object *object, u32 handle) { - struct nv50_disp_root *root = (void *)parent->parent; - struct nv50_disp_chan *chan = (void *)parent; - u32 addr = nv_gpuobj(object)->node->offset; - u32 data = (chan->chid << 27) | (addr << 9) | 0x00000001; - return nvkm_ramht_insert(root->ramht, NULL, chan->chid, 0, name, data); + return nvkm_ramht_insert(chan->base.root->ramht, object, + chan->base.chid, -9, handle, + chan->base.chid << 27 | 0x00000001); } -int -gf119_disp_dmac_fini(struct nvkm_object *object, bool suspend) +static void +gf119_disp_dmac_fini(struct nv50_disp_dmac *chan) { - struct nv50_disp *disp = (void *)object->engine; - struct nv50_disp_dmac *dmac = (void *)object; + struct nv50_disp *disp = chan->base.root->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int chid = dmac->base.chid; + int chid = chan->base.chid; /* deactivate channel */ nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00001010, 0x00001000); @@ -63,36 +53,26 @@ gf119_disp_dmac_fini(struct nvkm_object *object, bool suspend) ) < 0) { nvkm_error(subdev, "ch %d fini: %08x\n", chid, nvkm_rd32(device, 0x610490 + (chid * 0x10))); - if (suspend) - return -EBUSY; } /* disable error reporting and completion notification */ nvkm_mask(device, 0x610090, 0x00000001 << chid, 0x00000000); nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000000); - - return nv50_disp_chan_fini(&dmac->base, suspend); } -int -gf119_disp_dmac_init(struct nvkm_object *object) +static int +gf119_disp_dmac_init(struct nv50_disp_dmac *chan) { - struct nv50_disp *disp = (void *)object->engine; - struct nv50_disp_dmac *dmac = (void *)object; + struct nv50_disp *disp = chan->base.root->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int chid = dmac->base.chid; - int ret; - - ret = nv50_disp_chan_init(&dmac->base); - if (ret) - return ret; + int chid = chan->base.chid; /* enable error reporting */ nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610494 + (chid * 0x0010), dmac->push); + nvkm_wr32(device, 0x610494 + (chid * 0x0010), chan->push); nvkm_wr32(device, 0x610498 + (chid * 0x0010), 0x00010000); nvkm_wr32(device, 0x61049c + (chid * 0x0010), 0x00000001); nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00000010, 0x00000010); @@ -111,3 +91,10 @@ gf119_disp_dmac_init(struct nvkm_object *object) return 0; } + +const struct nv50_disp_dmac_func +gf119_disp_dmac_func = { + .init = gf119_disp_dmac_init, + .fini = gf119_disp_dmac_fini, + .bind = gf119_disp_dmac_bind, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c index 43c17d07e96e..9ad9512782a5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c @@ -26,38 +26,172 @@ #include <core/client.h> #include <core/handle.h> +#include <core/oproxy.h> #include <core/ramht.h> #include <subdev/fb.h> #include <subdev/timer.h> #include <engine/dma.h> -void -nv50_disp_dmac_object_detach(struct nvkm_object *parent, int cookie) +struct nv50_disp_dmac_object { + struct nvkm_oproxy oproxy; + struct nv50_disp_root *root; + int hash; +}; + +static void +nv50_disp_dmac_child_del_(struct nvkm_oproxy *base) +{ + struct nv50_disp_dmac_object *object = + container_of(base, typeof(*object), oproxy); + nvkm_ramht_remove(object->root->ramht, object->hash); +} + +static const struct nvkm_oproxy_func +nv50_disp_dmac_child_func_ = { + .dtor[0] = nv50_disp_dmac_child_del_, +}; + +static int +nv50_disp_dmac_child_new_(struct nv50_disp_chan *base, + const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + struct nv50_disp_dmac *chan = nv50_disp_dmac(base); + struct nv50_disp_root *root = chan->base.root; + struct nvkm_device *device = root->disp->base.engine.subdev.device; + const struct nvkm_device_oclass *sclass = oclass->priv; + struct nv50_disp_dmac_object *object; + int ret; + + if (!(object = kzalloc(sizeof(*object), GFP_KERNEL))) + return -ENOMEM; + nvkm_oproxy_ctor(&nv50_disp_dmac_child_func_, oclass, &object->oproxy); + object->root = root; + *pobject = &object->oproxy.base; + + ret = sclass->ctor(device, oclass, data, size, &object->oproxy.object); + if (ret) + return ret; + + object->hash = chan->func->bind(chan, object->oproxy.object, + oclass->handle); + if (object->hash < 0) + return object->hash; + + return 0; +} + +static int +nv50_disp_dmac_child_get_(struct nv50_disp_chan *base, int index, + struct nvkm_oclass *sclass) +{ + struct nv50_disp_dmac *chan = nv50_disp_dmac(base); + struct nv50_disp *disp = chan->base.root->disp; + struct nvkm_device *device = disp->base.engine.subdev.device; + const struct nvkm_device_oclass *oclass = NULL; + + sclass->engine = nvkm_device_engine(device, NVDEV_ENGINE_DMAOBJ); + if (sclass->engine && sclass->engine->func->base.sclass) { + sclass->engine->func->base.sclass(sclass, index, &oclass); + if (oclass) { + sclass->priv = oclass; + return 0; + } + } + + return -EINVAL; +} + +static void +nv50_disp_dmac_fini_(struct nv50_disp_chan *base) +{ + struct nv50_disp_dmac *chan = nv50_disp_dmac(base); + chan->func->fini(chan); +} + +static int +nv50_disp_dmac_init_(struct nv50_disp_chan *base) +{ + struct nv50_disp_dmac *chan = nv50_disp_dmac(base); + return chan->func->init(chan); +} + +static void * +nv50_disp_dmac_dtor_(struct nv50_disp_chan *base) { - struct nv50_disp_root *root = (void *)parent->parent; - nvkm_ramht_remove(root->ramht, cookie); + return nv50_disp_dmac(base); } +static const struct nv50_disp_chan_func +nv50_disp_dmac_func_ = { + .dtor = nv50_disp_dmac_dtor_, + .init = nv50_disp_dmac_init_, + .fini = nv50_disp_dmac_fini_, + .child_get = nv50_disp_dmac_child_get_, + .child_new = nv50_disp_dmac_child_new_, +}; + int -nv50_disp_dmac_object_attach(struct nvkm_object *parent, - struct nvkm_object *object, u32 name) +nv50_disp_dmac_new_(const struct nv50_disp_dmac_func *func, + const struct nv50_disp_chan_mthd *mthd, + struct nv50_disp_root *root, int chid, int head, u64 push, + const struct nvkm_oclass *oclass, + struct nvkm_object **pobject) { - struct nv50_disp_root *root = (void *)parent->parent; - struct nv50_disp_chan *chan = (void *)parent; - u32 addr = nv_gpuobj(object)->node->offset; - u32 chid = chan->chid; - u32 data = (chid << 28) | (addr << 10) | chid; - return nvkm_ramht_insert(root->ramht, NULL, chid, 0, name, data); + struct nvkm_device *device = root->disp->base.engine.subdev.device; + struct nvkm_client *client = oclass->client; + struct nvkm_dmaobj *dmaobj; + struct nv50_disp_dmac *chan; + int ret; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; + chan->func = func; + + ret = nv50_disp_chan_ctor(&nv50_disp_dmac_func_, mthd, root, + chid, head, oclass, &chan->base); + if (ret) + return ret; + + dmaobj = nvkm_dma_search(device->dma, client, push); + if (!dmaobj) + return -ENOENT; + + if (dmaobj->limit - dmaobj->start != 0xfff) + return -EINVAL; + + switch (dmaobj->target) { + case NV_MEM_TARGET_VRAM: + chan->push = 0x00000001 | dmaobj->start >> 8; + break; + case NV_MEM_TARGET_PCI_NOSNOOP: + chan->push = 0x00000003 | dmaobj->start >> 8; + break; + default: + return -EINVAL; + } + + return 0; } int -nv50_disp_dmac_fini(struct nvkm_object *object, bool suspend) +nv50_disp_dmac_bind(struct nv50_disp_dmac *chan, + struct nvkm_object *object, u32 handle) { - struct nv50_disp *disp = (void *)object->engine; - struct nv50_disp_dmac *dmac = (void *)object; + return nvkm_ramht_insert(chan->base.root->ramht, object, + chan->base.chid, -10, handle, + chan->base.chid << 28 | + chan->base.chid); +} + +static void +nv50_disp_dmac_fini(struct nv50_disp_dmac *chan) +{ + struct nv50_disp *disp = chan->base.root->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int chid = dmac->base.chid; + int chid = chan->base.chid; /* deactivate channel */ nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00001010, 0x00001000); @@ -68,35 +202,25 @@ nv50_disp_dmac_fini(struct nvkm_object *object, bool suspend) ) < 0) { nvkm_error(subdev, "ch %d fini timeout, %08x\n", chid, nvkm_rd32(device, 0x610200 + (chid * 0x10))); - if (suspend) - return -EBUSY; } /* disable error reporting and completion notifications */ nvkm_mask(device, 0x610028, 0x00010001 << chid, 0x00000000 << chid); - - return nv50_disp_chan_fini(&dmac->base, suspend); } -int -nv50_disp_dmac_init(struct nvkm_object *object) +static int +nv50_disp_dmac_init(struct nv50_disp_dmac *chan) { - struct nv50_disp *disp = (void *)object->engine; - struct nv50_disp_dmac *dmac = (void *)object; + struct nv50_disp *disp = chan->base.root->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int chid = dmac->base.chid; - int ret; - - ret = nv50_disp_chan_init(&dmac->base); - if (ret) - return ret; + int chid = chan->base.chid; /* enable error reporting */ nvkm_mask(device, 0x610028, 0x00010000 << chid, 0x00010000 << chid); /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610204 + (chid * 0x0010), dmac->push); + nvkm_wr32(device, 0x610204 + (chid * 0x0010), chan->push); nvkm_wr32(device, 0x610208 + (chid * 0x0010), 0x00010000); nvkm_wr32(device, 0x61020c + (chid * 0x0010), chid); nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00000010, 0x00000010); @@ -116,48 +240,9 @@ nv50_disp_dmac_init(struct nvkm_object *object) return 0; } -void -nv50_disp_dmac_dtor(struct nvkm_object *object) -{ - struct nv50_disp_dmac *dmac = (void *)object; - nv50_disp_chan_destroy(&dmac->base); -} - -int -nv50_disp_dmac_create_(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, u64 pushbuf, int head, - int length, void **pobject) -{ - struct nvkm_device *device = parent->engine->subdev.device; - struct nvkm_client *client = nvkm_client(parent); - struct nvkm_dmaobj *dmaobj; - struct nv50_disp_dmac *dmac; - int ret; - - ret = nv50_disp_chan_create_(parent, engine, oclass, head, - length, pobject); - dmac = *pobject; - if (ret) - return ret; - - dmaobj = nvkm_dma_search(device->dma, client, pushbuf); - if (!dmaobj) - return -ENOENT; - - if (dmaobj->limit - dmaobj->start != 0xfff) - return -EINVAL; - - switch (dmaobj->target) { - case NV_MEM_TARGET_VRAM: - dmac->push = 0x00000001 | dmaobj->start >> 8; - break; - case NV_MEM_TARGET_PCI_NOSNOOP: - dmac->push = 0x00000003 | dmaobj->start >> 8; - break; - default: - return -EINVAL; - } - - return 0; -} +const struct nv50_disp_dmac_func +nv50_disp_dmac_func = { + .init = nv50_disp_dmac_init, + .fini = nv50_disp_dmac_fini, + .bind = nv50_disp_dmac_bind, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h index cfd09d275b13..c748ca23ab70 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h @@ -1,24 +1,91 @@ #ifndef __NV50_DISP_DMAC_H__ #define __NV50_DISP_DMAC_H__ +#define nv50_disp_dmac(p) container_of((p), struct nv50_disp_dmac, base) #include "channv50.h" struct nv50_disp_dmac { + const struct nv50_disp_dmac_func *func; struct nv50_disp_chan base; u32 push; }; -void nv50_disp_dmac_dtor(struct nvkm_object *); -int nv50_disp_dmac_object_attach(struct nvkm_object *, - struct nvkm_object *, u32); -void nv50_disp_dmac_object_detach(struct nvkm_object *, int); -int nv50_disp_dmac_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, u64, int, int, void **); -int nv50_disp_dmac_init(struct nvkm_object *); -int nv50_disp_dmac_fini(struct nvkm_object *, bool); - -int gf119_disp_dmac_object_attach(struct nvkm_object *, - struct nvkm_object *, u32); -void gf119_disp_dmac_object_detach(struct nvkm_object *, int); -int gf119_disp_dmac_init(struct nvkm_object *); -int gf119_disp_dmac_fini(struct nvkm_object *, bool); +struct nv50_disp_dmac_func { + int (*init)(struct nv50_disp_dmac *); + void (*fini)(struct nv50_disp_dmac *); + int (*bind)(struct nv50_disp_dmac *, struct nvkm_object *, u32 handle); +}; + +int nv50_disp_dmac_new_(const struct nv50_disp_dmac_func *, + const struct nv50_disp_chan_mthd *, + struct nv50_disp_root *, int chid, int head, u64 push, + const struct nvkm_oclass *, struct nvkm_object **); + +extern const struct nv50_disp_dmac_func nv50_disp_dmac_func; +int nv50_disp_dmac_bind(struct nv50_disp_dmac *, struct nvkm_object *, u32); +extern const struct nv50_disp_dmac_func nv50_disp_core_func; + +extern const struct nv50_disp_dmac_func gf119_disp_dmac_func; +int gf119_disp_dmac_bind(struct nv50_disp_dmac *, struct nvkm_object *, u32); +extern const struct nv50_disp_dmac_func gf119_disp_core_func; + +struct nv50_disp_dmac_oclass { + int (*ctor)(const struct nv50_disp_dmac_func *, + const struct nv50_disp_chan_mthd *, + struct nv50_disp_root *, int chid, + const struct nvkm_oclass *, void *data, u32 size, + struct nvkm_object **); + struct nvkm_sclass base; + const struct nv50_disp_dmac_func *func; + const struct nv50_disp_chan_mthd *mthd; + int chid; +}; + +int nv50_disp_core_new(const struct nv50_disp_dmac_func *, + const struct nv50_disp_chan_mthd *, + struct nv50_disp_root *, int chid, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **); +int nv50_disp_base_new(const struct nv50_disp_dmac_func *, + const struct nv50_disp_chan_mthd *, + struct nv50_disp_root *, int chid, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **); +int nv50_disp_ovly_new(const struct nv50_disp_dmac_func *, + const struct nv50_disp_chan_mthd *, + struct nv50_disp_root *, int chid, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **); + +extern const struct nv50_disp_dmac_oclass nv50_disp_core_oclass; +extern const struct nv50_disp_dmac_oclass nv50_disp_base_oclass; +extern const struct nv50_disp_dmac_oclass nv50_disp_ovly_oclass; + +extern const struct nv50_disp_dmac_oclass g84_disp_core_oclass; +extern const struct nv50_disp_dmac_oclass g84_disp_base_oclass; +extern const struct nv50_disp_dmac_oclass g84_disp_ovly_oclass; + +extern const struct nv50_disp_dmac_oclass g94_disp_core_oclass; + +extern const struct nv50_disp_dmac_oclass gt200_disp_core_oclass; +extern const struct nv50_disp_dmac_oclass gt200_disp_base_oclass; +extern const struct nv50_disp_dmac_oclass gt200_disp_ovly_oclass; + +extern const struct nv50_disp_dmac_oclass gt215_disp_core_oclass; +extern const struct nv50_disp_dmac_oclass gt215_disp_base_oclass; +extern const struct nv50_disp_dmac_oclass gt215_disp_ovly_oclass; + +extern const struct nv50_disp_dmac_oclass gf119_disp_core_oclass; +extern const struct nv50_disp_dmac_oclass gf119_disp_base_oclass; +extern const struct nv50_disp_dmac_oclass gf119_disp_ovly_oclass; + +extern const struct nv50_disp_dmac_oclass gk104_disp_core_oclass; +extern const struct nv50_disp_dmac_oclass gk104_disp_base_oclass; +extern const struct nv50_disp_dmac_oclass gk104_disp_ovly_oclass; + +extern const struct nv50_disp_dmac_oclass gk110_disp_core_oclass; +extern const struct nv50_disp_dmac_oclass gk110_disp_base_oclass; + +extern const struct nv50_disp_dmac_oclass gm107_disp_core_oclass; + +extern const struct nv50_disp_dmac_oclass gm204_disp_core_oclass; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c index 5995bcae2178..a223cef2b81f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c @@ -24,6 +24,11 @@ #include "nv50.h" #include "rootnv50.h" +static const struct nvkm_disp_func +g84_disp = { + .root = &g84_disp_root_oclass, +}; + static int g84_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, @@ -38,15 +43,14 @@ g84_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; + disp->base.func = &g84_disp; + ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &disp->uevent); if (ret) return ret; - nv_engine(disp)->sclass = g84_disp_root_oclass; - nv_engine(disp)->cclass = &nv50_disp_cclass; nv_subdev(disp)->intr = nv50_disp_intr; INIT_WORK(&disp->supervisor, nv50_disp_intr_supervisor); - disp->sclass = g84_disp_sclass; disp->head.nr = 2; disp->dac.nr = 3; disp->sor.nr = 2; @@ -74,9 +78,5 @@ g84_disp_oclass = &(struct nv50_disp_impl) { .base.outp.external.tmds = nv50_pior_output_new, .base.outp.external.dp = nv50_pior_dp_new, .base.vblank = &nv50_disp_vblank_func, - .mthd.core = &g84_disp_core_mthd_chan, - .mthd.base = &g84_disp_base_mthd_chan, - .mthd.ovly = &g84_disp_ovly_mthd_chan, - .mthd.prev = 0x000004, .head.scanoutpos = nv50_disp_root_scanoutpos, }.base.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c index 024709007635..639b02b2fc14 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c @@ -24,6 +24,11 @@ #include "nv50.h" #include "rootnv50.h" +static const struct nvkm_disp_func +g94_disp = { + .root = &g94_disp_root_oclass, +}; + static int g94_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, @@ -38,15 +43,14 @@ g94_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; + disp->base.func = &g94_disp; + ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &disp->uevent); if (ret) return ret; - nv_engine(disp)->sclass = g94_disp_root_oclass; - nv_engine(disp)->cclass = &nv50_disp_cclass; nv_subdev(disp)->intr = nv50_disp_intr; INIT_WORK(&disp->supervisor, nv50_disp_intr_supervisor); - disp->sclass = g94_disp_sclass; disp->head.nr = 2; disp->dac.nr = 3; disp->sor.nr = 4; @@ -75,9 +79,5 @@ g94_disp_oclass = &(struct nv50_disp_impl) { .base.outp.external.lvds = nv50_pior_output_new, .base.outp.external.dp = nv50_pior_dp_new, .base.vblank = &nv50_disp_vblank_func, - .mthd.core = &g94_disp_core_mthd_chan, - .mthd.base = &g84_disp_base_mthd_chan, - .mthd.ovly = &g84_disp_ovly_mthd_chan, - .mthd.prev = 0x000004, .head.scanoutpos = nv50_disp_root_scanoutpos, }.base.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c index 154185a98e01..c3d22e33e073 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c @@ -370,7 +370,6 @@ gf119_disp_intr_supervisor(struct work_struct *work) { struct nv50_disp *disp = container_of(work, struct nv50_disp, supervisor); - struct nv50_disp_impl *impl = (void *)nv_object(disp)->oclass; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; u32 mask[4]; @@ -383,7 +382,7 @@ gf119_disp_intr_supervisor(struct work_struct *work) } if (disp->super & 0x00000001) { - nv50_disp_mthd_chan(disp, NV_DBG_DEBUG, 0, impl->mthd.core); + nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG); for (head = 0; head < disp->head.nr; head++) { if (!(mask[head] & 0x00001000)) continue; @@ -428,7 +427,6 @@ gf119_disp_intr_supervisor(struct work_struct *work) static void gf119_disp_intr_error(struct nv50_disp *disp, int chid) { - const struct nv50_disp_impl *impl = (void *)nv_object(disp)->oclass; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; u32 mthd = nvkm_rd32(device, 0x6101f0 + (chid * 12)); @@ -438,31 +436,10 @@ gf119_disp_intr_error(struct nv50_disp *disp, int chid) nvkm_error(subdev, "chid %d mthd %04x data %08x %08x %08x\n", chid, (mthd & 0x0000ffc), data, mthd, unkn); - if (chid == 0) { + if (chid < ARRAY_SIZE(disp->chan)) { switch (mthd & 0xffc) { case 0x0080: - nv50_disp_mthd_chan(disp, NV_DBG_ERROR, chid - 0, - impl->mthd.core); - break; - default: - break; - } - } else - if (chid <= 4) { - switch (mthd & 0xffc) { - case 0x0080: - nv50_disp_mthd_chan(disp, NV_DBG_ERROR, chid - 1, - impl->mthd.base); - break; - default: - break; - } - } else - if (chid <= 8) { - switch (mthd & 0xffc) { - case 0x0080: - nv50_disp_mthd_chan(disp, NV_DBG_ERROR, chid - 5, - impl->mthd.ovly); + nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR); break; default: break; @@ -528,6 +505,11 @@ gf119_disp_intr(struct nvkm_subdev *subdev) } } +static const struct nvkm_disp_func +gf119_disp = { + .root = &gf119_disp_root_oclass, +}; + static int gf119_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, @@ -544,15 +526,14 @@ gf119_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; + disp->base.func = &gf119_disp; + ret = nvkm_event_init(&gf119_disp_chan_uevent, 1, 17, &disp->uevent); if (ret) return ret; - nv_engine(disp)->sclass = gf119_disp_root_oclass; - nv_engine(disp)->cclass = &nv50_disp_cclass; nv_subdev(disp)->intr = gf119_disp_intr; INIT_WORK(&disp->supervisor, gf119_disp_intr_supervisor); - disp->sclass = gf119_disp_sclass; disp->head.nr = heads; disp->dac.nr = 3; disp->sor.nr = 4; @@ -578,9 +559,5 @@ gf110_disp_oclass = &(struct nv50_disp_impl) { .base.outp.internal.lvds = nv50_sor_output_new, .base.outp.internal.dp = gf119_sor_dp_new, .base.vblank = &gf119_disp_vblank_func, - .mthd.core = &gf119_disp_core_mthd_chan, - .mthd.base = &gf119_disp_base_mthd_chan, - .mthd.ovly = &gf119_disp_ovly_mthd_chan, - .mthd.prev = -0x020000, .head.scanoutpos = gf119_disp_root_scanoutpos, }.base.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c index 404c75278dd8..e478c9f87fc6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c @@ -24,6 +24,11 @@ #include "nv50.h" #include "rootnv50.h" +static const struct nvkm_disp_func +gk104_disp = { + .root = &gk104_disp_root_oclass, +}; + static int gk104_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, @@ -40,15 +45,14 @@ gk104_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; + disp->base.func = &gk104_disp; + ret = nvkm_event_init(&gf119_disp_chan_uevent, 1, 17, &disp->uevent); if (ret) return ret; - nv_engine(disp)->sclass = gk104_disp_root_oclass; - nv_engine(disp)->cclass = &nv50_disp_cclass; nv_subdev(disp)->intr = gf119_disp_intr; INIT_WORK(&disp->supervisor, gf119_disp_intr_supervisor); - disp->sclass = gk104_disp_sclass; disp->head.nr = heads; disp->dac.nr = 3; disp->sor.nr = 4; @@ -74,9 +78,5 @@ gk104_disp_oclass = &(struct nv50_disp_impl) { .base.outp.internal.lvds = nv50_sor_output_new, .base.outp.internal.dp = gf119_sor_dp_new, .base.vblank = &gf119_disp_vblank_func, - .mthd.core = &gk104_disp_core_mthd_chan, - .mthd.base = &gf119_disp_base_mthd_chan, - .mthd.ovly = &gk104_disp_ovly_mthd_chan, - .mthd.prev = -0x020000, .head.scanoutpos = gf119_disp_root_scanoutpos, }.base.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c index 2bb3515060af..f4801f8e8c7e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c @@ -24,6 +24,11 @@ #include "nv50.h" #include "rootnv50.h" +static const struct nvkm_disp_func +gk110_disp = { + .root = &gk110_disp_root_oclass, +}; + static int gk110_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, @@ -40,15 +45,14 @@ gk110_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; + disp->base.func = &gk110_disp; + ret = nvkm_event_init(&gf119_disp_chan_uevent, 1, 17, &disp->uevent); if (ret) return ret; - nv_engine(disp)->sclass = gk110_disp_root_oclass; - nv_engine(disp)->cclass = &nv50_disp_cclass; nv_subdev(disp)->intr = gf119_disp_intr; INIT_WORK(&disp->supervisor, gf119_disp_intr_supervisor); - disp->sclass = gk110_disp_sclass; disp->head.nr = heads; disp->dac.nr = 3; disp->sor.nr = 4; @@ -74,9 +78,5 @@ gk110_disp_oclass = &(struct nv50_disp_impl) { .base.outp.internal.lvds = nv50_sor_output_new, .base.outp.internal.dp = gf119_sor_dp_new, .base.vblank = &gf119_disp_vblank_func, - .mthd.core = &gk104_disp_core_mthd_chan, - .mthd.base = &gf119_disp_base_mthd_chan, - .mthd.ovly = &gk104_disp_ovly_mthd_chan, - .mthd.prev = -0x020000, .head.scanoutpos = gf119_disp_root_scanoutpos, }.base.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c index fbc6b7c86189..a72f61078acf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c @@ -24,6 +24,11 @@ #include "nv50.h" #include "rootnv50.h" +static const struct nvkm_disp_func +gm107_disp = { + .root = &gm107_disp_root_oclass, +}; + static int gm107_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, @@ -40,15 +45,14 @@ gm107_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; + disp->base.func = &gm107_disp; + ret = nvkm_event_init(&gf119_disp_chan_uevent, 1, 17, &disp->uevent); if (ret) return ret; - nv_engine(disp)->sclass = gm107_disp_root_oclass; - nv_engine(disp)->cclass = &nv50_disp_cclass; nv_subdev(disp)->intr = gf119_disp_intr; INIT_WORK(&disp->supervisor, gf119_disp_intr_supervisor); - disp->sclass = gm107_disp_sclass; disp->head.nr = heads; disp->dac.nr = 3; disp->sor.nr = 4; @@ -74,9 +78,5 @@ gm107_disp_oclass = &(struct nv50_disp_impl) { .base.outp.internal.lvds = nv50_sor_output_new, .base.outp.internal.dp = gf119_sor_dp_new, .base.vblank = &gf119_disp_vblank_func, - .mthd.core = &gk104_disp_core_mthd_chan, - .mthd.base = &gf119_disp_base_mthd_chan, - .mthd.ovly = &gk104_disp_ovly_mthd_chan, - .mthd.prev = -0x020000, .head.scanoutpos = gf119_disp_root_scanoutpos, }.base.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm204.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm204.c index bf6ede5c424e..363e939376e9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm204.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm204.c @@ -24,6 +24,11 @@ #include "nv50.h" #include "rootnv50.h" +static const struct nvkm_disp_func +gm204_disp = { + .root = &gm204_disp_root_oclass, +}; + static int gm204_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, @@ -40,15 +45,14 @@ gm204_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; + disp->base.func = &gm204_disp; + ret = nvkm_event_init(&gf119_disp_chan_uevent, 1, 17, &disp->uevent); if (ret) return ret; - nv_engine(disp)->sclass = gm204_disp_root_oclass; - nv_engine(disp)->cclass = &nv50_disp_cclass; nv_subdev(disp)->intr = gf119_disp_intr; INIT_WORK(&disp->supervisor, gf119_disp_intr_supervisor); - disp->sclass = gm204_disp_sclass; disp->head.nr = heads; disp->dac.nr = 3; disp->sor.nr = 4; @@ -75,9 +79,5 @@ gm204_disp_oclass = &(struct nv50_disp_impl) { .base.outp.internal.lvds = nv50_sor_output_new, .base.outp.internal.dp = gm204_sor_dp_new, .base.vblank = &gf119_disp_vblank_func, - .mthd.core = &gk104_disp_core_mthd_chan, - .mthd.base = &gf119_disp_base_mthd_chan, - .mthd.ovly = &gk104_disp_ovly_mthd_chan, - .mthd.prev = -0x020000, .head.scanoutpos = gf119_disp_root_scanoutpos, }.base.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c index 811f092a2df0..c699c5f70b8d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c @@ -24,6 +24,11 @@ #include "nv50.h" #include "rootnv50.h" +static const struct nvkm_disp_func +gt200_disp = { + .root = >200_disp_root_oclass, +}; + static int gt200_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, @@ -38,15 +43,14 @@ gt200_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; + disp->base.func = >200_disp; + ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &disp->uevent); if (ret) return ret; - nv_engine(disp)->sclass = gt200_disp_root_oclass; - nv_engine(disp)->cclass = &nv50_disp_cclass; nv_subdev(disp)->intr = nv50_disp_intr; INIT_WORK(&disp->supervisor, nv50_disp_intr_supervisor); - disp->sclass = gt200_disp_sclass; disp->head.nr = 2; disp->dac.nr = 3; disp->sor.nr = 2; @@ -74,9 +78,5 @@ gt200_disp_oclass = &(struct nv50_disp_impl) { .base.outp.external.tmds = nv50_pior_output_new, .base.outp.external.dp = nv50_pior_dp_new, .base.vblank = &nv50_disp_vblank_func, - .mthd.core = &g84_disp_core_mthd_chan, - .mthd.base = &g84_disp_base_mthd_chan, - .mthd.ovly = >200_disp_ovly_mthd_chan, - .mthd.prev = 0x000004, .head.scanoutpos = nv50_disp_root_scanoutpos, }.base.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c index fdde7ce18ce1..ddf65902fd23 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c @@ -24,6 +24,11 @@ #include "nv50.h" #include "rootnv50.h" +static const struct nvkm_disp_func +gt215_disp_func = { + .root = >215_disp_root_oclass, +}; + static int gt215_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, @@ -38,15 +43,14 @@ gt215_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; + disp->base.func = >215_disp_func; + ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &disp->uevent); if (ret) return ret; - nv_engine(disp)->sclass = gt215_disp_root_oclass; - nv_engine(disp)->cclass = &nv50_disp_cclass; nv_subdev(disp)->intr = nv50_disp_intr; INIT_WORK(&disp->supervisor, nv50_disp_intr_supervisor); - disp->sclass = gt215_disp_sclass; disp->head.nr = 2; disp->dac.nr = 3; disp->sor.nr = 4; @@ -76,9 +80,5 @@ gt215_disp_oclass = &(struct nv50_disp_impl) { .base.outp.external.lvds = nv50_pior_output_new, .base.outp.external.dp = nv50_pior_dp_new, .base.vblank = &nv50_disp_vblank_func, - .mthd.core = &g94_disp_core_mthd_chan, - .mthd.base = &g84_disp_base_mthd_chan, - .mthd.ovly = &g84_disp_ovly_mthd_chan, - .mthd.prev = 0x000004, .head.scanoutpos = nv50_disp_root_scanoutpos, }.base.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c index ceac0c0bbb4f..33922f3a176a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c @@ -74,6 +74,11 @@ nv04_disp_intr(struct nvkm_subdev *subdev) } } +static const struct nvkm_disp_func +nv04_disp = { + .root = &nv04_disp_root_oclass, +}; + static int nv04_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, @@ -88,7 +93,8 @@ nv04_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; - nv_engine(disp)->sclass = nv04_disp_sclass; + disp->func = &nv04_disp; + nv_subdev(disp)->intr = nv04_disp_intr; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c index 240a5438c7ac..9bc4273947c3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c @@ -33,47 +33,6 @@ #include <subdev/bios/pll.h> #include <subdev/devinit.h> -static int -nv50_disp_data_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv50_disp *disp = (void *)engine; - struct nvkm_gpuobj *gpuobj; - int ret; - - /* no context needed for channel objects... */ - if (parent->parent != &nvkm_client(parent)->object) { - atomic_inc(&parent->refcount); - *pobject = parent; - return 1; - } - - /* allocate display hardware to client */ - ret = nvkm_gpuobj_create(parent, engine, oclass, 0, NULL, - 0x10000, 0x10000, NVOBJ_FLAG_HEAP, - &gpuobj); - *pobject = nv_object(gpuobj); - mutex_lock(&nv_subdev(disp)->mutex); - if (!list_empty(&nv_engine(disp)->contexts)) - ret = -EBUSY; - mutex_unlock(&nv_subdev(disp)->mutex); - return ret; -} - -struct nvkm_oclass -nv50_disp_cclass = { - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_disp_data_ctor, - .dtor = _nvkm_gpuobj_dtor, - .init = _nvkm_gpuobj_init, - .fini = _nvkm_gpuobj_fini, - .rd32 = _nvkm_gpuobj_rd32, - .wr32 = _nvkm_gpuobj_wr32, - }, -}; - static void nv50_disp_vblank_fini(struct nvkm_event *event, int type, int head) { @@ -115,7 +74,6 @@ nv50_disp_intr_error_code[] = { static void nv50_disp_intr_error(struct nv50_disp *disp, int chid) { - struct nv50_disp_impl *impl = (void *)nv_object(disp)->oclass; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; u32 data = nvkm_rd32(device, 0x610084 + (chid * 0x08)); @@ -133,31 +91,10 @@ nv50_disp_intr_error(struct nv50_disp *disp, int chid) type, et ? et->name : "", code, ec ? ec->name : "", chid, mthd, data); - if (chid == 0) { - switch (mthd) { - case 0x0080: - nv50_disp_mthd_chan(disp, NV_DBG_ERROR, chid - 0, - impl->mthd.core); - break; - default: - break; - } - } else - if (chid <= 2) { - switch (mthd) { - case 0x0080: - nv50_disp_mthd_chan(disp, NV_DBG_ERROR, chid - 1, - impl->mthd.base); - break; - default: - break; - } - } else - if (chid <= 4) { + if (chid < ARRAY_SIZE(disp->chan)) { switch (mthd) { case 0x0080: - nv50_disp_mthd_chan(disp, NV_DBG_ERROR, chid - 3, - impl->mthd.ovly); + nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR); break; default: break; @@ -673,7 +610,6 @@ nv50_disp_intr_supervisor(struct work_struct *work) { struct nv50_disp *disp = container_of(work, struct nv50_disp, supervisor); - struct nv50_disp_impl *impl = (void *)nv_object(disp)->oclass; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; u32 super = nvkm_rd32(device, 0x610030); @@ -682,7 +618,7 @@ nv50_disp_intr_supervisor(struct work_struct *work) nvkm_debug(subdev, "supervisor %08x %08x\n", disp->super, super); if (disp->super & 0x00000010) { - nv50_disp_mthd_chan(disp, NV_DBG_DEBUG, 0, impl->mthd.core); + nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG); for (head = 0; head < disp->head.nr; head++) { if (!(super & (0x00000020 << head))) continue; @@ -756,6 +692,11 @@ nv50_disp_intr(struct nvkm_subdev *subdev) } } +static const struct nvkm_disp_func +nv50_disp = { + .root = &nv50_disp_root_oclass, +}; + static int nv50_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, @@ -770,15 +711,14 @@ nv50_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; + disp->base.func = &nv50_disp; + ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &disp->uevent); if (ret) return ret; - nv_engine(disp)->sclass = nv50_disp_root_oclass; - nv_engine(disp)->cclass = &nv50_disp_cclass; nv_subdev(disp)->intr = nv50_disp_intr; INIT_WORK(&disp->supervisor, nv50_disp_intr_supervisor); - disp->sclass = nv50_disp_sclass; disp->head.nr = 2; disp->dac.nr = 3; disp->sor.nr = 2; @@ -805,9 +745,5 @@ nv50_disp_oclass = &(struct nv50_disp_impl) { .base.outp.external.tmds = nv50_pior_output_new, .base.outp.external.dp = nv50_pior_dp_new, .base.vblank = &nv50_disp_vblank_func, - .mthd.core = &nv50_disp_core_mthd_chan, - .mthd.base = &nv50_disp_base_mthd_chan, - .mthd.ovly = &nv50_disp_ovly_mthd_chan, - .mthd.prev = 0x000004, .head.scanoutpos = nv50_disp_root_scanoutpos, }.base.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h index e42e66e1c1f3..13766b24706d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h @@ -1,5 +1,6 @@ #ifndef __NV50_DISP_H__ #define __NV50_DISP_H__ +#define nv50_disp(p) container_of((p), struct nv50_disp, base) #include "priv.h" struct nvkm_output; struct nvkm_output_dp; @@ -11,7 +12,6 @@ struct nvkm_output_dp; struct nv50_disp { struct nvkm_disp base; - struct nvkm_oclass *sclass; struct work_struct supervisor; u32 super; @@ -39,23 +39,18 @@ struct nv50_disp { int (*power)(NV50_DISP_MTHD_V1); u8 type[3]; } pior; + + struct nv50_disp_chan *chan[17]; }; struct nv50_disp_impl { struct nvkm_disp_impl base; struct { - const struct nv50_disp_mthd_chan *core; - const struct nv50_disp_mthd_chan *base; - const struct nv50_disp_mthd_chan *ovly; - int prev; - } mthd; - struct { int (*scanoutpos)(NV50_DISP_MTHD_V0); } head; }; int nv50_disp_root_scanoutpos(NV50_DISP_MTHD_V0); -int nv50_disp_root_mthd(struct nvkm_object *, u32, void *, u32); int gf119_disp_root_scanoutpos(NV50_DISP_MTHD_V0); @@ -73,59 +68,11 @@ int gk104_hdmi_ctrl(NV50_DISP_MTHD_V1); int nv50_sor_power(NV50_DISP_MTHD_V1); int nv50_pior_power(NV50_DISP_MTHD_V1); -extern struct nv50_disp_chan_impl nv50_disp_core_ofuncs; -int nv50_disp_core_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -extern struct nv50_disp_chan_impl nv50_disp_base_ofuncs; -int nv50_disp_base_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -extern struct nv50_disp_chan_impl nv50_disp_ovly_ofuncs; -int nv50_disp_ovly_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -extern struct nv50_disp_chan_impl nv50_disp_oimm_ofuncs; -int nv50_disp_oimm_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -extern struct nv50_disp_chan_impl nv50_disp_curs_ofuncs; -int nv50_disp_curs_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -extern struct nvkm_ofuncs nv50_disp_root_ofuncs; -int nv50_disp_root_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void nv50_disp_root_dtor(struct nvkm_object *); -extern struct nvkm_oclass nv50_disp_cclass; void nv50_disp_intr_supervisor(struct work_struct *); void nv50_disp_intr(struct nvkm_subdev *); extern const struct nvkm_event_func nv50_disp_vblank_func; -extern struct nv50_disp_chan_impl gf119_disp_core_ofuncs; -extern struct nv50_disp_chan_impl gf119_disp_base_ofuncs; -extern struct nv50_disp_chan_impl gf119_disp_ovly_ofuncs; -extern struct nv50_disp_chan_impl gf119_disp_oimm_ofuncs; -extern struct nv50_disp_chan_impl gf119_disp_curs_ofuncs; -extern struct nvkm_ofuncs gf119_disp_root_ofuncs; -extern struct nvkm_oclass gf119_disp_cclass; void gf119_disp_intr_supervisor(struct work_struct *); void gf119_disp_intr(struct nvkm_subdev *); extern const struct nvkm_event_func gf119_disp_vblank_func; - -extern struct nvkm_output_dp_impl nv50_pior_dp_impl; -extern struct nvkm_oclass *nv50_disp_outp_sclass[]; - -extern struct nvkm_output_dp_impl g94_sor_dp_impl; -u32 g94_sor_dp_lane_map(struct nvkm_device *, u8 lane); -int g94_sor_dp_lnk_pwr(struct nvkm_output_dp *, int); -extern struct nvkm_oclass *g94_disp_outp_sclass[]; - -extern struct nvkm_output_dp_impl gf119_sor_dp_impl; -int gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *, int, int, bool); -extern struct nvkm_oclass *gf119_disp_outp_sclass[]; - -void gm204_sor_magic(struct nvkm_output *outp); -extern struct nvkm_output_dp_impl gm204_sor_dp_impl; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c new file mode 100644 index 000000000000..54a4ae8d66c6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c @@ -0,0 +1,37 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ +#include "channv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_pioc_oclass +g84_disp_oimm_oclass = { + .base.oclass = G82_DISP_OVERLAY, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_oimm_new, + .func = &nv50_disp_pioc_func, + .chid = 5, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c index fa528051faa5..c658db54afc5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c @@ -22,16 +22,16 @@ * Authors: Ben Skeggs */ #include "channv50.h" +#include "rootnv50.h" -struct nv50_disp_chan_impl -gf119_disp_oimm_ofuncs = { - .base.ctor = nv50_disp_oimm_ctor, - .base.dtor = nv50_disp_pioc_dtor, - .base.init = gf119_disp_pioc_init, - .base.fini = gf119_disp_pioc_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, +#include <nvif/class.h> + +const struct nv50_disp_pioc_oclass +gf119_disp_oimm_oclass = { + .base.oclass = GF110_DISP_OVERLAY, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_oimm_new, + .func = &gf119_disp_pioc_func, .chid = 9, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c new file mode 100644 index 000000000000..b1fde8c125d6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c @@ -0,0 +1,37 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ +#include "channv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_pioc_oclass +gk104_disp_oimm_oclass = { + .base.oclass = GK104_DISP_OVERLAY, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_oimm_new, + .func = &gf119_disp_pioc_func, + .chid = 9, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c new file mode 100644 index 000000000000..f4e7eb3d1177 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c @@ -0,0 +1,37 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ +#include "channv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_pioc_oclass +gt215_disp_oimm_oclass = { + .base.oclass = GT214_DISP_OVERLAY, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_oimm_new, + .func = &nv50_disp_pioc_func, + .chid = 5, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c index 2128b01ae572..6f31c81fdb01 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "channv50.h" +#include "rootnv50.h" #include <core/client.h> @@ -29,17 +30,18 @@ #include <nvif/unpack.h> int -nv50_disp_oimm_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_disp_oimm_new(const struct nv50_disp_chan_func *func, + const struct nv50_disp_chan_mthd *mthd, + struct nv50_disp_root *root, int chid, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) { union { struct nv50_disp_overlay_v0 v0; } *args = data; - struct nv50_disp *disp = (void *)engine; - struct nv50_disp_pioc *pioc; - int ret; + struct nvkm_object *parent = oclass->parent; + struct nv50_disp *disp = root->disp; + int head, ret; nvif_ioctl(parent, "create disp overlay size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { @@ -47,27 +49,20 @@ nv50_disp_oimm_ctor(struct nvkm_object *parent, args->v0.version, args->v0.head); if (args->v0.head > disp->head.nr) return -EINVAL; + head = args->v0.head; } else return ret; - ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head, - sizeof(*pioc), (void **)&pioc); - *pobject = nv_object(pioc); - if (ret) - return ret; - - return 0; + return nv50_disp_chan_new_(func, mthd, root, chid + head, + head, oclass, pobject); } -struct nv50_disp_chan_impl -nv50_disp_oimm_ofuncs = { - .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.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, +const struct nv50_disp_pioc_oclass +nv50_disp_oimm_oclass = { + .base.oclass = NV50_DISP_OVERLAY, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_oimm_new, + .func = &nv50_disp_pioc_func, .chid = 5, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h index 83d9d3f129f5..2590fec67ca9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h @@ -27,18 +27,22 @@ struct nvkm_output_func { void nvkm_output_ctor(const struct nvkm_output_func *, struct nvkm_disp *, int index, struct dcb_output *, struct nvkm_output *); -int nvkm_output_new_(const struct nvkm_output_func *, struct nvkm_disp *, - int index, struct dcb_output *, struct nvkm_output **); +int nvkm_output_new_(const struct nvkm_output_func *, struct nvkm_disp *, + int index, struct dcb_output *, struct nvkm_output **); void nvkm_output_del(struct nvkm_output **); void nvkm_output_init(struct nvkm_output *); void nvkm_output_fini(struct nvkm_output *); -int nv50_dac_output_new(struct nvkm_disp *, int, struct dcb_output *, +int nv50_dac_output_new(struct nvkm_disp *, int, struct dcb_output *, + struct nvkm_output **); +int nv50_sor_output_new(struct nvkm_disp *, int, struct dcb_output *, + struct nvkm_output **); +int nv50_pior_output_new(struct nvkm_disp *, int, struct dcb_output *, struct nvkm_output **); -int nv50_sor_output_new(struct nvkm_disp *, int, struct dcb_output *, - struct nvkm_output **); -int nv50_pior_output_new(struct nvkm_disp *, int, struct dcb_output *, - struct nvkm_output **); + +u32 g94_sor_dp_lane_map(struct nvkm_device *, u8 lane); + +void gm204_sor_magic(struct nvkm_output *outp); #define OUTP_MSG(o,l,f,a...) do { \ struct nvkm_output *_outp = (o); \ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h index 18ddf481c346..731136d660b7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h @@ -52,14 +52,16 @@ int nvkm_output_dp_new_(const struct nvkm_output_dp_func *, struct nvkm_disp *, int index, struct dcb_output *, struct nvkm_output **); -int nv50_pior_dp_new(struct nvkm_disp *, int, struct dcb_output *, - struct nvkm_output **); +int nv50_pior_dp_new(struct nvkm_disp *, int, struct dcb_output *, + struct nvkm_output **); -int g94_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *, - struct nvkm_output **); +int g94_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *, + struct nvkm_output **); +int g94_sor_dp_lnk_pwr(struct nvkm_output_dp *, int); -int gf119_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *, - struct nvkm_output **); +int gf119_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *, + struct nvkm_output **); +int gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *, int, int, bool); int gm204_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *, struct nvkm_output **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c index 149e7c4c75fa..db6234eebc61 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c @@ -22,6 +22,9 @@ * Authors: Ben Skeggs */ #include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> static const struct nv50_disp_mthd_list g84_disp_ovly_mthd_base = { @@ -51,12 +54,24 @@ g84_disp_ovly_mthd_base = { } }; -const struct nv50_disp_mthd_chan -g84_disp_ovly_mthd_chan = { +const struct nv50_disp_chan_mthd +g84_disp_ovly_chan_mthd = { .name = "Overlay", .addr = 0x000540, + .prev = 0x000004, .data = { { "Global", 1, &g84_disp_ovly_mthd_base }, {} } }; + +const struct nv50_disp_dmac_oclass +g84_disp_ovly_oclass = { + .base.oclass = G82_DISP_OVERLAY_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_ovly_new, + .func = &nv50_disp_dmac_func, + .mthd = &g84_disp_ovly_chan_mthd, + .chid = 3, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c index c44c927460bc..5985879abd23 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c @@ -22,6 +22,9 @@ * Authors: Ben Skeggs */ #include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> static const struct nv50_disp_mthd_list gf119_disp_ovly_mthd_base = { @@ -75,27 +78,24 @@ gf119_disp_ovly_mthd_base = { } }; -const struct nv50_disp_mthd_chan -gf119_disp_ovly_mthd_chan = { +static const struct nv50_disp_chan_mthd +gf119_disp_ovly_chan_mthd = { .name = "Overlay", .addr = 0x001000, + .prev = -0x020000, .data = { { "Global", 1, &gf119_disp_ovly_mthd_base }, {} } }; -struct nv50_disp_chan_impl -gf119_disp_ovly_ofuncs = { - .base.ctor = nv50_disp_ovly_ctor, - .base.dtor = nv50_disp_dmac_dtor, - .base.init = gf119_disp_dmac_init, - .base.fini = gf119_disp_dmac_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, +const struct nv50_disp_dmac_oclass +gf119_disp_ovly_oclass = { + .base.oclass = GF110_DISP_OVERLAY_CONTROL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_ovly_new, + .func = &gf119_disp_dmac_func, + .mthd = &gf119_disp_ovly_chan_mthd, .chid = 5, - .attach = gf119_disp_dmac_object_attach, - .detach = gf119_disp_dmac_object_detach, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c index 7b83d70b244a..2e2dc0641ef2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c @@ -22,6 +22,9 @@ * Authors: Ben Skeggs */ #include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> static const struct nv50_disp_mthd_list gk104_disp_ovly_mthd_base = { @@ -77,12 +80,24 @@ gk104_disp_ovly_mthd_base = { } }; -const struct nv50_disp_mthd_chan -gk104_disp_ovly_mthd_chan = { +static const struct nv50_disp_chan_mthd +gk104_disp_ovly_chan_mthd = { .name = "Overlay", .addr = 0x001000, + .prev = -0x020000, .data = { { "Global", 1, &gk104_disp_ovly_mthd_base }, {} } }; + +const struct nv50_disp_dmac_oclass +gk104_disp_ovly_oclass = { + .base.oclass = GK104_DISP_OVERLAY_CONTROL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_ovly_new, + .func = &gf119_disp_dmac_func, + .mthd = &gk104_disp_ovly_chan_mthd, + .chid = 5, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c index 8299b5e02352..f858053db83d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c @@ -22,6 +22,9 @@ * Authors: Ben Skeggs */ #include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> static const struct nv50_disp_mthd_list gt200_disp_ovly_mthd_base = { @@ -54,12 +57,24 @@ gt200_disp_ovly_mthd_base = { } }; -const struct nv50_disp_mthd_chan -gt200_disp_ovly_mthd_chan = { +static const struct nv50_disp_chan_mthd +gt200_disp_ovly_chan_mthd = { .name = "Overlay", .addr = 0x000540, + .prev = 0x000004, .data = { { "Global", 1, >200_disp_ovly_mthd_base }, {} } }; + +const struct nv50_disp_dmac_oclass +gt200_disp_ovly_oclass = { + .base.oclass = GT200_DISP_OVERLAY_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_ovly_new, + .func = &nv50_disp_dmac_func, + .mthd = >200_disp_ovly_chan_mthd, + .chid = 3, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt215.c new file mode 100644 index 000000000000..c947e1e16a37 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt215.c @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include <nvif/class.h> + +const struct nv50_disp_dmac_oclass +gt215_disp_ovly_oclass = { + .base.oclass = GT214_DISP_OVERLAY_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_ovly_new, + .func = &nv50_disp_dmac_func, + .mthd = &g84_disp_ovly_chan_mthd, + .chid = 3, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c index 840e2b0a90a4..110662c1fe04 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c @@ -22,13 +22,45 @@ * Authors: Ben Skeggs */ #include "dmacnv50.h" +#include "rootnv50.h" #include <core/client.h> #include <nvif/class.h> #include <nvif/unpack.h> -const struct nv50_disp_mthd_list +int +nv50_disp_ovly_new(const struct nv50_disp_dmac_func *func, + const struct nv50_disp_chan_mthd *mthd, + struct nv50_disp_root *root, int chid, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + union { + struct nv50_disp_overlay_channel_dma_v0 v0; + } *args = data; + struct nvkm_object *parent = oclass->parent; + struct nv50_disp *disp = root->disp; + int head, ret; + u64 push; + + nvif_ioctl(parent, "create disp overlay channel dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create disp overlay channel dma vers %d " + "pushbuf %016llx head %d\n", + args->v0.version, args->v0.pushbuf, args->v0.head); + if (args->v0.head > disp->head.nr) + return -EINVAL; + push = args->v0.pushbuf; + head = args->v0.head; + } else + return ret; + + return nv50_disp_dmac_new_(func, mthd, root, chid + head, + head, push, oclass, pobject); +} + +static const struct nv50_disp_mthd_list nv50_disp_ovly_mthd_base = { .mthd = 0x0000, .addr = 0x000000, @@ -56,60 +88,24 @@ nv50_disp_ovly_mthd_base = { } }; -const struct nv50_disp_mthd_chan -nv50_disp_ovly_mthd_chan = { +static const struct nv50_disp_chan_mthd +nv50_disp_ovly_chan_mthd = { .name = "Overlay", .addr = 0x000540, + .prev = 0x000004, .data = { { "Global", 1, &nv50_disp_ovly_mthd_base }, {} } }; -int -nv50_disp_ovly_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_overlay_channel_dma_v0 v0; - } *args = data; - struct nv50_disp *disp = (void *)engine; - struct nv50_disp_dmac *dmac; - int ret; - - nvif_ioctl(parent, "create disp overlay channel dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nvif_ioctl(parent, "create disp overlay channel dma vers %d " - "pushbuf %016llx head %d\n", - args->v0.version, args->v0.pushbuf, args->v0.head); - if (args->v0.head > disp->head.nr) - return -EINVAL; - } else - return ret; - - ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf, - args->v0.head, sizeof(*dmac), - (void **)&dmac); - *pobject = nv_object(dmac); - if (ret) - return ret; - - return 0; -} - -struct nv50_disp_chan_impl -nv50_disp_ovly_ofuncs = { - .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.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, +const struct nv50_disp_dmac_oclass +nv50_disp_ovly_oclass = { + .base.oclass = NV50_DISP_OVERLAY_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_disp_ovly_new, + .func = &nv50_disp_dmac_func, + .mthd = &nv50_disp_ovly_chan_mthd, .chid = 3, - .attach = nv50_disp_dmac_object_attach, - .detach = nv50_disp_dmac_object_detach, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c index 08aeb8e4e6dc..a625a9876e34 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c @@ -22,17 +22,17 @@ * Authors: Ben Skeggs */ #include "channv50.h" +#include "rootnv50.h" #include <subdev/timer.h> -int -gf119_disp_pioc_fini(struct nvkm_object *object, bool suspend) +static void +gf119_disp_pioc_fini(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = (void *)object->engine; - struct nv50_disp_pioc *pioc = (void *)object; + struct nv50_disp *disp = chan->root->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int chid = pioc->base.chid; + int chid = chan->chid; nvkm_mask(device, 0x610490 + (chid * 0x10), 0x00000001, 0x00000000); if (nvkm_msec(device, 2000, @@ -41,30 +41,20 @@ gf119_disp_pioc_fini(struct nvkm_object *object, bool suspend) ) < 0) { nvkm_error(subdev, "ch %d fini: %08x\n", chid, nvkm_rd32(device, 0x610490 + (chid * 0x10))); - if (suspend) - return -EBUSY; } /* disable error reporting and completion notification */ nvkm_mask(device, 0x610090, 0x00000001 << chid, 0x00000000); nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000000); - - return nv50_disp_chan_fini(&pioc->base, suspend); } -int -gf119_disp_pioc_init(struct nvkm_object *object) +static int +gf119_disp_pioc_init(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = (void *)object->engine; - struct nv50_disp_pioc *pioc = (void *)object; + struct nv50_disp *disp = chan->root->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int chid = pioc->base.chid; - int ret; - - ret = nv50_disp_chan_init(&pioc->base); - if (ret) - return ret; + int chid = chan->chid; /* enable error reporting */ nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); @@ -83,3 +73,9 @@ gf119_disp_pioc_init(struct nvkm_object *object) return 0; } + +const struct nv50_disp_chan_func +gf119_disp_pioc_func = { + .init = gf119_disp_pioc_init, + .fini = gf119_disp_pioc_fini, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c index 13e4711ec0c7..9d2618dacf20 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c @@ -22,17 +22,17 @@ * Authors: Ben Skeggs */ #include "channv50.h" +#include "rootnv50.h" #include <subdev/timer.h> -int -nv50_disp_pioc_fini(struct nvkm_object *object, bool suspend) +static void +nv50_disp_pioc_fini(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = (void *)object->engine; - struct nv50_disp_pioc *pioc = (void *)object; + struct nv50_disp *disp = chan->root->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int chid = pioc->base.chid; + int chid = chan->chid; nvkm_mask(device, 0x610200 + (chid * 0x10), 0x00000001, 0x00000000); if (nvkm_msec(device, 2000, @@ -41,26 +41,16 @@ nv50_disp_pioc_fini(struct nvkm_object *object, bool suspend) ) < 0) { nvkm_error(subdev, "ch %d timeout: %08x\n", chid, nvkm_rd32(device, 0x610200 + (chid * 0x10))); - if (suspend) - return -EBUSY; } - - return nv50_disp_chan_fini(&pioc->base, suspend); } -int -nv50_disp_pioc_init(struct nvkm_object *object) +static int +nv50_disp_pioc_init(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = (void *)object->engine; - struct nv50_disp_pioc *pioc = (void *)object; + struct nv50_disp *disp = chan->root->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int chid = pioc->base.chid; - int ret; - - ret = nv50_disp_chan_init(&pioc->base); - if (ret) - return ret; + int chid = chan->chid; nvkm_wr32(device, 0x610200 + (chid * 0x10), 0x00002000); if (nvkm_msec(device, 2000, @@ -86,19 +76,8 @@ nv50_disp_pioc_init(struct nvkm_object *object) return 0; } -void -nv50_disp_pioc_dtor(struct nvkm_object *object) -{ - struct nv50_disp_pioc *pioc = (void *)object; - nv50_disp_chan_destroy(&pioc->base); -} - -int -nv50_disp_pioc_create_(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, int head, - int length, void **pobject) -{ - return nv50_disp_chan_create_(parent, engine, oclass, head, - length, pobject); -} +const struct nv50_disp_chan_func +nv50_disp_pioc_func = { + .init = nv50_disp_pioc_init, + .fini = nv50_disp_pioc_fini, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h index 603526ceaa28..6cd6086ce78b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h @@ -57,5 +57,11 @@ int nvkm_disp_vblank_ctor(struct nvkm_object *, void *data, u32 size, void nvkm_disp_vblank(struct nvkm_disp *, int head); int nvkm_disp_ntfy(struct nvkm_object *, u32, struct nvkm_event **); -extern struct nvkm_oclass nv04_disp_sclass[]; +extern const struct nvkm_disp_oclass nv04_disp_root_oclass; + +struct nvkm_disp_oclass { + int (*ctor)(struct nvkm_disp *, const struct nvkm_oclass *, + void *data, u32 size, struct nvkm_object **); + struct nvkm_sclass base; +}; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c index 128b2d797e6f..721e4f74d1fc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c @@ -26,18 +26,33 @@ #include <nvif/class.h> -struct nvkm_oclass -g84_disp_sclass[] = { - { G82_DISP_CORE_CHANNEL_DMA, &nv50_disp_core_ofuncs.base }, - { G82_DISP_BASE_CHANNEL_DMA, &nv50_disp_base_ofuncs.base }, - { G82_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base }, - { G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base }, - { G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base }, - {} +static const struct nv50_disp_root_func +g84_disp_root = { + .init = nv50_disp_root_init, + .fini = nv50_disp_root_fini, + .dmac = { + &g84_disp_core_oclass, + &g84_disp_base_oclass, + &g84_disp_ovly_oclass, + }, + .pioc = { + &g84_disp_oimm_oclass, + &g84_disp_curs_oclass, + }, }; -struct nvkm_oclass -g84_disp_root_oclass[] = { - { G82_DISP, &nv50_disp_root_ofuncs }, - {} +static int +g84_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_(&g84_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +g84_disp_root_oclass = { + .base.oclass = G82_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = g84_disp_root_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c index 9b1ef885a262..9493f6edf62b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c @@ -26,18 +26,33 @@ #include <nvif/class.h> -struct nvkm_oclass -g94_disp_sclass[] = { - { GT206_DISP_CORE_CHANNEL_DMA, &nv50_disp_core_ofuncs.base }, - { GT200_DISP_BASE_CHANNEL_DMA, &nv50_disp_base_ofuncs.base }, - { GT200_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base }, - { G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base }, - { G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base }, - {} +static const struct nv50_disp_root_func +g94_disp_root = { + .init = nv50_disp_root_init, + .fini = nv50_disp_root_fini, + .dmac = { + &g94_disp_core_oclass, + >200_disp_base_oclass, + >200_disp_ovly_oclass, + }, + .pioc = { + &g84_disp_oimm_oclass, + &g84_disp_curs_oclass, + }, }; -struct nvkm_oclass -g94_disp_root_oclass[] = { - { GT206_DISP, &nv50_disp_root_ofuncs }, - {} +static int +g94_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_(&g94_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +g94_disp_root_oclass = { + .base.oclass = GT206_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = g94_disp_root_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c index ae55cb21eb33..5868c446b846 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c @@ -65,18 +65,21 @@ gf119_disp_root_scanoutpos(NV50_DISP_MTHD_V0) return 0; } -static int -gf119_disp_root_init(struct nvkm_object *object) +void +gf119_disp_root_fini(struct nv50_disp_root *root) { - struct nv50_disp *disp = (void *)object->engine; - struct nv50_disp_root *root = (void *)object; + struct nvkm_device *device = root->disp->base.engine.subdev.device; + /* disable all interrupts */ + nvkm_wr32(device, 0x6100b0, 0x00000000); +} + +int +gf119_disp_root_init(struct nv50_disp_root *root) +{ + 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 @@ -117,7 +120,7 @@ gf119_disp_root_init(struct nvkm_object *object) } /* point at display engine memory area (hash table, objects) */ - nvkm_wr32(device, 0x610010, (nv_gpuobj(object->parent)->addr >> 8) | 9); + nvkm_wr32(device, 0x610010, (root->instmem->addr >> 8) | 9); /* enable supervisor interrupts, disable everything else */ nvkm_wr32(device, 0x610090, 0x00000000); @@ -136,41 +139,33 @@ gf119_disp_root_init(struct nvkm_object *object) return 0; } -static int -gf119_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, 0x6100b0, 0x00000000); - - return nvkm_parent_fini(&root->base, suspend); -} - -struct nvkm_ofuncs -gf119_disp_root_ofuncs = { - .ctor = nv50_disp_root_ctor, - .dtor = nv50_disp_root_dtor, +static const struct nv50_disp_root_func +gf119_disp_root = { .init = gf119_disp_root_init, .fini = gf119_disp_root_fini, - .mthd = nv50_disp_root_mthd, - .ntfy = nvkm_disp_ntfy, + .dmac = { + &gf119_disp_core_oclass, + &gf119_disp_base_oclass, + &gf119_disp_ovly_oclass, + }, + .pioc = { + &gf119_disp_oimm_oclass, + &gf119_disp_curs_oclass, + }, }; -struct nvkm_oclass -gf119_disp_root_oclass[] = { - { GF110_DISP, &gf119_disp_root_ofuncs }, - {} -}; +static int +gf119_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_(&gf119_disp_root, disp, oclass, + data, size, pobject); +} -struct nvkm_oclass -gf119_disp_sclass[] = { - { GF110_DISP_CORE_CHANNEL_DMA, &gf119_disp_core_ofuncs.base }, - { GF110_DISP_BASE_CHANNEL_DMA, &gf119_disp_base_ofuncs.base }, - { GF110_DISP_OVERLAY_CONTROL_DMA, &gf119_disp_ovly_ofuncs.base }, - { GF110_DISP_OVERLAY, &gf119_disp_oimm_ofuncs.base }, - { GF110_DISP_CURSOR, &gf119_disp_curs_ofuncs.base }, - {} +const struct nvkm_disp_oclass +gf119_disp_root_oclass = { + .base.oclass = GF110_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gf119_disp_root_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c index f89b33496b1e..0bfdb1d1c6ab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c @@ -26,18 +26,33 @@ #include <nvif/class.h> -struct nvkm_oclass -gk104_disp_sclass[] = { - { GK104_DISP_CORE_CHANNEL_DMA, &gf119_disp_core_ofuncs.base }, - { GK104_DISP_BASE_CHANNEL_DMA, &gf119_disp_base_ofuncs.base }, - { GK104_DISP_OVERLAY_CONTROL_DMA, &gf119_disp_ovly_ofuncs.base }, - { GK104_DISP_OVERLAY, &gf119_disp_oimm_ofuncs.base }, - { GK104_DISP_CURSOR, &gf119_disp_curs_ofuncs.base }, - {} +static const struct nv50_disp_root_func +gk104_disp_root = { + .init = gf119_disp_root_init, + .fini = gf119_disp_root_fini, + .dmac = { + &gk104_disp_core_oclass, + &gk104_disp_base_oclass, + &gk104_disp_ovly_oclass, + }, + .pioc = { + &gk104_disp_oimm_oclass, + &gk104_disp_curs_oclass, + }, }; -struct nvkm_oclass -gk104_disp_root_oclass[] = { - { GK104_DISP, &gf119_disp_root_ofuncs }, - {} +static int +gk104_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_(&gk104_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +gk104_disp_root_oclass = { + .base.oclass = GK104_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gk104_disp_root_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c index ef2f73a6539d..1e8dbed8a67c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c @@ -26,18 +26,33 @@ #include <nvif/class.h> -struct nvkm_oclass -gk110_disp_sclass[] = { - { GK110_DISP_CORE_CHANNEL_DMA, &gf119_disp_core_ofuncs.base }, - { GK110_DISP_BASE_CHANNEL_DMA, &gf119_disp_base_ofuncs.base }, - { GK104_DISP_OVERLAY_CONTROL_DMA, &gf119_disp_ovly_ofuncs.base }, - { GK104_DISP_OVERLAY, &gf119_disp_oimm_ofuncs.base }, - { GK104_DISP_CURSOR, &gf119_disp_curs_ofuncs.base }, - {} +static const struct nv50_disp_root_func +gk110_disp_root = { + .init = gf119_disp_root_init, + .fini = gf119_disp_root_fini, + .dmac = { + &gk110_disp_core_oclass, + &gk110_disp_base_oclass, + &gk104_disp_ovly_oclass, + }, + .pioc = { + &gk104_disp_oimm_oclass, + &gk104_disp_curs_oclass, + }, }; -struct nvkm_oclass -gk110_disp_root_oclass[] = { - { GK110_DISP, &gf119_disp_root_ofuncs }, - {} +static int +gk110_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_(&gk110_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +gk110_disp_root_oclass = { + .base.oclass = GK110_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gk110_disp_root_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c index ba69ee4e0a49..44c55be69e99 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c @@ -26,18 +26,33 @@ #include <nvif/class.h> -struct nvkm_oclass -gm107_disp_sclass[] = { - { GM107_DISP_CORE_CHANNEL_DMA, &gf119_disp_core_ofuncs.base }, - { GK110_DISP_BASE_CHANNEL_DMA, &gf119_disp_base_ofuncs.base }, - { GK104_DISP_OVERLAY_CONTROL_DMA, &gf119_disp_ovly_ofuncs.base }, - { GK104_DISP_OVERLAY, &gf119_disp_oimm_ofuncs.base }, - { GK104_DISP_CURSOR, &gf119_disp_curs_ofuncs.base }, - {} +static const struct nv50_disp_root_func +gm107_disp_root = { + .init = gf119_disp_root_init, + .fini = gf119_disp_root_fini, + .dmac = { + &gm107_disp_core_oclass, + &gk110_disp_base_oclass, + &gk104_disp_ovly_oclass, + }, + .pioc = { + &gk104_disp_oimm_oclass, + &gk104_disp_curs_oclass, + }, }; -struct nvkm_oclass -gm107_disp_root_oclass[] = { - { GM107_DISP, &gf119_disp_root_ofuncs }, - {} +static int +gm107_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_(&gm107_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +gm107_disp_root_oclass = { + .base.oclass = GM107_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gm107_disp_root_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm204.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm204.c index 255308f6ec25..168bffe0643c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm204.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm204.c @@ -26,18 +26,33 @@ #include <nvif/class.h> -struct nvkm_oclass -gm204_disp_sclass[] = { - { GM204_DISP_CORE_CHANNEL_DMA, &gf119_disp_core_ofuncs.base }, - { GK110_DISP_BASE_CHANNEL_DMA, &gf119_disp_base_ofuncs.base }, - { GK104_DISP_OVERLAY_CONTROL_DMA, &gf119_disp_ovly_ofuncs.base }, - { GK104_DISP_OVERLAY, &gf119_disp_oimm_ofuncs.base }, - { GK104_DISP_CURSOR, &gf119_disp_curs_ofuncs.base }, - {} +static const struct nv50_disp_root_func +gm204_disp_root = { + .init = gf119_disp_root_init, + .fini = gf119_disp_root_fini, + .dmac = { + &gm204_disp_core_oclass, + &gk110_disp_base_oclass, + &gk104_disp_ovly_oclass, + }, + .pioc = { + &gk104_disp_oimm_oclass, + &gk104_disp_curs_oclass, + }, }; -struct nvkm_oclass -gm204_disp_root_oclass[] = { - { GM204_DISP, &gf119_disp_root_ofuncs }, - {} +static int +gm204_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_(&gm204_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +gm204_disp_root_oclass = { + .base.oclass = GM204_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gm204_disp_root_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c index b1963e531ae1..124a0c24f92c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c @@ -26,18 +26,33 @@ #include <nvif/class.h> -struct nvkm_oclass -gt200_disp_sclass[] = { - { GT200_DISP_CORE_CHANNEL_DMA, &nv50_disp_core_ofuncs.base }, - { GT200_DISP_BASE_CHANNEL_DMA, &nv50_disp_base_ofuncs.base }, - { GT200_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base }, - { G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base }, - { G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base }, - {} +static const struct nv50_disp_root_func +gt200_disp_root = { + .init = nv50_disp_root_init, + .fini = nv50_disp_root_fini, + .dmac = { + >200_disp_core_oclass, + >200_disp_base_oclass, + >200_disp_ovly_oclass, + }, + .pioc = { + &g84_disp_oimm_oclass, + &g84_disp_curs_oclass, + }, }; -struct nvkm_oclass -gt200_disp_root_oclass[] = { - { GT200_DISP, &nv50_disp_root_ofuncs }, - {} +static int +gt200_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_(>200_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +gt200_disp_root_oclass = { + .base.oclass = GT200_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gt200_disp_root_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c index 83b214abb13a..dff52f30668b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c @@ -26,18 +26,33 @@ #include <nvif/class.h> -struct nvkm_oclass -gt215_disp_sclass[] = { - { GT214_DISP_CORE_CHANNEL_DMA, &nv50_disp_core_ofuncs.base }, - { GT214_DISP_BASE_CHANNEL_DMA, &nv50_disp_base_ofuncs.base }, - { GT214_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base }, - { GT214_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base }, - { GT214_DISP_CURSOR, &nv50_disp_curs_ofuncs.base }, - {} +static const struct nv50_disp_root_func +gt215_disp_root = { + .init = nv50_disp_root_init, + .fini = nv50_disp_root_fini, + .dmac = { + >215_disp_core_oclass, + >215_disp_base_oclass, + >215_disp_ovly_oclass, + }, + .pioc = { + >215_disp_oimm_oclass, + >215_disp_curs_oclass, + }, }; -struct nvkm_oclass -gt215_disp_root_oclass[] = { - { GT214_DISP, &nv50_disp_root_ofuncs }, - {} +static int +gt215_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_(>215_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +gt215_disp_root_oclass = { + .base.oclass = GT214_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gt215_disp_root_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c index 603ebb6fd541..2d9b81fb83a2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c @@ -21,6 +21,7 @@ * * Authors: Ben Skeggs */ +#define nv04_disp_root(p) container_of((p), struct nv04_disp_root, object); #include "priv.h" #include <core/client.h> @@ -28,11 +29,17 @@ #include <nvif/class.h> #include <nvif/unpack.h> +struct nv04_disp_root { + struct nvkm_object object; + struct nvkm_disp *disp; +}; + static int -nv04_disp_scanoutpos(struct nvkm_object *object, struct nvkm_disp *disp, +nv04_disp_scanoutpos(struct nv04_disp_root *root, void *data, u32 size, int head) { - struct nvkm_device *device = disp->engine.subdev.device; + struct nvkm_device *device = root->disp->engine.subdev.device; + struct nvkm_object *object = &root->object; const u32 hoff = head * 0x2000; union { struct nv04_disp_scanoutpos_v0 v0; @@ -74,10 +81,10 @@ nv04_disp_scanoutpos(struct nvkm_object *object, struct nvkm_disp *disp, static int nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) { + struct nv04_disp_root *root = nv04_disp_root(object); union { struct nv04_disp_mthd_v0 v0; } *args = data; - struct nvkm_disp *disp = (void *)object->engine; int head, ret; nvif_ioctl(object, "disp mthd size %d\n", size); @@ -94,7 +101,7 @@ nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) switch (mthd) { case NV04_DISP_SCANOUTPOS: - return nv04_disp_scanoutpos(object, disp, data, size, head); + return nv04_disp_scanoutpos(root, data, size, head); default: break; } @@ -102,18 +109,31 @@ nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) return -EINVAL; } -static struct nvkm_ofuncs -nv04_disp_ofuncs = { - .ctor = _nvkm_object_ctor, - .dtor = nvkm_object_destroy, - .init = _nvkm_object_init, - .fini = _nvkm_object_fini, +static struct nvkm_object_func +nv04_disp_root = { .mthd = nv04_disp_mthd, .ntfy = nvkm_disp_ntfy, }; -struct nvkm_oclass -nv04_disp_sclass[] = { - { NV04_DISP, &nv04_disp_ofuncs }, - {}, +static int +nv04_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + struct nv04_disp_root *root; + + if (!(root = kzalloc(sizeof(*root), GFP_KERNEL))) + return -ENOMEM; + root->disp = disp; + *pobject = &root->object; + + nvkm_object_ctor(&nv04_disp_root, oclass, &root->object); + return 0; +} + +const struct nvkm_disp_oclass +nv04_disp_root_oclass = { + .base.oclass = NV04_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = nv04_disp_root_new, }; 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, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h index 9ae4bf927065..5b2c903ce9ee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h @@ -1,36 +1,43 @@ #ifndef __NV50_DISP_ROOT_H__ #define __NV50_DISP_ROOT_H__ +#define nv50_disp_root(p) container_of((p), struct nv50_disp_root, object) #include "nv50.h" #include "channv50.h" #include "dmacnv50.h" -#include <core/parent.h> - -#include <nvif/class.h> struct nv50_disp_root { - struct nvkm_parent base; + const struct nv50_disp_root_func *func; + struct nv50_disp *disp; + struct nvkm_object object; + + struct nvkm_gpuobj *instmem; struct nvkm_ramht *ramht; - u32 chan; }; -extern struct nvkm_oclass nv50_disp_root_oclass[]; -extern struct nvkm_oclass nv50_disp_sclass[]; -extern struct nvkm_oclass g84_disp_root_oclass[]; -extern struct nvkm_oclass g84_disp_sclass[]; -extern struct nvkm_oclass g94_disp_root_oclass[]; -extern struct nvkm_oclass g94_disp_sclass[]; -extern struct nvkm_oclass gt200_disp_root_oclass[]; -extern struct nvkm_oclass gt200_disp_sclass[]; -extern struct nvkm_oclass gt215_disp_root_oclass[]; -extern struct nvkm_oclass gt215_disp_sclass[]; -extern struct nvkm_oclass gf119_disp_root_oclass[]; -extern struct nvkm_oclass gf119_disp_sclass[]; -extern struct nvkm_oclass gk104_disp_root_oclass[]; -extern struct nvkm_oclass gk104_disp_sclass[]; -extern struct nvkm_oclass gk110_disp_root_oclass[]; -extern struct nvkm_oclass gk110_disp_sclass[]; -extern struct nvkm_oclass gm107_disp_root_oclass[]; -extern struct nvkm_oclass gm107_disp_sclass[]; -extern struct nvkm_oclass gm204_disp_root_oclass[]; -extern struct nvkm_oclass gm204_disp_sclass[]; +struct nv50_disp_root_func { + int (*init)(struct nv50_disp_root *); + void (*fini)(struct nv50_disp_root *); + const struct nv50_disp_dmac_oclass *dmac[3]; + const struct nv50_disp_pioc_oclass *pioc[2]; +}; + +int nv50_disp_root_new_(const struct nv50_disp_root_func *, struct nvkm_disp *, + const struct nvkm_oclass *, void *data, u32 size, + struct nvkm_object **); +int nv50_disp_root_init(struct nv50_disp_root *); +void nv50_disp_root_fini(struct nv50_disp_root *); + +int gf119_disp_root_init(struct nv50_disp_root *); +void gf119_disp_root_fini(struct nv50_disp_root *); + +extern const struct nvkm_disp_oclass nv50_disp_root_oclass; +extern const struct nvkm_disp_oclass g84_disp_root_oclass; +extern const struct nvkm_disp_oclass g94_disp_root_oclass; +extern const struct nvkm_disp_oclass gt200_disp_root_oclass; +extern const struct nvkm_disp_oclass gt215_disp_root_oclass; +extern const struct nvkm_disp_oclass gf119_disp_root_oclass; +extern const struct nvkm_disp_oclass gk104_disp_root_oclass; +extern const struct nvkm_disp_oclass gk110_disp_root_oclass; +extern const struct nvkm_disp_oclass gm107_disp_root_oclass; +extern const struct nvkm_disp_oclass gm204_disp_root_oclass; #endif |