aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_hdmi.c
diff options
context:
space:
mode:
authorDamien Lespiau <damien.lespiau@intel.com>2013-08-06 15:32:19 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-08-08 08:04:48 -0400
commit5adaea799c1c2c00a1ffe995255af25717029b65 (patch)
treeb81ebf5d4264dbb858e1f1c81072fd65c70adba6 /drivers/gpu/drm/i915/intel_hdmi.c
parent178f736ab96637bc17bcf00c3b58af0137e880e0 (diff)
drm/i915/hdmi: Port the infoframe code to the common hdmi helpers
Let's use the drivers/video/hmdi.c and drm infoframe helpers to build our infoframes. v2: Simplify the logic to compute the buffer size. We can just take the maximum infoframe size rounded to 32, which happens to be what the hardware let us write anyway. v3: Remove unnecessary memset() (Ville Syrjälä) Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_hdmi.c')
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c82
1 files changed, 58 insertions, 24 deletions
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 951f4817e1b6..84e57c74a8d5 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -325,14 +325,43 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
325 POSTING_READ(ctl_reg); 325 POSTING_READ(ctl_reg);
326} 326}
327 327
328/*
329 * The data we write to the DIP data buffer registers is 1 byte bigger than the
330 * HDMI infoframe size because of an ECC/reserved byte at position 3 (starting
331 * at 0). It's also a byte used by DisplayPort so the same DIP registers can be
332 * used for both technologies.
333 *
334 * DW0: Reserved/ECC/DP | HB2 | HB1 | HB0
335 * DW1: DB3 | DB2 | DB1 | DB0
336 * DW2: DB7 | DB6 | DB5 | DB4
337 * DW3: ...
338 *
339 * (HB is Header Byte, DB is Data Byte)
340 *
341 * The hdmi pack() functions don't know about that hardware specific hole so we
342 * trick them by giving an offset into the buffer and moving back the header
343 * bytes by one.
344 */
328static void intel_set_infoframe(struct drm_encoder *encoder, 345static void intel_set_infoframe(struct drm_encoder *encoder,
329 struct dip_infoframe *frame) 346 union hdmi_infoframe *frame)
330{ 347{
331 struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); 348 struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
349 uint8_t buffer[VIDEO_DIP_DATA_SIZE];
350 ssize_t len;
332 351
333 intel_dip_infoframe_csum(frame); 352 /* see comment above for the reason for this offset */
334 intel_hdmi->write_infoframe(encoder, frame->type, (uint8_t *)frame, 353 len = hdmi_infoframe_pack(frame, buffer + 1, sizeof(buffer) - 1);
335 DIP_HEADER_SIZE + frame->len); 354 if (len < 0)
355 return;
356
357 /* Insert the 'hole' (see big comment above) at position 3 */
358 buffer[0] = buffer[1];
359 buffer[1] = buffer[2];
360 buffer[2] = buffer[3];
361 buffer[3] = 0;
362 len++;
363
364 intel_hdmi->write_infoframe(encoder, frame->any.type, buffer, len);
336} 365}
337 366
338static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, 367static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
@@ -340,40 +369,45 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
340{ 369{
341 struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); 370 struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
342 struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); 371 struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
343 struct dip_infoframe avi_if = { 372 union hdmi_infoframe frame;
344 .type = DIP_TYPE_AVI, 373 int ret;
345 .ver = DIP_VERSION_AVI, 374
346 .len = DIP_LEN_AVI, 375 ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
347 }; 376 adjusted_mode);
377 if (ret < 0) {
378 DRM_ERROR("couldn't fill AVI infoframe\n");
379 return;
380 }
348 381
349 if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) 382 if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
350 avi_if.body.avi.YQ_CN_PR |= DIP_AVI_PR_2; 383 frame.avi.pixel_repeat = 1;
351 384
352 if (intel_hdmi->rgb_quant_range_selectable) { 385 if (intel_hdmi->rgb_quant_range_selectable) {
353 if (intel_crtc->config.limited_color_range) 386 if (intel_crtc->config.limited_color_range)
354 avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_LIMITED; 387 frame.avi.quantization_range =
388 HDMI_QUANTIZATION_RANGE_LIMITED;
355 else 389 else
356 avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_FULL; 390 frame.avi.quantization_range =
391 HDMI_QUANTIZATION_RANGE_FULL;
357 } 392 }
358 393
359 avi_if.body.avi.VIC = drm_match_cea_mode(adjusted_mode); 394 intel_set_infoframe(encoder, &frame);
360
361 intel_set_infoframe(encoder, &avi_if);
362} 395}
363 396
364static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) 397static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
365{ 398{
366 struct dip_infoframe spd_if; 399 union hdmi_infoframe frame;
400 int ret;
401
402 ret = hdmi_spd_infoframe_init(&frame.spd, "Intel", "Integrated gfx");
403 if (ret < 0) {
404 DRM_ERROR("couldn't fill SPD infoframe\n");
405 return;
406 }
367 407
368 memset(&spd_if, 0, sizeof(spd_if)); 408 frame.spd.sdi = HDMI_SPD_SDI_PC;
369 spd_if.type = DIP_TYPE_SPD;
370 spd_if.ver = DIP_VERSION_SPD;
371 spd_if.len = DIP_LEN_SPD;
372 strcpy(spd_if.body.spd.vn, "Intel");
373 strcpy(spd_if.body.spd.pd, "Integrated gfx");
374 spd_if.body.spd.sdi = DIP_SPD_PC;
375 409
376 intel_set_infoframe(encoder, &spd_if); 410 intel_set_infoframe(encoder, &frame);
377} 411}
378 412
379static void g4x_set_infoframes(struct drm_encoder *encoder, 413static void g4x_set_infoframes(struct drm_encoder *encoder,