diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c | 54 |
1 files changed, 6 insertions, 48 deletions
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; } |