Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: handle HDMI 2.0 VICs in AVI info-frames

HDMI 1.4b support the CEA video modes as per range of CEA-861-D (VIC 1-64).
For any other mode, the VIC filed in AVI infoframes should be 0.
HDMI 2.0 sinks, support video modes range as per CEA-861-F spec, which is
extended to (VIC 1-107).

This patch adds a bool input variable, which indicates if the connected
sink is a HDMI 2.0 sink or not. This will make sure that we don't pass a
HDMI 2.0 VIC to a HDMI 1.4 sink.

This patch touches all drm drivers, who are callers of this function
drm_hdmi_avi_infoframe_from_display_mode but to make sure there is
no change in current behavior, is_hdmi2 is kept as false.

In case of I915 driver, this patch:
- checks if the connected display is HDMI 2.0.
- HDMI infoframes carry one of this two type of information:
- VIC for 4K modes for HDMI 1.4 sinks
- S3D information for S3D modes
As CEA-861-F has already defined VICs for 4K videomodes, this
patch doesn't allow sending HDMI infoframes for HDMI 2.0 sinks,
until the mode is 3D.

Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Jose Abreu <jose.abreu@synopsys.com>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Daniel Vetter <daniel.vetter@intel.com>

PS: This patch touches a few lines in few files, which were
already above 80 char, so checkpatch gives 80 char warning again.
- gpu/drm/omapdrm/omap_encoder.c
- gpu/drm/i915/intel_sdvo.c

V2: Rebase, Added r-b from Andrzej
V3: Addressed review comment from Ville:
- Do not send VICs in both AVI-IF and HDMI-IF
send only one of it.
V4: Rebase
V5: Added r-b from Neil.
Addressed review comments from Ville
- Do not block HDMI vendor IF, instead check for VIC while
handling AVI infoframes
V6: Rebase
V7: Rebase

Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1499960000-9232-2-git-send-email-shashank.sharma@intel.com
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

authored by

Shashank Sharma and committed by
Ville Syrjälä
0c1f528c 3589211e

