diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2018-05-08 20:39:46 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2018-05-18 15:01:20 +1000 |
commit | bb3b0a422074606400e6aff216300bb4f012b22a (patch) | |
tree | fdf98fc1a38f0ae4887d7428d62e15670f8d66c1 | |
parent | f5e088d6f0b4d969b2e7d8f931af082ba2527a56 (diff) | |
download | op-kernel-dev-bb3b0a422074606400e6aff216300bb4f012b22a.zip op-kernel-dev-bb3b0a422074606400e6aff216300bb4f012b22a.tar.gz |
drm/nouveau/disp/nv50-: initialise from the engine, rather than the user object
Engines are initialised on an as-needed basis, so this results in the
same behaviour, whilst allowing us to simplify things a bit.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
33 files changed, 247 insertions, 243 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c index 5b9d9c6..32fa94a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c @@ -220,6 +220,9 @@ nvkm_disp_fini(struct nvkm_engine *engine, bool suspend) struct nvkm_conn *conn; struct nvkm_outp *outp; + if (disp->func->fini) + disp->func->fini(disp); + list_for_each_entry(outp, &disp->outp, head) { nvkm_outp_fini(outp); } @@ -237,6 +240,7 @@ nvkm_disp_init(struct nvkm_engine *engine) struct nvkm_disp *disp = nvkm_disp(engine); struct nvkm_conn *conn; struct nvkm_outp *outp; + struct nvkm_ior *ior; list_for_each_entry(conn, &disp->conn, head) { nvkm_conn_init(conn); @@ -246,6 +250,19 @@ nvkm_disp_init(struct nvkm_engine *engine) nvkm_outp_init(outp); } + if (disp->func->init) { + int ret = disp->func->init(disp); + if (ret) + return ret; + } + + /* Set 'normal' (ie. when it's attached to a head) state for + * each output resource to 'fully enabled'. + */ + list_for_each_entry(ior, &disp->ior, head) { + ior->func->power(ior, true, true, true, true, true); + } + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h index 40681db..b518585 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h @@ -4,6 +4,7 @@ #define nv50_disp_chan(p) container_of((p), struct nv50_disp_chan, object) #include <core/object.h> #include "nv50.h" +struct nv50_disp_root; struct nv50_disp_chan { const struct nv50_disp_chan_func *func; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c index ce7cd74..6680ff8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c @@ -31,7 +31,7 @@ int gf119_disp_dmac_bind(struct nv50_disp_dmac *chan, struct nvkm_object *object, u32 handle) { - return nvkm_ramht_insert(chan->base.root->ramht, object, + return nvkm_ramht_insert(chan->base.root->disp->ramht, object, chan->base.chid.user, -9, handle, chan->base.chid.user << 27 | 0x00000001); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c index 070ec5e..c80d047 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c @@ -33,7 +33,7 @@ struct nv50_disp_dmac_object { struct nvkm_oproxy oproxy; - struct nv50_disp_root *root; + struct nv50_disp *disp; int hash; }; @@ -42,7 +42,7 @@ 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); + nvkm_ramht_remove(object->disp->ramht, object->hash); } static const struct nvkm_oproxy_func @@ -56,8 +56,8 @@ nv50_disp_dmac_child_new_(struct nv50_disp_chan *base, 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; + struct nv50_disp *disp = chan->base.root->disp; + struct nvkm_device *device = disp->base.engine.subdev.device; const struct nvkm_device_oclass *sclass = oclass->priv; struct nv50_disp_dmac_object *object; int ret; @@ -65,7 +65,7 @@ nv50_disp_dmac_child_new_(struct nv50_disp_chan *base, if (!(object = kzalloc(sizeof(*object), GFP_KERNEL))) return -ENOMEM; nvkm_oproxy_ctor(&nv50_disp_dmac_child_func_, oclass, &object->oproxy); - object->root = root; + object->disp = disp; *pobject = &object->oproxy.base; ret = sclass->ctor(device, oclass, data, size, &object->oproxy.object); @@ -177,7 +177,7 @@ int nv50_disp_dmac_bind(struct nv50_disp_dmac *chan, struct nvkm_object *object, u32 handle) { - return nvkm_ramht_insert(chan->base.root->ramht, object, + return nvkm_ramht_insert(chan->base.root->disp->ramht, object, chan->base.chid.user, -10, handle, chan->base.chid.user << 28 | chan->base.chid.user); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c index 1ec81f3..731f188 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c @@ -28,6 +28,8 @@ static const struct nv50_disp_func g84_disp = { + .init = nv50_disp_init, + .fini = nv50_disp_fini, .intr = nv50_disp_intr, .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c index 791c2cd..def54fe 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c @@ -28,6 +28,8 @@ static const struct nv50_disp_func g94_disp = { + .init = nv50_disp_init, + .fini = nv50_disp_fini, .intr = nv50_disp_intr, .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c index 0139d14..382e6a6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c @@ -26,6 +26,9 @@ #include "ior.h" #include "rootnv50.h" +#include <core/ramht.h> +#include <subdev/timer.h> + void gf119_disp_super(struct work_struct *work) { @@ -164,8 +167,87 @@ gf119_disp_intr(struct nv50_disp *disp) } } +void +gf119_disp_fini(struct nv50_disp *disp) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + /* disable all interrupts */ + nvkm_wr32(device, 0x6100b0, 0x00000000); +} + +int +gf119_disp_init(struct nv50_disp *disp) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_head *head; + u32 tmp; + int i; + + /* The below segments of code copying values from one register to + * another appear to inform EVO of the display capabilities or + * something similar. + */ + + /* ... CRTC caps */ + list_for_each_entry(head, &disp->base.head, head) { + const u32 hoff = head->id * 0x800; + tmp = nvkm_rd32(device, 0x616104 + hoff); + nvkm_wr32(device, 0x6101b4 + hoff, tmp); + tmp = nvkm_rd32(device, 0x616108 + hoff); + nvkm_wr32(device, 0x6101b8 + hoff, tmp); + tmp = nvkm_rd32(device, 0x61610c + hoff); + nvkm_wr32(device, 0x6101bc + hoff, tmp); + } + + /* ... DAC caps */ + for (i = 0; i < disp->dac.nr; i++) { + tmp = nvkm_rd32(device, 0x61a000 + (i * 0x800)); + nvkm_wr32(device, 0x6101c0 + (i * 0x800), tmp); + } + + /* ... SOR caps */ + for (i = 0; i < disp->sor.nr; i++) { + tmp = nvkm_rd32(device, 0x61c000 + (i * 0x800)); + nvkm_wr32(device, 0x6301c4 + (i * 0x800), tmp); + } + + /* steal display away from vbios, or something like that */ + if (nvkm_rd32(device, 0x6100ac) & 0x00000100) { + nvkm_wr32(device, 0x6100ac, 0x00000100); + nvkm_mask(device, 0x6194e8, 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x6194e8) & 0x00000002)) + break; + ) < 0) + return -EBUSY; + } + + /* point at display engine memory area (hash table, objects) */ + nvkm_wr32(device, 0x610010, (disp->inst->addr >> 8) | 9); + + /* enable supervisor interrupts, disable everything else */ + nvkm_wr32(device, 0x610090, 0x00000000); + nvkm_wr32(device, 0x6100a0, 0x00000000); + nvkm_wr32(device, 0x6100b0, 0x00000307); + + /* disable underflow reporting, preventing an intermittent issue + * on some gk104 boards where the production vbios left this + * setting enabled by default. + * + * ftp://download.nvidia.com/open-gpu-doc/gk104-disable-underflow-reporting/1/gk104-disable-underflow-reporting.txt + */ + list_for_each_entry(head, &disp->base.head, head) { + const u32 hoff = head->id * 0x800; + nvkm_mask(device, 0x616308 + hoff, 0x00000111, 0x00000010); + } + + return 0; +} + static const struct nv50_disp_func gf119_disp = { + .init = gf119_disp_init, + .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, .uevent = &gf119_disp_chan_uevent, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c index 6a59a52..4c3439b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c @@ -28,6 +28,8 @@ static const struct nv50_disp_func gk104_disp = { + .init = gf119_disp_init, + .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, .uevent = &gf119_disp_chan_uevent, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c index f3b10dc4..bc6f475 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c @@ -28,6 +28,8 @@ static const struct nv50_disp_func gk110_disp = { + .init = gf119_disp_init, + .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, .uevent = &gf119_disp_chan_uevent, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c index 068c595..031cf6b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c @@ -28,6 +28,8 @@ static const struct nv50_disp_func gm107_disp = { + .init = gf119_disp_init, + .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, .uevent = &gf119_disp_chan_uevent, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c index 1c27dbe..ec9c33a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c @@ -28,6 +28,8 @@ static const struct nv50_disp_func gm200_disp = { + .init = gf119_disp_init, + .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, .uevent = &gf119_disp_chan_uevent, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c index 84933b6..fd62166 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c @@ -28,6 +28,8 @@ static const struct nv50_disp_func gp100_disp = { + .init = gf119_disp_init, + .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, .uevent = &gf119_disp_chan_uevent, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c index b36d926..0a2c5b5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c @@ -54,6 +54,8 @@ gp102_disp_intr_error(struct nv50_disp *disp, int chid) static const struct nv50_disp_func gp102_disp = { + .init = gf119_disp_init, + .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gp102_disp_intr_error, .uevent = &gf119_disp_chan_uevent, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c index 62e721d..f801837 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c @@ -28,6 +28,8 @@ static const struct nv50_disp_func gt200_disp = { + .init = nv50_disp_init, + .fini = nv50_disp_fini, .intr = nv50_disp_intr, .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c index a5b1b14..7581efc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c @@ -28,6 +28,8 @@ static const struct nv50_disp_func gt215_disp = { + .init = nv50_disp_init, + .fini = nv50_disp_fini, .intr = nv50_disp_intr, .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c index ff49040..cfdce23 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c @@ -26,6 +26,8 @@ static const struct nv50_disp_func mcp77_disp = { + .init = nv50_disp_init, + .fini = nv50_disp_fini, .intr = nv50_disp_intr, .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c index 0cf968d..85d9329 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c @@ -26,6 +26,8 @@ static const struct nv50_disp_func mcp89_disp = { + .init = nv50_disp_init, + .fini = nv50_disp_fini, .intr = nv50_disp_intr, .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c index c0faa39..1d2280a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c @@ -28,7 +28,7 @@ #include <core/client.h> #include <core/enum.h> -#include <core/gpuobj.h> +#include <core/ramht.h> #include <subdev/bios.h> #include <subdev/bios/disp.h> #include <subdev/bios/init.h> @@ -49,13 +49,32 @@ nv50_disp_intr_(struct nvkm_disp *base) disp->func->intr(disp); } +static void +nv50_disp_fini_(struct nvkm_disp *base) +{ + struct nv50_disp *disp = nv50_disp(base); + disp->func->fini(disp); +} + +static int +nv50_disp_init_(struct nvkm_disp *base) +{ + struct nv50_disp *disp = nv50_disp(base); + return disp->func->init(disp); +} + static void * nv50_disp_dtor_(struct nvkm_disp *base) { struct nv50_disp *disp = nv50_disp(base); + + nvkm_ramht_del(&disp->ramht); + nvkm_gpuobj_del(&disp->inst); + nvkm_event_fini(&disp->uevent); if (disp->wq) destroy_workqueue(disp->wq); + return disp; } @@ -65,6 +84,7 @@ nv50_disp_oneinit_(struct nvkm_disp *base) struct nv50_disp *disp = nv50_disp(base); const struct nv50_disp_func *func = disp->func; struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; int ret, i; disp->head.nr = func->head.cnt(&disp->base, &disp->head.mask); @@ -107,13 +127,20 @@ nv50_disp_oneinit_(struct nvkm_disp *base) return ret; } - return 0; + ret = nvkm_gpuobj_new(device, 0x10000, 0x10000, false, NULL, + &disp->inst); + if (ret) + return ret; + + return nvkm_ramht_new(device, 0x1000, 0, disp->inst, &disp->ramht); } static const struct nvkm_disp_func nv50_disp_ = { .dtor = nv50_disp_dtor_, .oneinit = nv50_disp_oneinit_, + .init = nv50_disp_init_, + .fini = nv50_disp_fini_, .intr = nv50_disp_intr_, .root = nv50_disp_root_, }; @@ -643,8 +670,84 @@ nv50_disp_intr(struct nv50_disp *disp) } } +void +nv50_disp_fini(struct nv50_disp *disp) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + /* disable all interrupts */ + nvkm_wr32(device, 0x610024, 0x00000000); + nvkm_wr32(device, 0x610020, 0x00000000); +} + +int +nv50_disp_init(struct nv50_disp *disp) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_head *head; + u32 tmp; + int i; + + /* The below segments of code copying values from one register to + * another appear to inform EVO of the display capabilities or + * something similar. NFI what the 0x614004 caps are for.. + */ + tmp = nvkm_rd32(device, 0x614004); + nvkm_wr32(device, 0x610184, tmp); + + /* ... CRTC caps */ + list_for_each_entry(head, &disp->base.head, head) { + tmp = nvkm_rd32(device, 0x616100 + (head->id * 0x800)); + nvkm_wr32(device, 0x610190 + (head->id * 0x10), tmp); + tmp = nvkm_rd32(device, 0x616104 + (head->id * 0x800)); + nvkm_wr32(device, 0x610194 + (head->id * 0x10), tmp); + tmp = nvkm_rd32(device, 0x616108 + (head->id * 0x800)); + nvkm_wr32(device, 0x610198 + (head->id * 0x10), tmp); + tmp = nvkm_rd32(device, 0x61610c + (head->id * 0x800)); + nvkm_wr32(device, 0x61019c + (head->id * 0x10), tmp); + } + + /* ... DAC caps */ + for (i = 0; i < disp->dac.nr; i++) { + tmp = nvkm_rd32(device, 0x61a000 + (i * 0x800)); + nvkm_wr32(device, 0x6101d0 + (i * 0x04), tmp); + } + + /* ... SOR caps */ + for (i = 0; i < disp->sor.nr; i++) { + tmp = nvkm_rd32(device, 0x61c000 + (i * 0x800)); + nvkm_wr32(device, 0x6101e0 + (i * 0x04), tmp); + } + + /* ... PIOR caps */ + for (i = 0; i < disp->pior.nr; i++) { + tmp = nvkm_rd32(device, 0x61e000 + (i * 0x800)); + nvkm_wr32(device, 0x6101f0 + (i * 0x04), tmp); + } + + /* steal display away from vbios, or something like that */ + if (nvkm_rd32(device, 0x610024) & 0x00000100) { + nvkm_wr32(device, 0x610024, 0x00000100); + nvkm_mask(device, 0x6194e8, 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x6194e8) & 0x00000002)) + break; + ) < 0) + return -EBUSY; + } + + /* point at display engine memory area (hash table, objects) */ + nvkm_wr32(device, 0x610010, (disp->inst->addr >> 8) | 9); + + /* enable supervisor interrupts, disable everything else */ + nvkm_wr32(device, 0x61002c, 0x00000370); + nvkm_wr32(device, 0x610028, 0x00000000); + return 0; +} + static const struct nv50_disp_func nv50_disp = { + .init = nv50_disp_init, + .fini = nv50_disp_fini, .intr = nv50_disp_intr, .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h index a29bcf7..bb622d0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h @@ -32,6 +32,9 @@ struct nv50_disp { u8 type[3]; } pior; + struct nvkm_gpuobj *inst; + struct nvkm_ramht *ramht; + struct nv50_disp_chan *chan[21]; }; @@ -46,6 +49,8 @@ int nv50_disp_new_(const struct nv50_disp_func *, struct nvkm_device *, int index, struct nvkm_disp **); struct nv50_disp_func { + int (*init)(struct nv50_disp *); + void (*fini)(struct nv50_disp *); void (*intr)(struct nv50_disp *); void (*intr_error)(struct nv50_disp *, int chid); @@ -60,9 +65,13 @@ struct nv50_disp_func { } head, dac, sor, pior; }; +int nv50_disp_init(struct nv50_disp *); +void nv50_disp_fini(struct nv50_disp *); void nv50_disp_intr(struct nv50_disp *); void nv50_disp_super(struct work_struct *); +int gf119_disp_init(struct nv50_disp *); +void gf119_disp_fini(struct nv50_disp *); void gf119_disp_intr(struct nv50_disp *); void gf119_disp_super(struct work_struct *); void gf119_disp_intr_error(struct nv50_disp *, int); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h index c614351..ef66c5f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h @@ -13,6 +13,8 @@ void nvkm_disp_vblank(struct nvkm_disp *, int head); struct nvkm_disp_func { void *(*dtor)(struct nvkm_disp *); int (*oneinit)(struct nvkm_disp *); + int (*init)(struct nvkm_disp *); + void (*fini)(struct nvkm_disp *); void (*intr)(struct nvkm_disp *); const struct nvkm_disp_oclass *(*root)(struct nvkm_disp *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c index 721e4f7..36ac0d42 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c @@ -28,8 +28,6 @@ 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, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c index 9493f6e..18b87b3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c @@ -28,8 +28,6 @@ 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, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c index 4ba2d80..7c5701f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c @@ -22,96 +22,12 @@ * Authors: Ben Skeggs */ #include "rootnv50.h" -#include "head.h" #include "dmacnv50.h" -#include <core/ramht.h> -#include <subdev/timer.h> - #include <nvif/class.h> -void -gf119_disp_root_fini(struct nv50_disp_root *root) -{ - 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_head *head; - struct nvkm_device *device = disp->base.engine.subdev.device; - u32 tmp; - int i; - - /* The below segments of code copying values from one register to - * another appear to inform EVO of the display capabilities or - * something similar. - */ - - /* ... CRTC caps */ - list_for_each_entry(head, &disp->base.head, head) { - const u32 hoff = head->id * 0x800; - tmp = nvkm_rd32(device, 0x616104 + hoff); - nvkm_wr32(device, 0x6101b4 + hoff, tmp); - tmp = nvkm_rd32(device, 0x616108 + hoff); - nvkm_wr32(device, 0x6101b8 + hoff, tmp); - tmp = nvkm_rd32(device, 0x61610c + hoff); - nvkm_wr32(device, 0x6101bc + hoff, tmp); - } - - /* ... DAC caps */ - for (i = 0; i < disp->dac.nr; i++) { - tmp = nvkm_rd32(device, 0x61a000 + (i * 0x800)); - nvkm_wr32(device, 0x6101c0 + (i * 0x800), tmp); - } - - /* ... SOR caps */ - for (i = 0; i < disp->sor.nr; i++) { - tmp = nvkm_rd32(device, 0x61c000 + (i * 0x800)); - nvkm_wr32(device, 0x6301c4 + (i * 0x800), tmp); - } - - /* steal display away from vbios, or something like that */ - if (nvkm_rd32(device, 0x6100ac) & 0x00000100) { - nvkm_wr32(device, 0x6100ac, 0x00000100); - nvkm_mask(device, 0x6194e8, 0x00000001, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x6194e8) & 0x00000002)) - break; - ) < 0) - return -EBUSY; - } - - /* point at display engine memory area (hash table, objects) */ - nvkm_wr32(device, 0x610010, (root->instmem->addr >> 8) | 9); - - /* enable supervisor interrupts, disable everything else */ - nvkm_wr32(device, 0x610090, 0x00000000); - nvkm_wr32(device, 0x6100a0, 0x00000000); - nvkm_wr32(device, 0x6100b0, 0x00000307); - - /* disable underflow reporting, preventing an intermittent issue - * on some gk104 boards where the production vbios left this - * setting enabled by default. - * - * ftp://download.nvidia.com/open-gpu-doc/gk104-disable-underflow-reporting/1/gk104-disable-underflow-reporting.txt - */ - list_for_each_entry(head, &disp->base.head, head) { - const u32 hoff = head->id * 0x800; - nvkm_mask(device, 0x616308 + hoff, 0x00000111, 0x00000010); - } - - return 0; -} - static const struct nv50_disp_root_func gf119_disp_root = { - .init = gf119_disp_root_init, - .fini = gf119_disp_root_fini, .dmac = { &gf119_disp_core_oclass, &gf119_disp_base_oclass, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c index 0bfdb1d..c0946a6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c @@ -28,8 +28,6 @@ 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, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c index 1e8dbed..2ebc166 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c @@ -28,8 +28,6 @@ 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, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c index 44c55be..5a62c9e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c @@ -28,8 +28,6 @@ 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, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c index 38f5ee1..2634e06 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c @@ -28,8 +28,6 @@ static const struct nv50_disp_root_func gm200_disp_root = { - .init = gf119_disp_root_init, - .fini = gf119_disp_root_fini, .dmac = { &gm200_disp_core_oclass, &gk110_disp_base_oclass, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c index ac8fdd7..7847235 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c @@ -28,8 +28,6 @@ static const struct nv50_disp_root_func gp100_disp_root = { - .init = gf119_disp_root_init, - .fini = gf119_disp_root_fini, .dmac = { &gp100_disp_core_oclass, &gk110_disp_base_oclass, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c index 37122ca..2fdfa8d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c @@ -28,8 +28,6 @@ static const struct nv50_disp_root_func gp102_disp_root = { - .init = gf119_disp_root_init, - .fini = gf119_disp_root_fini, .dmac = { &gp102_disp_core_oclass, &gp102_disp_base_oclass, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c index 124a0c2..facad27 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c @@ -28,8 +28,6 @@ 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, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c index dff52f3..3e93db5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c @@ -28,8 +28,6 @@ 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, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c index c8379bf..072c8c0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -28,8 +28,6 @@ #include "ior.h" #include <core/client.h> -#include <core/ramht.h> -#include <subdev/timer.h> #include <nvif/class.h> #include <nvif/cl5070.h> @@ -315,49 +313,16 @@ nv50_disp_root_child_get_(struct nvkm_object *object, int index, 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); - struct nvkm_ior *ior; - int ret; - - ret = root->func->init(root); - if (ret) - return ret; - - /* Set 'normal' (ie. when it's attached to a head) state for - * each output resource to 'fully enabled'. - */ - list_for_each_entry(ior, &root->disp->base.ior, head) { - ior->func->power(ior, true, true, true, true, true); - } - - return 0; -} - 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_, @@ -370,8 +335,6 @@ nv50_disp_root_new_(const struct nv50_disp_root_func *func, { struct nv50_disp *disp = nv50_disp(base); struct nv50_disp_root *root; - struct nvkm_device *device = disp->base.engine.subdev.device; - int ret; if (!(root = kzalloc(sizeof(*root), GFP_KERNEL))) return -ENOMEM; @@ -380,94 +343,11 @@ nv50_disp_root_new_(const struct nv50_disp_root_func *func, 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, root->instmem, &root->ramht); -} - -void -nv50_disp_root_fini(struct nv50_disp_root *root) -{ - struct nvkm_device *device = root->disp->base.engine.subdev.device; - /* disable all interrupts */ - nvkm_wr32(device, 0x610024, 0x00000000); - nvkm_wr32(device, 0x610020, 0x00000000); -} - -int -nv50_disp_root_init(struct nv50_disp_root *root) -{ - struct nv50_disp *disp = root->disp; - struct nvkm_head *head; - struct nvkm_device *device = disp->base.engine.subdev.device; - u32 tmp; - int i; - - /* The below segments of code copying values from one register to - * another appear to inform EVO of the display capabilities or - * something similar. NFI what the 0x614004 caps are for.. - */ - tmp = nvkm_rd32(device, 0x614004); - nvkm_wr32(device, 0x610184, tmp); - - /* ... CRTC caps */ - list_for_each_entry(head, &disp->base.head, head) { - tmp = nvkm_rd32(device, 0x616100 + (head->id * 0x800)); - nvkm_wr32(device, 0x610190 + (head->id * 0x10), tmp); - tmp = nvkm_rd32(device, 0x616104 + (head->id * 0x800)); - nvkm_wr32(device, 0x610194 + (head->id * 0x10), tmp); - tmp = nvkm_rd32(device, 0x616108 + (head->id * 0x800)); - nvkm_wr32(device, 0x610198 + (head->id * 0x10), tmp); - tmp = nvkm_rd32(device, 0x61610c + (head->id * 0x800)); - nvkm_wr32(device, 0x61019c + (head->id * 0x10), tmp); - } - - /* ... DAC caps */ - for (i = 0; i < disp->dac.nr; i++) { - tmp = nvkm_rd32(device, 0x61a000 + (i * 0x800)); - nvkm_wr32(device, 0x6101d0 + (i * 0x04), tmp); - } - - /* ... SOR caps */ - for (i = 0; i < disp->sor.nr; i++) { - tmp = nvkm_rd32(device, 0x61c000 + (i * 0x800)); - nvkm_wr32(device, 0x6101e0 + (i * 0x04), tmp); - } - - /* ... PIOR caps */ - for (i = 0; i < disp->pior.nr; i++) { - tmp = nvkm_rd32(device, 0x61e000 + (i * 0x800)); - nvkm_wr32(device, 0x6101f0 + (i * 0x04), tmp); - } - - /* steal display away from vbios, or something like that */ - if (nvkm_rd32(device, 0x610024) & 0x00000100) { - nvkm_wr32(device, 0x610024, 0x00000100); - nvkm_mask(device, 0x6194e8, 0x00000001, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x6194e8) & 0x00000002)) - break; - ) < 0) - return -EBUSY; - } - - /* point at display engine memory area (hash table, objects) */ - nvkm_wr32(device, 0x610010, (root->instmem->addr >> 8) | 9); - - /* enable supervisor interrupts, disable everything else */ - nvkm_wr32(device, 0x61002c, 0x00000370); - nvkm_wr32(device, 0x610028, 0x00000000); return 0; } static const struct nv50_disp_root_func nv50_disp_root = { - .init = nv50_disp_root_init, - .fini = nv50_disp_root_fini, .dmac = { &nv50_disp_core_oclass, &nv50_disp_base_oclass, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h index 4818fa6..06b554b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h @@ -10,14 +10,9 @@ struct nv50_disp_root { const struct nv50_disp_root_func *func; struct nv50_disp *disp; struct nvkm_object object; - - struct nvkm_gpuobj *instmem; - struct nvkm_ramht *ramht; }; 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]; }; @@ -25,11 +20,6 @@ struct nv50_disp_root_func { 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; |