diff options
author | Roy Spliet <rspliet@eclipso.eu> | 2015-09-30 02:23:51 +0300 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2015-11-03 08:02:18 +0300 |
commit | 271c27665c2d2f719a2fca6a3530a82984f22cca (patch) | |
tree | df6a58d0c215da5ef7136f989fbc31f8554960e5 /drivers/gpu/drm/nouveau/nvkm/subdev/bus | |
parent | 4d9faafa0fdda2f4ba04b5cdffc0af1bab2312f4 (diff) | |
download | linux-271c27665c2d2f719a2fca6a3530a82984f22cca.tar.xz |
drm/nouveau/bus/hwsq: Implement VBLANK waiting heuristic
Avoids waiting for VBLANKS that never arrive on headless or otherwise
unconventional set-ups. Strategy taken from MEMX.
Signed-off-by: Roy Spliet <rspliet@eclipso.eu>
Tested-by: Pierre Moreau <pierre.morrow@free.fr>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/bus')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h | 6 |
2 files changed, 38 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; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h index 8117ec5a1468..54ec3b131dfd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h @@ -134,6 +134,12 @@ hwsq_wait(struct hwsq *ram, u8 flag, u8 data) } static inline void +hwsq_wait_vblank(struct hwsq *ram) +{ + nvkm_hwsq_wait_vblank(ram->hwsq); +} + +static inline void hwsq_nsec(struct hwsq *ram, u32 nsec) { nvkm_hwsq_nsec(ram->hwsq, nsec); |