+57 -25
+1 -1
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
··· 1867 1867 dce_v10_0_audio_write_sad_regs(encoder); 1868 1868 dce_v10_0_audio_write_latency_fields(encoder, mode); 1869 1869 1870 - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); 1870 + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); 1871 1871 if (err < 0) { 1872 1872 DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); 1873 1873 return;
+1 -1
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
··· 1851 1851 dce_v11_0_audio_write_sad_regs(encoder); 1852 1852 dce_v11_0_audio_write_latency_fields(encoder, mode); 1853 1853 1854 - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); 1854 + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); 1855 1855 if (err < 0) { 1856 1856 DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); 1857 1857 return;
+1 -1
drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
··· 1597 1597 ssize_t err; 1598 1598 u32 tmp; 1599 1599 1600 - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); 1600 + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); 1601 1601 if (err < 0) { 1602 1602 DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); 1603 1603 return;
+1 -1
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
··· 1750 1750 dce_v8_0_audio_write_sad_regs(encoder); 1751 1751 dce_v8_0_audio_write_latency_fields(encoder, mode); 1752 1752 1753 - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); 1753 + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); 1754 1754 if (err < 0) { 1755 1755 DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); 1756 1756 return;
+2 -1
drivers/gpu/drm/bridge/analogix-anx78xx.c
··· 1097 1097 1098 1098 mutex_lock(&anx78xx->lock); 1099 1099 1100 - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode); 1100 + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode, 1101 + false); 1101 1102 if (err) { 1102 1103 DRM_ERROR("Failed to setup AVI infoframe: %d\n", err); 1103 1104 goto unlock;
+1 -1
drivers/gpu/drm/bridge/sii902x.c
··· 269 269 if (ret) 270 270 return; 271 271 272 - ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj); 272 + ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj, false); 273 273 if (ret < 0) { 274 274 DRM_ERROR("couldn't fill AVI infoframe\n"); 275 275 return;
+1 -1
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
··· 1317 1317 u8 val; 1318 1318 1319 1319 /* Initialise info frame from DRM mode */ 1320 - drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); 1320 + drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); 1321 1321 1322 1322 if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) 1323 1323 frame.colorspace = HDMI_COLORSPACE_YUV444;
+25 -1
drivers/gpu/drm/drm_edid.c
··· 4334 4334 * data from a DRM display mode 4335 4335 * @frame: HDMI AVI infoframe 4336 4336 * @mode: DRM display mode 4337 + * @is_hdmi2_sink: Sink is HDMI 2.0 compliant 4337 4338 * 4338 4339 * Return: 0 on success or a negative error code on failure. 4339 4340 */ 4340 4341 int 4341 4342 drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, 4342 - const struct drm_display_mode *mode) 4343 + const struct drm_display_mode *mode, 4344 + bool is_hdmi2_sink) 4343 4345 { 4344 4346 int err; 4345 4347 ··· 4356 4354 frame->pixel_repeat = 1; 4357 4355 4358 4356 frame->video_code = drm_match_cea_mode(mode); 4357 + 4358 + /* 4359 + * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but 4360 + * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we 4361 + * have to make sure we dont break HDMI 1.4 sinks. 4362 + */ 4363 + if (!is_hdmi2_sink && frame->video_code > 64) 4364 + frame->video_code = 0; 4365 + 4366 + /* 4367 + * HDMI spec says if a mode is found in HDMI 1.4b 4K modes 4368 + * we should send its VIC in vendor infoframes, else send the 4369 + * VIC in AVI infoframes. Lets check if this mode is present in 4370 + * HDMI 1.4b 4K modes 4371 + */ 4372 + if (frame->video_code) { 4373 + u8 vendor_if_vic = drm_match_hdmi_mode(mode); 4374 + bool is_s3d = mode->flags & DRM_MODE_FLAG_3D_MASK; 4375 + 4376 + if (drm_valid_hdmi_vic(vendor_if_vic) && !is_s3d) 4377 + frame->video_code = 0; 4378 + } 4359 4379 4360 4380 frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE; 4361 4381
+1 -1
drivers/gpu/drm/exynos/exynos_hdmi.c
··· 784 784 } 785 785 786 786 ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi, 787 - &hdata->current_mode); 787 + &hdata->current_mode, false); 788 788 if (!ret) 789 789 ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf)); 790 790 if (ret > 0) {
+1 -1
drivers/gpu/drm/i2c/tda998x_drv.c
··· 712 712 { 713 713 union hdmi_infoframe frame; 714 714 715 - drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); 715 + drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false); 716 716 frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL; 717 717 718 718 tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
+4 -1
drivers/gpu/drm/i915/intel_hdmi.c
··· 459 459 struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); 460 460 const struct drm_display_mode *adjusted_mode = 461 461 &crtc_state->base.adjusted_mode; 462 + struct drm_connector *connector = &intel_hdmi->attached_connector->base; 463 + bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported; 462 464 union hdmi_infoframe frame; 463 465 int ret; 464 466 465 467 ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, 466 - adjusted_mode); 468 + adjusted_mode, 469 + is_hdmi2_sink); 467 470 if (ret < 0) { 468 471 DRM_ERROR("couldn't fill AVI infoframe\n"); 469 472 return;
+2 -1
drivers/gpu/drm/i915/intel_sdvo.c
··· 996 996 ssize_t len; 997 997 998 998 ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, 999 - &pipe_config->base.adjusted_mode); 999 + &pipe_config->base.adjusted_mode, 1000 + false); 1000 1001 if (ret < 0) { 1001 1002 DRM_ERROR("couldn't fill AVI infoframe\n"); 1002 1003 return false;
+1 -1
drivers/gpu/drm/mediatek/mtk_hdmi.c
··· 975 975 u8 buffer[17]; 976 976 ssize_t err; 977 977 978 - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); 978 + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); 979 979 if (err < 0) { 980 980 dev_err(hdmi->dev, 981 981 "Failed to get AVI infoframe from mode: %zd\n", err);
+1 -1
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
··· 97 97 u32 val; 98 98 int len; 99 99 100 - drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); 100 + drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false); 101 101 102 102 len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer)); 103 103 if (len < 0) {
+2 -1
drivers/gpu/drm/nouveau/nv50_display.c
··· 2762 2762 if (!drm_detect_hdmi_monitor(nv_connector->edid)) 2763 2763 return; 2764 2764 2765 - ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode); 2765 + ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode, 2766 + false); 2766 2767 if (!ret) { 2767 2768 /* We have an AVI InfoFrame, populate it to the display */ 2768 2769 args.pwr.avi_infoframe_length
+2 -1
drivers/gpu/drm/omapdrm/omap_encoder.c
··· 85 85 if (hdmi_mode && dssdev->driver->set_hdmi_infoframe) { 86 86 struct hdmi_avi_infoframe avi; 87 87 88 - r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode); 88 + r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode, 89 + false); 89 90 if (r == 0) 90 91 dssdev->driver->set_hdmi_infoframe(dssdev, &avi); 91 92 }
+1 -1
drivers/gpu/drm/radeon/radeon_audio.c
··· 516 516 if (!connector) 517 517 return -EINVAL; 518 518 519 - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); 519 + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); 520 520 if (err < 0) { 521 521 DRM_ERROR("failed to setup AVI infoframe: %d\n", err); 522 522 return err;
+1 -1
drivers/gpu/drm/rockchip/inno_hdmi.c
··· 294 294 union hdmi_infoframe frame; 295 295 int rc; 296 296 297 - rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); 297 + rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false); 298 298 299 299 if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444) 300 300 frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
+1 -1
drivers/gpu/drm/sti/sti_hdmi.c
··· 434 434 435 435 DRM_DEBUG_DRIVER("\n"); 436 436 437 - ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode); 437 + ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode, false); 438 438 if (ret < 0) { 439 439 DRM_ERROR("failed to setup AVI infoframe: %d\n", ret); 440 440 return ret;
+1 -1
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
··· 52 52 u8 buffer[17]; 53 53 int i, ret; 54 54 55 - ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); 55 + ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); 56 56 if (ret < 0) { 57 57 DRM_ERROR("Failed to get infoframes from mode\n"); 58 58 return ret;
+1 -1
drivers/gpu/drm/tegra/hdmi.c
··· 734 734 u8 buffer[17]; 735 735 ssize_t err; 736 736 737 - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); 737 + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); 738 738 if (err < 0) { 739 739 dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err); 740 740 return;
+1 -1
drivers/gpu/drm/tegra/sor.c
··· 1904 1904 value &= ~INFOFRAME_CTRL_ENABLE; 1905 1905 tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL); 1906 1906 1907 - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); 1907 + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); 1908 1908 if (err < 0) { 1909 1909 dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err); 1910 1910 return err;
+1 -1
drivers/gpu/drm/vc4/vc4_hdmi.c
··· 395 395 union hdmi_infoframe frame; 396 396 int ret; 397 397 398 - ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); 398 + ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false); 399 399 if (ret < 0) { 400 400 DRM_ERROR("couldn't fill AVI infoframe\n"); 401 401 return;
+1 -1
drivers/gpu/drm/zte/zx_hdmi.c
··· 124 124 union hdmi_infoframe frame; 125 125 int ret; 126 126 127 - ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); 127 + ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false); 128 128 if (ret) { 129 129 DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n", 130 130 ret);
+2 -1
include/drm/drm_edid.h
··· 343 343 344 344 int 345 345 drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, 346 - const struct drm_display_mode *mode); 346 + const struct drm_display_mode *mode, 347 + bool is_hdmi2_sink); 347 348 int 348 349 drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, 349 350 const struct drm_display_mode *mode);