]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
drm/nouveau/disp: common implementation of scanoutpos method in nvkm_head
authorBen Skeggs <bskeggs@redhat.com>
Fri, 19 May 2017 13:59:35 +0000 (23:59 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 16 Jun 2017 04:04:48 +0000 (14:04 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
21 files changed:
drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c

index 1b74072e28fedcb535bf90d23a2d686418ef1e04..bdaec4e4cb60ba0bdcbe55bc55919f5b055697c4 100644 (file)
@@ -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,
index 38a5d165c11c0aa95feeb4a863a8ce8ee878e8a2..12e4984e5393c81e8ceb87beb7db2bddde677b49 100644 (file)
@@ -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,
index e9cf53e918afe4e31a9215b6c75085e4ff6f16d2..d353d29f2ad439aa7337aaf2b417a8d141124798 100644 (file)
@@ -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,
index 3dd530298a288565bf48759c8fdff8b029002f8f..a83684c2c129851e780e8d49ff8ffc636186e054 100644 (file)
@@ -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,
index 8c4cabec036d1ae490d6555604aa77131969697a..72a2fc0183b3ae50819eddfbbb25f71bfffbf831 100644 (file)
@@ -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,
index dfb32c14558e227c3edcacb7f1817f083f77be21..b6658e22b207fb17b93a48ccfec880a47607201f 100644 (file)
@@ -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,
index 97ca9434e1f3bbf8a62bb79c14a5167fcaebd82a..e0ea05350dfb2bdc7f59238621be3fc737865800 100644 (file)
@@ -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,
index e0d5ed423f1972c59ffce2f123cd165fac6d64b6..90ea05f98699b116c6f54acc9874e50cdd86002d 100644 (file)
@@ -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,
index 56eeee4dd63439b4b3654378fd869bdfcb5093a3..722a057bc9ff29dca93cef7372eb0b9bec2d64c4 100644 (file)
@@ -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,
index fa8eea41dfa2b74e5a168167600132a8fe0424ea..a5710ea0b244167499a3a10c98d4e69d02da7cc1 100644 (file)
@@ -32,7 +32,6 @@ gt200_disp = {
        .super = nv50_disp_super,
        .root = &gt200_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,
index b211757910e21023dfda70dbfe8326a8d3fcb616..3c100fc617a64773b3e6e412372f55b5c0f74268 100644 (file)
@@ -32,7 +32,6 @@ gt215_disp = {
        .super = nv50_disp_super,
        .root = &gt215_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,
index 67020933f4ff65649f01a9d0db68ebf6aa7c0e79..5c557f3e6c2cd0feb92ebb4ac8250ef43a2bbad2 100644 (file)
  */
 #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)
 {
index 68866a7fba013179ccd1cc810f210d079c0d6d9c..94f5cb7596a04f68d315ece9b303b6926d0a122e 100644 (file)
@@ -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);     \
index 8ac76445b07a5dced4bc7691ce94149527bfe51f..8e7acc57d31de7e100f81532050129c9f6f72dee 100644 (file)
@@ -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,
 };
index d8d6fbef88ae4bb7fbd0649f8a3325e3e5190ce8..dcf459282aa12126c58b34b65c05c201fb382ec8 100644 (file)
@@ -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,
 };
index b3aaa68c0daac6aa64a38c473b2056130d4323ea..3cccda2cb09ec628def23ab0aa006af9220f7bd0 100644 (file)
@@ -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,
 };
index 6f2314d5dac11160ca4cab428ff7e66fd855ebed..aa7ed87825e51a28f7f6b1c8ca4d979ea257e41b 100644 (file)
@@ -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,
index 5047e719dc58c7d79c9b712c31b54c8fe504de92..42c2dd83fe569033c5ab28b8964df2fdf287ee68 100644 (file)
@@ -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 {
index f1159dd4db87ac1602973e60b457927d1f941c05..333c8424b413c1ab16919996df08051d20657584 100644 (file)
 #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)
index f535f43231e2ac9815d89f95ca2c5681ee053ecb..7f3e2554a83d104e79c197af9fbb5fb81d578438 100644 (file)
@@ -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>
 
@@ -35,50 +36,6 @@ struct nv04_disp_root {
        struct nvkm_disp *disp;
 };
 
-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)
 {
@@ -86,23 +43,24 @@ nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
        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;
        }
index b5df4e8ddbfd206f227412d871eabc5582375553..609bfae9acbb70fc584ec59a61c236baaaa901e1 100644 (file)
 #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;
        }