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 <dan.doel@gmail.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=69119
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2013-09-09 16:23:04 +01:00
parent dbe7598245
commit 8ff8eb2b38
1 changed files with 30 additions and 6 deletions

View File

@ -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,