aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c
index 79f1cf513b36..2a5668938f2f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c
@@ -132,6 +132,38 @@ nvkm_hwsq_wait(struct nvkm_hwsq *hwsq, u8 flag, u8 data)
}
void
+nvkm_hwsq_wait_vblank(struct nvkm_hwsq *hwsq)
+{
+ struct nvkm_subdev *subdev = hwsq->subdev;
+ struct nvkm_device *device = subdev->device;
+ u32 heads, x, y, px = 0;
+ int i, head_sync;
+
+ heads = nvkm_rd32(device, 0x610050);
+ for (i = 0; i < 2; i++) {
+ /* Heuristic: sync to head with biggest resolution */
+ if (heads & (2 << (i << 3))) {
+ x = nvkm_rd32(device, 0x610b40 + (0x540 * i));
+ y = (x & 0xffff0000) >> 16;
+ x &= 0x0000ffff;
+ if ((x * y) > px) {
+ px = (x * y);
+ head_sync = i;
+ }
+ }
+ }
+
+ if (px == 0) {
+ nvkm_debug(subdev, "WAIT VBLANK !NO ACTIVE HEAD\n");
+ return;
+ }
+
+ nvkm_debug(subdev, "WAIT VBLANK HEAD%d\n", head_sync);
+ nvkm_hwsq_wait(hwsq, head_sync ? 0x3 : 0x1, 0x0);
+ nvkm_hwsq_wait(hwsq, head_sync ? 0x3 : 0x1, 0x1);
+}
+
+void
nvkm_hwsq_nsec(struct nvkm_hwsq *hwsq, u32 nsec)
{
u8 shift = 0, usec = nsec / 1000;