diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2017-05-19 23:59:35 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2017-06-16 14:04:48 +1000 |
commit | 57b2d73be275f853066aaf5cc33f6c59a94260b2 (patch) | |
tree | d95db4ceb4cf485007977df9d43eb3643d4b21d7 /drivers/gpu/drm/nouveau/nvkm/engine | |
parent | 14187b007e646c0dbf0813d22f7733cf6eebc099 (diff) | |
download | linux-stable-57b2d73be275f853066aaf5cc33f6c59a94260b2.tar.gz linux-stable-57b2d73be275f853066aaf5cc33f6c59a94260b2.tar.bz2 linux-stable-57b2d73be275f853066aaf5cc33f6c59a94260b2.zip |
drm/nouveau/disp: common implementation of scanoutpos method in nvkm_head
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine')
21 files changed, 161 insertions, 150 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c index 1b74072e28fe..bdaec4e4cb60 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c @@ -32,7 +32,6 @@ g84_disp = { .super = nv50_disp_super, .root = &g84_disp_root_oclass, .head.new = nv50_head_new, - .head.scanoutpos = nv50_disp_root_scanoutpos, .outp.internal.crt = nv50_dac_output_new, .outp.internal.tmds = nv50_sor_output_new, .outp.internal.lvds = nv50_sor_output_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c index 38a5d165c11c..12e4984e5393 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c @@ -32,7 +32,6 @@ g94_disp = { .super = nv50_disp_super, .root = &g94_disp_root_oclass, .head.new = nv50_head_new, - .head.scanoutpos = nv50_disp_root_scanoutpos, .outp.internal.crt = nv50_dac_output_new, .outp.internal.tmds = nv50_sor_output_new, .outp.internal.lvds = nv50_sor_output_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c index e9cf53e918af..d353d29f2ad4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c @@ -501,7 +501,6 @@ gf119_disp = { .super = gf119_disp_super, .root = &gf119_disp_root_oclass, .head.new = gf119_head_new, - .head.scanoutpos = gf119_disp_root_scanoutpos, .outp.internal.crt = nv50_dac_output_new, .outp.internal.tmds = nv50_sor_output_new, .outp.internal.lvds = nv50_sor_output_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c index 3dd530298a28..a83684c2c129 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c @@ -33,7 +33,6 @@ gk104_disp = { .super = gf119_disp_super, .root = &gk104_disp_root_oclass, .head.new = gf119_head_new, - .head.scanoutpos = gf119_disp_root_scanoutpos, .outp.internal.crt = nv50_dac_output_new, .outp.internal.tmds = nv50_sor_output_new, .outp.internal.lvds = nv50_sor_output_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c index 8c4cabec036d..72a2fc0183b3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c @@ -33,7 +33,6 @@ gk110_disp = { .super = gf119_disp_super, .root = &gk110_disp_root_oclass, .head.new = gf119_head_new, - .head.scanoutpos = gf119_disp_root_scanoutpos, .outp.internal.crt = nv50_dac_output_new, .outp.internal.tmds = nv50_sor_output_new, .outp.internal.lvds = nv50_sor_output_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c index dfb32c14558e..b6658e22b207 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c @@ -33,7 +33,6 @@ gm107_disp = { .super = gf119_disp_super, .root = &gm107_disp_root_oclass, .head.new = gf119_head_new, - .head.scanoutpos = gf119_disp_root_scanoutpos, .outp.internal.crt = nv50_dac_output_new, .outp.internal.tmds = nv50_sor_output_new, .outp.internal.lvds = nv50_sor_output_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c index 97ca9434e1f3..e0ea05350dfb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c @@ -33,7 +33,6 @@ gm200_disp = { .super = gf119_disp_super, .root = &gm200_disp_root_oclass, .head.new = gf119_head_new, - .head.scanoutpos = gf119_disp_root_scanoutpos, .outp.internal.crt = nv50_dac_output_new, .outp.internal.tmds = nv50_sor_output_new, .outp.internal.lvds = nv50_sor_output_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c index e0d5ed423f19..90ea05f98699 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c @@ -33,7 +33,6 @@ gp100_disp = { .super = gf119_disp_super, .root = &gp100_disp_root_oclass, .head.new = gf119_head_new, - .head.scanoutpos = gf119_disp_root_scanoutpos, .outp.internal.crt = nv50_dac_output_new, .outp.internal.tmds = nv50_sor_output_new, .outp.internal.lvds = nv50_sor_output_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c index 56eeee4dd634..722a057bc9ff 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c @@ -59,7 +59,6 @@ gp102_disp = { .super = gf119_disp_super, .root = &gp102_disp_root_oclass, .head.new = gf119_head_new, - .head.scanoutpos = gf119_disp_root_scanoutpos, .outp.internal.crt = nv50_dac_output_new, .outp.internal.tmds = nv50_sor_output_new, .outp.internal.lvds = nv50_sor_output_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c index fa8eea41dfa2..a5710ea0b244 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c @@ -32,7 +32,6 @@ gt200_disp = { .super = nv50_disp_super, .root = >200_disp_root_oclass, .head.new = nv50_head_new, - .head.scanoutpos = nv50_disp_root_scanoutpos, .outp.internal.crt = nv50_dac_output_new, .outp.internal.tmds = nv50_sor_output_new, .outp.internal.lvds = nv50_sor_output_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c index b211757910e2..3c100fc617a6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c @@ -32,7 +32,6 @@ gt215_disp = { .super = nv50_disp_super, .root = >215_disp_root_oclass, .head.new = nv50_head_new, - .head.scanoutpos = nv50_disp_root_scanoutpos, .outp.internal.crt = nv50_dac_output_new, .outp.internal.tmds = nv50_sor_output_new, .outp.internal.lvds = nv50_sor_output_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c index 67020933f4ff..5c557f3e6c2c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c @@ -23,6 +23,11 @@ */ #include "head.h" +#include <core/client.h> + +#include <nvif/cl0046.h> +#include <nvif/unpack.h> + struct nvkm_head * nvkm_head_find(struct nvkm_disp *disp, int id) { @@ -34,6 +39,44 @@ nvkm_head_find(struct nvkm_disp *disp, int id) return NULL; } +int +nvkm_head_mthd_scanoutpos(struct nvkm_object *object, + struct nvkm_head *head, void *data, u32 size) +{ + union { + struct nv04_disp_scanoutpos_v0 v0; + } *args = data; + int ret = -ENOSYS; + + nvif_ioctl(object, "head scanoutpos size %d\n", size); + if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { + nvif_ioctl(object, "head scanoutpos vers %d\n", + args->v0.version); + + head->func->state(head, &head->arm); + args->v0.vtotal = head->arm.vtotal; + args->v0.vblanks = head->arm.vblanks; + args->v0.vblanke = head->arm.vblanke; + args->v0.htotal = head->arm.htotal; + args->v0.hblanks = head->arm.hblanks; + args->v0.hblanke = head->arm.hblanke; + + /* We don't support reading htotal/vtotal on pre-NV50 VGA, + * so we have to give up and trigger the timestamping + * fallback in the drm core. + */ + if (!args->v0.vtotal || !args->v0.htotal) + return -ENOTSUPP; + + args->v0.time[0] = ktime_to_ns(ktime_get()); + head->func->rgpos(head, &args->v0.hline, &args->v0.vline); + args->v0.time[1] = ktime_to_ns(ktime_get()); + } else + return ret; + + return 0; +} + void nvkm_head_del(struct nvkm_head **phead) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h index 68866a7fba01..94f5cb7596a0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h @@ -8,17 +8,34 @@ struct nvkm_head { int id; struct list_head head; + + struct nvkm_head_state { + u16 htotal; + u16 hsynce; + u16 hblanke; + u16 hblanks; + u16 vtotal; + u16 vsynce; + u16 vblanke; + u16 vblanks; + } arm, asy; }; int nvkm_head_new_(const struct nvkm_head_func *, struct nvkm_disp *, int id); void nvkm_head_del(struct nvkm_head **); +int nvkm_head_mthd_scanoutpos(struct nvkm_object *, + struct nvkm_head *, void *, u32); struct nvkm_head *nvkm_head_find(struct nvkm_disp *, int id); struct nvkm_head_func { + void (*state)(struct nvkm_head *, struct nvkm_head_state *); + void (*rgpos)(struct nvkm_head *, u16 *hline, u16 *vline); void (*vblank_get)(struct nvkm_head *); void (*vblank_put)(struct nvkm_head *); }; +void nv50_head_rgpos(struct nvkm_head *, u16 *, u16 *); + #define HEAD_MSG(h,l,f,a...) do { \ struct nvkm_head *_h = (h); \ nvkm_##l(&_h->disp->engine.subdev, "head-%d: "f"\n", _h->id, ##a); \ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c index 8ac76445b07a..8e7acc57d31d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c @@ -39,8 +39,31 @@ gf119_head_vblank_get(struct nvkm_head *head) nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000001); } +static void +gf119_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = (state == &head->asy) * 0x20000 + head->id * 0x300; + u32 data; + + data = nvkm_rd32(device, 0x640414 + hoff); + state->vtotal = (data & 0xffff0000) >> 16; + state->htotal = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x640418 + hoff); + state->vsynce = (data & 0xffff0000) >> 16; + state->hsynce = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x64041c + hoff); + state->vblanke = (data & 0xffff0000) >> 16; + state->hblanke = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x640420 + hoff); + state->vblanks = (data & 0xffff0000) >> 16; + state->hblanks = (data & 0x0000ffff); +} + static const struct nvkm_head_func gf119_head = { + .state = gf119_head_state, + .rgpos = nv50_head_rgpos, .vblank_get = gf119_head_vblank_get, .vblank_put = gf119_head_vblank_put, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c index d8d6fbef88ae..dcf459282aa1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c @@ -37,8 +37,32 @@ nv04_head_vblank_get(struct nvkm_head *head) nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000001); } +static void +nv04_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + u32 data = nvkm_rd32(device, 0x600868 + (head->id * 0x2000)); + *hline = (data & 0xffff0000) >> 16; + *vline = (data & 0x0000ffff); +} + +static void +nv04_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x0200; + state->vblanks = nvkm_rd32(device, 0x680800 + hoff) & 0x0000ffff; + state->vtotal = nvkm_rd32(device, 0x680804 + hoff) & 0x0000ffff; + state->vblanke = state->vtotal - 1; + state->hblanks = nvkm_rd32(device, 0x680820 + hoff) & 0x0000ffff; + state->htotal = nvkm_rd32(device, 0x680824 + hoff) & 0x0000ffff; + state->hblanke = state->htotal - 1; +} + static const struct nvkm_head_func nv04_head = { + .state = nv04_head_state, + .rgpos = nv04_head_rgpos, .vblank_get = nv04_head_vblank_get, .vblank_put = nv04_head_vblank_put, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c index b3aaa68c0daa..3cccda2cb09e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c @@ -37,8 +37,41 @@ nv50_head_vblank_get(struct nvkm_head *head) nvkm_mask(device, 0x61002c, (4 << head->id), (4 << head->id)); } +void +nv50_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x800; + /* vline read locks hline. */ + *vline = nvkm_rd32(device, 0x616340 + hoff) & 0x0000ffff; + *hline = nvkm_rd32(device, 0x616344 + hoff) & 0x0000ffff; +} + +static void +nv50_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x540 + (state == &head->arm) * 4; + u32 data; + + data = nvkm_rd32(device, 0x610ae8 + hoff); + state->vblanke = (data & 0xffff0000) >> 16; + state->hblanke = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x610af0 + hoff); + state->vblanks = (data & 0xffff0000) >> 16; + state->hblanks = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x610af8 + hoff); + state->vtotal = (data & 0xffff0000) >> 16; + state->htotal = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x610b00 + hoff); + state->vsynce = (data & 0xffff0000) >> 16; + state->hsynce = (data & 0x0000ffff); +} + static const struct nvkm_head_func nv50_head = { + .state = nv50_head_state, + .rgpos = nv50_head_rgpos, .vblank_get = nv50_head_vblank_get, .vblank_put = nv50_head_vblank_put, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c index 6f2314d5dac1..aa7ed87825e5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c @@ -797,7 +797,6 @@ nv50_disp = { .super = nv50_disp_super, .root = &nv50_disp_root_oclass, .head.new = nv50_head_new, - .head.scanoutpos = nv50_disp_root_scanoutpos, .outp.internal.crt = nv50_dac_output_new, .outp.internal.tmds = nv50_sor_output_new, .outp.internal.lvds = nv50_sor_output_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h index 5047e719dc58..42c2dd83fe56 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h @@ -6,7 +6,6 @@ #define NV50_DISP_MTHD_ struct nvkm_object *object, \ struct nv50_disp *disp, void *data, u32 size -#define NV50_DISP_MTHD_V0 NV50_DISP_MTHD_, int head #define NV50_DISP_MTHD_V1 NV50_DISP_MTHD_, int head, struct nvkm_output *outp struct nv50_disp { @@ -29,10 +28,6 @@ struct nv50_disp { struct nv50_disp_chan *chan[17]; }; -int nv50_disp_root_scanoutpos(NV50_DISP_MTHD_V0); - -int gf119_disp_root_scanoutpos(NV50_DISP_MTHD_V0); - int nv50_dac_power(NV50_DISP_MTHD_V1); int nv50_dac_sense(NV50_DISP_MTHD_V1); @@ -76,7 +71,6 @@ struct nv50_disp_func { struct { int (*new)(struct nvkm_disp *, int id); - int (*scanoutpos)(NV50_DISP_MTHD_V0); } head; struct { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c index f1159dd4db87..333c8424b413 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c @@ -25,47 +25,10 @@ #include "head.h" #include "dmacnv50.h" -#include <core/client.h> #include <core/ramht.h> #include <subdev/timer.h> #include <nvif/class.h> -#include <nvif/cl5070.h> -#include <nvif/unpack.h> - -int -gf119_disp_root_scanoutpos(NV50_DISP_MTHD_V0) -{ - struct nvkm_device *device = disp->base.engine.subdev.device; - const u32 total = nvkm_rd32(device, 0x640414 + (head * 0x300)); - const u32 blanke = nvkm_rd32(device, 0x64041c + (head * 0x300)); - const u32 blanks = nvkm_rd32(device, 0x640420 + (head * 0x300)); - union { - struct nv50_disp_scanoutpos_v0 v0; - } *args = data; - int ret = -ENOSYS; - - nvif_ioctl(object, "disp scanoutpos size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "disp scanoutpos vers %d\n", - args->v0.version); - args->v0.vblanke = (blanke & 0xffff0000) >> 16; - args->v0.hblanke = (blanke & 0x0000ffff); - args->v0.vblanks = (blanks & 0xffff0000) >> 16; - args->v0.hblanks = (blanks & 0x0000ffff); - args->v0.vtotal = ( total & 0xffff0000) >> 16; - args->v0.htotal = ( total & 0x0000ffff); - args->v0.time[0] = ktime_to_ns(ktime_get()); - args->v0.vline = /* vline read locks hline */ - nvkm_rd32(device, 0x616340 + (head * 0x800)) & 0xffff; - args->v0.time[1] = ktime_to_ns(ktime_get()); - args->v0.hline = - nvkm_rd32(device, 0x616344 + (head * 0x800)) & 0xffff; - } else - return ret; - - return 0; -} void gf119_disp_root_fini(struct nv50_disp_root *root) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c index f535f43231e2..7f3e2554a83d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c @@ -23,6 +23,7 @@ */ #define nv04_disp_root(p) container_of((p), struct nv04_disp_root, object) #include "priv.h" +#include "head.h" #include <core/client.h> @@ -36,73 +37,30 @@ struct nv04_disp_root { }; static int -nv04_disp_scanoutpos(struct nv04_disp_root *root, - void *data, u32 size, int head) -{ - 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; - } *args = data; - u32 line; - int ret = -ENOSYS; - - nvif_ioctl(object, "disp scanoutpos size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "disp scanoutpos vers %d\n", - args->v0.version); - args->v0.vblanks = nvkm_rd32(device, 0x680800 + hoff) & 0xffff; - args->v0.vtotal = nvkm_rd32(device, 0x680804 + hoff) & 0xffff; - args->v0.vblanke = args->v0.vtotal - 1; - - args->v0.hblanks = nvkm_rd32(device, 0x680820 + hoff) & 0xffff; - args->v0.htotal = nvkm_rd32(device, 0x680824 + hoff) & 0xffff; - args->v0.hblanke = args->v0.htotal - 1; - - /* - * If output is vga instead of digital then vtotal/htotal is - * invalid so we have to give up and trigger the timestamping - * fallback in the drm core. - */ - if (!args->v0.vtotal || !args->v0.htotal) - return -ENOTSUPP; - - args->v0.time[0] = ktime_to_ns(ktime_get()); - line = nvkm_rd32(device, 0x600868 + hoff); - args->v0.time[1] = ktime_to_ns(ktime_get()); - args->v0.hline = (line & 0xffff0000) >> 16; - args->v0.vline = (line & 0x0000ffff); - } else - return ret; - - return 0; -} - -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; - int head, ret = -ENOSYS; + struct nvkm_head *head; + int id, ret = -ENOSYS; nvif_ioctl(object, "disp mthd size %d\n", size); if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { nvif_ioctl(object, "disp mthd vers %d mthd %02x head %d\n", args->v0.version, args->v0.method, args->v0.head); mthd = args->v0.method; - head = args->v0.head; + id = args->v0.head; } else return ret; - if (head < 0 || head >= 2) + if (!(head = nvkm_head_find(root->disp, id))) return -ENXIO; switch (mthd) { case NV04_DISP_SCANOUTPOS: - return nv04_disp_scanoutpos(root, data, size, head); + return nvkm_head_mthd_scanoutpos(object, head, data, size); default: break; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c index b5df4e8ddbfd..609bfae9acbb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -33,40 +33,6 @@ #include <nvif/cl5070.h> #include <nvif/unpack.h> -int -nv50_disp_root_scanoutpos(NV50_DISP_MTHD_V0) -{ - struct nvkm_device *device = disp->base.engine.subdev.device; - const u32 blanke = nvkm_rd32(device, 0x610aec + (head * 0x540)); - const u32 blanks = nvkm_rd32(device, 0x610af4 + (head * 0x540)); - const u32 total = nvkm_rd32(device, 0x610afc + (head * 0x540)); - union { - struct nv50_disp_scanoutpos_v0 v0; - } *args = data; - int ret = -ENOSYS; - - nvif_ioctl(object, "disp scanoutpos size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "disp scanoutpos vers %d\n", - args->v0.version); - args->v0.vblanke = (blanke & 0xffff0000) >> 16; - args->v0.hblanke = (blanke & 0x0000ffff); - args->v0.vblanks = (blanks & 0xffff0000) >> 16; - args->v0.hblanks = (blanks & 0x0000ffff); - args->v0.vtotal = ( total & 0xffff0000) >> 16; - args->v0.htotal = ( total & 0x0000ffff); - args->v0.time[0] = ktime_to_ns(ktime_get()); - args->v0.vline = /* vline read locks hline */ - nvkm_rd32(device, 0x616340 + (head * 0x800)) & 0xffff; - args->v0.time[1] = ktime_to_ns(ktime_get()); - args->v0.hline = - nvkm_rd32(device, 0x616344 + (head * 0x800)) & 0xffff; - } else - return ret; - - return 0; -} - static int nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) { @@ -78,8 +44,9 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) struct nv50_disp *disp = root->disp; const struct nv50_disp_func *func = disp->func; struct nvkm_outp *temp, *outp = NULL; + struct nvkm_head *head; u16 type, mask = 0; - int head, ret = -ENOSYS; + int hidx, ret = -ENOSYS; if (mthd != NV50_DISP_MTHD) return -EINVAL; @@ -89,7 +56,7 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) nvif_ioctl(object, "disp mthd vers %d mthd %02x head %d\n", args->v0.version, args->v0.method, args->v0.head); mthd = args->v0.method; - head = args->v0.head; + hidx = args->v0.head; } else if (!(ret = nvif_unpack(ret, &data, &size, args->v1, 1, 1, true))) { nvif_ioctl(object, "disp mthd vers %d mthd %02x " @@ -99,11 +66,11 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) mthd = args->v1.method; type = args->v1.hasht; mask = args->v1.hashm; - head = ffs((mask >> 8) & 0x0f) - 1; + hidx = ffs((mask >> 8) & 0x0f) - 1; } else return ret; - if (!nvkm_head_find(&disp->base, head)) + if (!(head = nvkm_head_find(&disp->base, hidx))) return -ENXIO; if (mask) { @@ -119,27 +86,28 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) } switch (mthd) { - case NV50_DISP_SCANOUTPOS: - return func->head.scanoutpos(object, disp, data, size, head); + case NV50_DISP_SCANOUTPOS: { + return nvkm_head_mthd_scanoutpos(object, head, data, size); + } default: break; } switch (mthd * !!outp) { case NV50_DISP_MTHD_V1_DAC_PWR: - return func->dac.power(object, disp, data, size, head, outp); + return func->dac.power(object, disp, data, size, hidx, outp); case NV50_DISP_MTHD_V1_DAC_LOAD: - return func->dac.sense(object, disp, data, size, head, outp); + return func->dac.sense(object, disp, data, size, hidx, outp); case NV50_DISP_MTHD_V1_SOR_PWR: - return func->sor.power(object, disp, data, size, head, outp); + return func->sor.power(object, disp, data, size, hidx, outp); case NV50_DISP_MTHD_V1_SOR_HDA_ELD: if (!func->sor.hda_eld) return -ENODEV; - return func->sor.hda_eld(object, disp, data, size, head, outp); + return func->sor.hda_eld(object, disp, data, size, hidx, outp); case NV50_DISP_MTHD_V1_SOR_HDMI_PWR: if (!func->sor.hdmi) return -ENODEV; - return func->sor.hdmi(object, disp, data, size, head, outp); + return func->sor.hdmi(object, disp, data, size, hidx, outp); case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT: { union { struct nv50_disp_sor_lvds_script_v0 v0; @@ -215,7 +183,7 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) args->v0.aligned_pbn); if (!outpdp->func->vcpi) return -ENODEV; - outpdp->func->vcpi(outpdp, head, args->v0.start_slot, + outpdp->func->vcpi(outpdp, hidx, args->v0.start_slot, args->v0.num_slots, args->v0.pbn, args->v0.aligned_pbn); return 0; @@ -226,7 +194,7 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) case NV50_DISP_MTHD_V1_PIOR_PWR: if (!func->pior.power) return -ENODEV; - return func->pior.power(object, disp, data, size, head, outp); + return func->pior.power(object, disp, data, size, hidx, outp); default: break; } |