summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2018-08-14 20:44:03 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2018-08-14 20:44:02 -0700
commitcae5c018df9115580489ec9e1692fc38a38c806c (patch)
tree115e7d3fa7e3c802c30cfb3041b15b27de01339e
parent2d6cc4c81b1cb69379102c57a9a927c9583ccb8b (diff)
parent63f9f30f6f54b917c153684a7d1599699dd3f6e0 (diff)
Merge "drm/msm: Clear the mode private flags before setting"
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c63
-rw-r--r--drivers/gpu/drm/msm/sde_edid_parser.c42
2 files changed, 87 insertions, 18 deletions
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
index 2d65fc924f07..120a6defc868 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
@@ -125,6 +125,55 @@ static void sde_hdmi_clear_hdr_info(struct drm_bridge *bridge)
connector->hdr_supported = false;
}
+static void sde_hdmi_clear_vsdb_info(struct drm_bridge *bridge)
+{
+ struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
+ struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
+ struct drm_connector *connector = hdmi->connector;
+
+ connector->max_tmds_clock = 0;
+ connector->latency_present[0] = false;
+ connector->latency_present[1] = false;
+ connector->video_latency[0] = false;
+ connector->video_latency[1] = false;
+ connector->audio_latency[0] = false;
+ connector->audio_latency[1] = false;
+}
+
+static void sde_hdmi_clear_hf_vsdb_info(struct drm_bridge *bridge)
+{
+ struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
+ struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
+ struct drm_connector *connector = hdmi->connector;
+
+ connector->max_tmds_char = 0;
+ connector->scdc_present = false;
+ connector->rr_capable = false;
+ connector->supports_scramble = false;
+ connector->flags_3d = 0;
+}
+
+static void sde_hdmi_clear_vcdb_info(struct drm_bridge *bridge)
+{
+ struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
+ struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
+ struct drm_connector *connector = hdmi->connector;
+
+ connector->pt_scan_info = 0;
+ connector->it_scan_info = 0;
+ connector->ce_scan_info = 0;
+ connector->rgb_qs = false;
+ connector->yuv_qs = false;
+}
+
+static void sde_hdmi_clear_vsdbs(struct drm_bridge *bridge)
+{
+ /* Clear fields of HDMI VSDB */
+ sde_hdmi_clear_vsdb_info(bridge);
+ /* Clear fields of HDMI forum VSDB */
+ sde_hdmi_clear_hf_vsdb_info(bridge);
+}
+
static int _sde_hdmi_bridge_power_on(struct drm_bridge *bridge)
{
struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
@@ -606,6 +655,12 @@ static void _sde_hdmi_bridge_disable(struct drm_bridge *bridge)
mutex_lock(&display->display_lock);
+ if (!bridge) {
+ SDE_ERROR("Invalid params\n");
+ mutex_unlock(&display->display_lock);
+ return;
+ }
+
display->pll_update_enable = false;
display->sink_hdcp_ver = SDE_HDMI_HDCP_NONE;
display->sink_hdcp22_support = false;
@@ -614,6 +669,11 @@ static void _sde_hdmi_bridge_disable(struct drm_bridge *bridge)
sde_hdmi_hdcp_off(display);
sde_hdmi_clear_hdr_info(bridge);
+ /* Clear HDMI VSDB blocks info */
+ sde_hdmi_clear_vsdbs(bridge);
+ /* Clear HDMI VCDB block info */
+ sde_hdmi_clear_vcdb_info(bridge);
+
mutex_unlock(&display->display_lock);
}
@@ -940,6 +1000,9 @@ static bool _sde_hdmi_bridge_mode_fixup(struct drm_bridge *bridge,
struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
+ /* Clear the private flags before assigning new one */
+ adjusted_mode->private_flags = 0;
+
adjusted_mode->private_flags |=
_sde_hdmi_choose_best_format(hdmi, adjusted_mode);
SDE_DEBUG("Adjusted mode private flags: 0x%x\n",
diff --git a/drivers/gpu/drm/msm/sde_edid_parser.c b/drivers/gpu/drm/msm/sde_edid_parser.c
index 50667c5921a0..043e439835f1 100644
--- a/drivers/gpu/drm/msm/sde_edid_parser.c
+++ b/drivers/gpu/drm/msm/sde_edid_parser.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -252,12 +252,13 @@ static void sde_edid_parse_Y420CMDB(
struct drm_connector *connector, struct sde_edid_ctrl *edid_ctrl,
const u8 *db)
{
- u32 offset = 0;
u8 cmdb_len = 0;
u8 svd_len = 0;
const u8 *svd = NULL;
- u32 i = 0, j = 0;
+ u32 i = 0;
u32 video_format = 0;
+ u32 num_cmdb_svd = 0;
+ const u32 mult = 8;
if (!edid_ctrl) {
DEV_ERR("%s: edid_ctrl is NULL\n", __func__);
@@ -271,8 +272,8 @@ const u8 *db)
SDE_EDID_DEBUG("%s +\n", __func__);
cmdb_len = db[0] & 0x1f;
- /* Byte 3 to L+1 contain SVDs */
- offset += 2;
+ if (cmdb_len < 1)
+ return;
svd = sde_edid_find_block(edid_ctrl->edid, VIDEO_DATA_BLOCK);
@@ -282,21 +283,26 @@ const u8 *db)
++svd;
}
- for (i = 0; i < svd_len; i++, j++) {
+ if (cmdb_len == 1)
+ num_cmdb_svd = svd_len;
+ else {
+ num_cmdb_svd = (cmdb_len - 1) * mult;
+ if (num_cmdb_svd > svd_len)
+ num_cmdb_svd = svd_len;
+ }
+
+ for (i = 0; i < num_cmdb_svd; i++) {
video_format = *(svd + i) & 0x7F;
- if (cmdb_len == 1) {
- /* If cmdb_len is 1, it means all SVDs support YUV */
- sde_edid_set_y420_support(connector, video_format);
- } else if (db[offset] & (1 << j)) {
+ /*
+ * If cmdb_len is 1, it means all SVDs support YUV
+ * Else, we check each byte of the cmdb bitmap bitwise
+ * and match those bits with the formats populated
+ * during the parsing of the Video Data Blocks.
+ * Refer to CTA 861-F section 7.5.11 YCBCR 4:2:0 Capability
+ * Map Data Block for more details on this.
+ */
+ if (cmdb_len == 1 || (db[2 + i / mult] & (1 << (i % mult))))
sde_edid_set_y420_support(connector, video_format);
-
- if (j & 0x80) {
- j = j/8;
- offset++;
- if (offset >= cmdb_len)
- break;
- }
- }
}
SDE_EDID_DEBUG("%s -\n", __func__);