From 8ff8eb2b38dc705f5c86f524c1cd74a811a7b04c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 9 Sep 2013 16:23:04 +0100 Subject: [PATCH] sna/hsw: Scanline waits require both DERRMR and forcewake Oh my, bspec is missing a few details on how to perform a scanline wait on Haswell. But by using the extra steps required for Ivybridge, we can successfully send events from the scanout to the BCS ring. Sadly this again means that to use vsync on Haswell requires preventing the GPU from sleeping whilst it waits for the scanout to advance. Reported-by: Dan Doel Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=69119 Signed-off-by: Chris Wilson --- src/sna/sna_display.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 78aa09ac..1d1022e0 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -3381,6 +3381,8 @@ sna_covering_crtc(struct sna *sna, const BoxRec *box, xf86CrtcPtr desired) return best_crtc; } +#define MI_LOAD_REGISTER_IMM (0x22<<23) + static bool sna_emit_wait_for_scanline_hsw(struct sna *sna, xf86CrtcPtr crtc, int pipe, int y1, int y2, @@ -3389,8 +3391,25 @@ static bool sna_emit_wait_for_scanline_hsw(struct sna *sna, uint32_t event; uint32_t *b; + if (!sna->kgem.has_secure_batches) + return false; + b = kgem_get_batch(&sna->kgem); - sna->kgem.nbatch += 5; + sna->kgem.nbatch += 17; + + switch (pipe) { + default: assert(0); + case 0: event = 1 << 0; break; + case 1: event = 1 << 8; break; + case 2: event = 1 << 14; break; + } + + b[0] = MI_LOAD_REGISTER_IMM | 1; + b[1] = 0x44050; /* DERRMR */ + b[2] = ~event; + b[3] = MI_LOAD_REGISTER_IMM | 1; + b[4] = 0xa188; /* FORCEWAKE_MT */ + b[5] = 2 << 16 | 2; /* The documentation says that the LOAD_SCAN_LINES command * always comes in pairs. Don't ask me why. */ @@ -3400,8 +3419,8 @@ static bool sna_emit_wait_for_scanline_hsw(struct sna *sna, case 1: event = 1 << 19; break; case 2: event = 4 << 19; break; } - b[2] = b[0] = MI_LOAD_SCAN_LINES_INCL | event; - b[3] = b[1] = (y1 << 16) | (y2-1); + b[8] = b[6] = MI_LOAD_SCAN_LINES_INCL | event; + b[9] = b[7] = (y1 << 16) | (y2-1); switch (pipe) { default: assert(0); @@ -3409,13 +3428,18 @@ static bool sna_emit_wait_for_scanline_hsw(struct sna *sna, case 1: event = 1 << 8; break; case 2: event = 1 << 14; break; } - b[4] = MI_WAIT_FOR_EVENT | event; + b[10] = MI_WAIT_FOR_EVENT | event; + + b[11] = MI_LOAD_REGISTER_IMM | 1; + b[12] = 0xa188; /* FORCEWAKE_MT */ + b[13] = 2 << 16; + b[14] = MI_LOAD_REGISTER_IMM | 1; + b[15] = 0x44050; /* DERRMR */ + b[16] = ~0; return true; } -#define MI_LOAD_REGISTER_IMM (0x22<<23) - static bool sna_emit_wait_for_scanline_ivb(struct sna *sna, xf86CrtcPtr crtc, int pipe, int y1, int y2,