Commit 9d9740f099f2eaf309c4c9cbc0d732507140db28

Authored by Paulo Zanoni
Committed by Daniel Vetter
1 parent c30b611090

drm/i915: add some barriers when changing DIPs

On IVB and older, we basically have two registers: the control and the
data register. We write a few consecutitve times to the control
register, and we need these writes to arrive exactly in the specified
order.

Also, when we're changing the data register, we need to guarantee that
anything written to the control register already arrived (since
changing the control register can change where the data register
points to). Also, we need to make sure all the writes to the data
register happen exactly in the specified order, and we also *can't*
read the data register during this process, since reading and/or
writing it will change the place it points to.

So invoke the "better safe than sorry" rule and just be careful and
put barriers everywhere :)

On HSW we still have a control register that we write many times, but
we have many data registers.

Demanded-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Showing 1 changed file with 27 additions and 0 deletions Side-by-side Diff

drivers/gpu/drm/i915/intel_hdmi.c
... ... @@ -133,16 +133,19 @@
133 133  
134 134 I915_WRITE(VIDEO_DIP_CTL, val);
135 135  
  136 + mmiowb();
136 137 for (i = 0; i < len; i += 4) {
137 138 I915_WRITE(VIDEO_DIP_DATA, *data);
138 139 data++;
139 140 }
  141 + mmiowb();
140 142  
141 143 val |= g4x_infoframe_enable(frame);
142 144 val &= ~VIDEO_DIP_FREQ_MASK;
143 145 val |= VIDEO_DIP_FREQ_VSYNC;
144 146  
145 147 I915_WRITE(VIDEO_DIP_CTL, val);
  148 + POSTING_READ(VIDEO_DIP_CTL);
146 149 }
147 150  
148 151 static void ibx_write_infoframe(struct drm_encoder *encoder,
149 152  
150 153  
... ... @@ -165,16 +168,19 @@
165 168  
166 169 I915_WRITE(reg, val);
167 170  
  171 + mmiowb();
168 172 for (i = 0; i < len; i += 4) {
169 173 I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
170 174 data++;
171 175 }
  176 + mmiowb();
172 177  
173 178 val |= g4x_infoframe_enable(frame);
174 179 val &= ~VIDEO_DIP_FREQ_MASK;
175 180 val |= VIDEO_DIP_FREQ_VSYNC;
176 181  
177 182 I915_WRITE(reg, val);
  183 + POSTING_READ(reg);
178 184 }
179 185  
180 186 static void cpt_write_infoframe(struct drm_encoder *encoder,
181 187  
182 188  
... ... @@ -200,16 +206,19 @@
200 206  
201 207 I915_WRITE(reg, val);
202 208  
  209 + mmiowb();
203 210 for (i = 0; i < len; i += 4) {
204 211 I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
205 212 data++;
206 213 }
  214 + mmiowb();
207 215  
208 216 val |= g4x_infoframe_enable(frame);
209 217 val &= ~VIDEO_DIP_FREQ_MASK;
210 218 val |= VIDEO_DIP_FREQ_VSYNC;
211 219  
212 220 I915_WRITE(reg, val);
  221 + POSTING_READ(reg);
213 222 }
214 223  
215 224 static void vlv_write_infoframe(struct drm_encoder *encoder,
216 225  
217 226  
... ... @@ -232,16 +241,19 @@
232 241  
233 242 I915_WRITE(reg, val);
234 243  
  244 + mmiowb();
235 245 for (i = 0; i < len; i += 4) {
236 246 I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
237 247 data++;
238 248 }
  249 + mmiowb();
239 250  
240 251 val |= g4x_infoframe_enable(frame);
241 252 val &= ~VIDEO_DIP_FREQ_MASK;
242 253 val |= VIDEO_DIP_FREQ_VSYNC;
243 254  
244 255 I915_WRITE(reg, val);
  256 + POSTING_READ(reg);
245 257 }
246 258  
247 259 static void hsw_write_infoframe(struct drm_encoder *encoder,
248 260  
249 261  
... ... @@ -262,13 +274,16 @@
262 274 val &= ~hsw_infoframe_enable(frame);
263 275 I915_WRITE(ctl_reg, val);
264 276  
  277 + mmiowb();
265 278 for (i = 0; i < len; i += 4) {
266 279 I915_WRITE(data_reg + i, *data);
267 280 data++;
268 281 }
  282 + mmiowb();
269 283  
270 284 val |= hsw_infoframe_enable(frame);
271 285 I915_WRITE(ctl_reg, val);
  286 + POSTING_READ(ctl_reg);
272 287 }
273 288  
274 289 static void intel_set_infoframe(struct drm_encoder *encoder,
... ... @@ -335,6 +350,7 @@
335 350 return;
336 351 val &= ~VIDEO_DIP_ENABLE;
337 352 I915_WRITE(reg, val);
  353 + POSTING_READ(reg);
338 354 return;
339 355 }
340 356  
... ... @@ -353,6 +369,7 @@
353 369 if (val & VIDEO_DIP_ENABLE) {
354 370 val &= ~VIDEO_DIP_ENABLE;
355 371 I915_WRITE(reg, val);
  372 + POSTING_READ(reg);
356 373 }
357 374 val &= ~VIDEO_DIP_PORT_MASK;
358 375 val |= port;
... ... @@ -362,6 +379,7 @@
362 379 val &= ~VIDEO_DIP_ENABLE_VENDOR;
363 380  
364 381 I915_WRITE(reg, val);
  382 + POSTING_READ(reg);
