FROMLIST: drm: Add HDMI 2.0 VIC support for AVI info-frames
authorZheng Yang <zhengyang@rock-chips.com>
Mon, 27 Mar 2017 03:04:14 +0000 (11:04 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Wed, 29 Mar 2017 02:49:54 +0000 (10:49 +0800)
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 the connector->display_info
to check if the connected display is HDMI 2.0.

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

Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
(am from https://patchwork.kernel.org/patch/9641449)
Change-Id: I364cd0aed7eea0384ea9eddfff20c3fa86eb9ba2
Signed-off-by: Zheng Yang <zhengyang@rock-chips.com>
15 files changed:
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
drivers/gpu/drm/bridge/dw-hdmi.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/i2c/tda998x_drv.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/omapdrm/omap_encoder.c
drivers/gpu/drm/radeon/radeon_audio.c
drivers/gpu/drm/rockchip/inno_hdmi.c
drivers/gpu/drm/sti/sti_hdmi.c
drivers/gpu/drm/tegra/hdmi.c
drivers/gpu/drm/tegra/sor.c
include/drm/drm_edid.h

index 75b7b4d1e5c7aacd13bf5684e94cc9fb45d3798e..67e465c111ac604b045bef179b707e30cae211fd 100644 (file)
@@ -1910,7 +1910,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder,
        dce_v10_0_audio_write_sad_regs(encoder);
        dce_v10_0_audio_write_latency_fields(encoder, mode);
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
        if (err < 0) {
                DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
                return;
index af30e3f95eab18b7be67658090b0f2af6ff1a974..ccd2ed433e1757d82f378f0a9f139a0d8b1fa1c0 100644 (file)
@@ -1898,7 +1898,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder,
        dce_v11_0_audio_write_sad_regs(encoder);
        dce_v11_0_audio_write_latency_fields(encoder, mode);
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
        if (err < 0) {
                DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
                return;
index 967a2d3482ae52fd55ccd07627ce1eeae352da2f..1c3f4948911fa0725bff9a0866bc636dd3577a6e 100644 (file)
@@ -1878,7 +1878,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
        dce_v8_0_audio_write_sad_regs(encoder);
        dce_v8_0_audio_write_latency_fields(encoder, mode);
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
        if (err < 0) {
                DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
                return;
index 7aab06712118ac49958b766d7e9882409ba95aaa..334bb28630672c6653e22824aa9a449dee488671 100644 (file)
@@ -1276,7 +1276,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
        u8 val;
 
        /* Initialise info frame from DRM mode */
-       drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+       drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
 
        if (hdmi->hdmi_data.enc_out_format == YCBCR444)
                frame.colorspace = HDMI_COLORSPACE_YUV444;
index 10ae897465b1644410bd8a3a20b937821b7e7d7d..d4e01b0586b90164b18d52f518079842d384e13a 100644 (file)
@@ -4380,12 +4380,14 @@ EXPORT_SYMBOL(drm_set_preferred_mode);
  *                                              data from a DRM display mode
  * @frame: HDMI AVI infoframe
  * @mode: DRM display mode
+ * @is_hdmi2: Sink is HDMI 2.0 compliant
  *
  * Return: 0 on success or a negative error code on failure.
  */
 int
 drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
-                                        const struct drm_display_mode *mode)
+                                        const struct drm_display_mode *mode,
+                                        bool is_hdmi2)
 {
        int err;
 
@@ -4401,6 +4403,14 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
 
        frame->video_code = drm_match_cea_mode(mode);
 
+       /*
+        * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
+        * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
+        * have to make sure we dont break HDMI 1.4 sinks.
+        */
+       if (!is_hdmi2 && frame->video_code > 64)
+               frame->video_code = 0;
+
        frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
 
        /*
index aefab3dc23e9b27e597134bb8e170c3bdf0b1960..ab4f2a416bd87389d5061eea2878b519cb6fbcee 100644 (file)
@@ -692,7 +692,7 @@ tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode)
 {
        union hdmi_infoframe frame;
 
-       drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
+       drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
        frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
 
        tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
index b1c54f28e9da82c2e833a120276a01017f0b0662..5b8aeafcbfc48dbc239e62d5e44742017b1cd619 100644 (file)
@@ -457,7 +457,8 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
        int ret;
 
        ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
-                                                      adjusted_mode);
+                                                      adjusted_mode,
+                                                      false);
        if (ret < 0) {
                DRM_ERROR("couldn't fill AVI infoframe\n");
                return;
index c011cf70264fe7f0581a2fd4096ebfffa7c7c568..a9612cf1a6ed077978d2477ab9872dbf8606a305 100644 (file)
@@ -1014,7 +1014,8 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
        ssize_t len;
 
        ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
-                                                      adjusted_mode);
+                                                      adjusted_mode,
+                                                      false);
        if (ret < 0) {
                DRM_ERROR("couldn't fill AVI infoframe\n");
                return false;
index 0c104ad7ef661c9bc453b4e9ef442931526573b3..24ad9adf6d6c03ea4359251aad730a86bdf8b85f 100644 (file)
@@ -85,7 +85,8 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
        if (hdmi_mode && dssdev->driver->set_hdmi_infoframe) {
                struct hdmi_avi_infoframe avi;
 
-               r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode);
+               r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode,
+                                                            false);
                if (r == 0)
                        dssdev->driver->set_hdmi_infoframe(dssdev, &avi);
        }
index b214663b370da00905faa882ea27513153aa91bd..49b42bff9635b4cf39221fa7c300394c28bde2f9 100644 (file)
@@ -516,7 +516,7 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
        if (!connector)
                return -EINVAL;
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
        if (err < 0) {
                DRM_ERROR("failed to setup AVI infoframe: %d\n", err);
                return err;
index 97eada48177774b4f48ee762d2c94d9f5ab7b279..d7b4266e1fa73ca8fc0a318142bae2e7331e4049 100644 (file)
@@ -305,7 +305,7 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
        union hdmi_infoframe frame;
        int rc;
 
-       rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
+       rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
 
        if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
                frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
index cd501563c0cc58f83b9992e7e83e09e048dfd32a..de18a6cedbb22830aece9e902952ac29870284a5 100644 (file)
@@ -345,7 +345,7 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
 
        DRM_DEBUG_DRIVER("\n");
 
-       ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode);
+       ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode, false);
        if (ret < 0) {
                DRM_ERROR("failed to setup AVI infoframe: %d\n", ret);
                return ret;
index b7ef4929e347a0f2fe0f85e80cf49bac3c7dc7d3..1c6d615840cfdfe108d33089e229b38cf78ac6d2 100644 (file)
@@ -650,7 +650,7 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
                return;
        }
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
        if (err < 0) {
                dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
                return;
index 3e012ee25242d6efb98f27ec7cb50c439f95b9cf..f0b5bf6dd406e2af73ecf83613d1a5f4443fc51c 100644 (file)
@@ -1692,7 +1692,7 @@ tegra_sor_hdmi_setup_avi_infoframe(struct tegra_sor *sor,
        value &= ~INFOFRAME_CTRL_ENABLE;
        tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL);
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
        if (err < 0) {
                dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
                return err;
index 4317ea41382fceb2258b25f5ebf5a0ca0f5c4590..820ad9e33884366b44f1e08c465e66f69466d719 100644 (file)
@@ -337,7 +337,8 @@ int drm_load_edid_firmware(struct drm_connector *connector);
 
 int
 drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
-                                        const struct drm_display_mode *mode);
+                                        const struct drm_display_mode *mode,
+                                        bool is_hdmi2);
 int
 drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
                                            const struct drm_display_mode *mode);