diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c | 43 |
1 files changed, 43 insertions, 0 deletions
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) { |