|
@@ -131,6 +131,38 @@ nvkm_hwsq_wait(struct nvkm_hwsq *hwsq, u8 flag, u8 data)
|
|
hwsq_cmd(hwsq, 3, (u8[]){ 0x5f, flag, data });
|
|
hwsq_cmd(hwsq, 3, (u8[]){ 0x5f, flag, 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
|
|
void
|
|
nvkm_hwsq_nsec(struct nvkm_hwsq *hwsq, u32 nsec)
|
|
nvkm_hwsq_nsec(struct nvkm_hwsq *hwsq, u32 nsec)
|
|
{
|
|
{
|