365 383  
366 384 intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
367 385 intel_hdmi_set_spd_infoframe(encoder);
... ... @@ -385,6 +403,7 @@
385 403 return;
386 404 val &= ~VIDEO_DIP_ENABLE;
387 405 I915_WRITE(reg, val);
  406 + POSTING_READ(reg);
388 407 return;
389 408 }
390 409  
... ... @@ -406,6 +425,7 @@
406 425 if (val & VIDEO_DIP_ENABLE) {
407 426 val &= ~VIDEO_DIP_ENABLE;
408 427 I915_WRITE(reg, val);
  428 + POSTING_READ(reg);
409 429 }
410 430 val &= ~VIDEO_DIP_PORT_MASK;
411 431 val |= port;
... ... @@ -416,6 +436,7 @@
416 436 VIDEO_DIP_ENABLE_GCP);
417 437  
418 438 I915_WRITE(reg, val);
  439 + POSTING_READ(reg);
419 440  
420 441 intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
421 442 intel_hdmi_set_spd_infoframe(encoder);
... ... @@ -438,6 +459,7 @@
438 459 return;
439 460 val &= ~(VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI);
440 461 I915_WRITE(reg, val);
  462 + POSTING_READ(reg);
441 463 return;
442 464 }
443 465  
... ... @@ -447,6 +469,7 @@
447 469 VIDEO_DIP_ENABLE_GCP);
448 470  
449 471 I915_WRITE(reg, val);
  472 + POSTING_READ(reg);
450 473  
451 474 intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
452 475 intel_hdmi_set_spd_infoframe(encoder);
... ... @@ -469,6 +492,7 @@
469 492 return;
470 493 val &= ~VIDEO_DIP_ENABLE;
471 494 I915_WRITE(reg, val);
  495 + POSTING_READ(reg);
472 496 return;
473 497 }
474 498  
... ... @@ -477,6 +501,7 @@
477 501 VIDEO_DIP_ENABLE_GCP);
478 502  
479 503 I915_WRITE(reg, val);
  504 + POSTING_READ(reg);
480 505  
481 506 intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
482 507 intel_hdmi_set_spd_infoframe(encoder);
... ... @@ -493,6 +518,7 @@
493 518  
494 519 if (!intel_hdmi->has_hdmi_sink) {
495 520 I915_WRITE(reg, 0);
  521 + POSTING_READ(reg);
496 522 return;
497 523 }
498 524  
... ... @@ -500,6 +526,7 @@
500 526 VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW);
501 527  
502 528 I915_WRITE(reg, val);
  529 + POSTING_READ(reg);
503 530  
504 531 intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
505 532 intel_hdmi_set_spd_infoframe(encoder);