diff options
author | Archit Taneja <architt@codeaurora.org> | 2017-06-16 01:09:36 -0400 |
---|---|---|
committer | Rob Clark <robdclark@gmail.com> | 2017-06-16 11:16:09 -0400 |
commit | 816fa34c051492c7f115ad2fd91c9e723d7fc298 (patch) | |
tree | 690bd6a80f2f8e42806500f85ea282017d624edd | |
parent | b474cbbb2bfd8d38f8bc36165567fe153d89fc9a (diff) |
drm/msm/hdmi: Fix HDMI pink strip issue seen on 8x96
A 2 pixel wide pink strip was observed on the left end of some HDMI
monitors configured in a HDMI mode.
It turned out that we were missing out on configuring AVI infoframes, and
unlike APQ8064, the 8x96 HDMI H/W seems to be sensitive to that.
Add configuration of AVI infoframes. While at it, make sure that
hdmi_audio_update is only called when we've detected that the monitor
supports HDMI.
Signed-off-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
-rw-r--r-- | drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 70 |
1 files changed, 67 insertions, 3 deletions
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 4e6d1bf27474..ae40e7179d4f 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | |||
@@ -86,6 +86,65 @@ static void power_off(struct drm_bridge *bridge) | |||
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
89 | #define AVI_IFRAME_LINE_NUMBER 1 | ||
90 | |||
91 | static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi) | ||
92 | { | ||
93 | struct drm_crtc *crtc = hdmi->encoder->crtc; | ||
94 | const struct drm_display_mode *mode = &crtc->state->adjusted_mode; | ||
95 | union hdmi_infoframe frame; | ||
96 | u8 buffer[HDMI_INFOFRAME_SIZE(AVI)]; | ||
97 | u32 val; | ||
98 | int len; | ||
99 | |||
100 | drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); | ||
101 | |||
102 | len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer)); | ||
103 | if (len < 0) { | ||
104 | dev_err(&hdmi->pdev->dev, | ||
105 | "failed to configure avi infoframe\n"); | ||
106 | return; | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * the AVI_INFOx registers don't map exactly to how the AVI infoframes | ||
111 | * are packed according to the spec. The checksum from the header is | ||
112 | * written to the LSB byte of AVI_INFO0 and the version is written to | ||
113 | * the third byte from the LSB of AVI_INFO3 | ||
114 | */ | ||
115 | hdmi_write(hdmi, REG_HDMI_AVI_INFO(0), | ||
116 | buffer[3] | | ||
117 | buffer[4] << 8 | | ||
118 | buffer[5] << 16 | | ||
119 | buffer[6] << 24); | ||
120 | |||
121 | hdmi_write(hdmi, REG_HDMI_AVI_INFO(1), | ||
122 | buffer[7] | | ||
123 | buffer[8] << 8 | | ||
124 | buffer[9] << 16 | | ||
125 | buffer[10] << 24); | ||
126 | |||
127 | hdmi_write(hdmi, REG_HDMI_AVI_INFO(2), | ||
128 | buffer[11] | | ||
129 | buffer[12] << 8 | | ||
130 | buffer[13] << 16 | | ||
131 | buffer[14] << 24); | ||
132 | |||
133 | hdmi_write(hdmi, REG_HDMI_AVI_INFO(3), | ||
134 | buffer[15] | | ||
135 | buffer[16] << 8 | | ||
136 | buffer[1] << 24); | ||
137 | |||
138 | hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, | ||
139 | HDMI_INFOFRAME_CTRL0_AVI_SEND | | ||
140 | HDMI_INFOFRAME_CTRL0_AVI_CONT); | ||
141 | |||
142 | val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); | ||
143 | val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK; | ||
144 | val |= HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE(AVI_IFRAME_LINE_NUMBER); | ||
145 | hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); | ||
146 | } | ||
147 | |||
89 | static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge) | 148 | static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge) |
90 | { | 149 | { |
91 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); | 150 | struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); |
@@ -98,7 +157,10 @@ static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge) | |||
98 | msm_hdmi_phy_resource_enable(phy); | 157 | msm_hdmi_phy_resource_enable(phy); |
99 | msm_hdmi_power_on(bridge); | 158 | msm_hdmi_power_on(bridge); |
100 | hdmi->power_on = true; | 159 | hdmi->power_on = true; |
101 | msm_hdmi_audio_update(hdmi); | 160 | if (hdmi->hdmi_mode) { |
161 | msm_hdmi_config_avi_infoframe(hdmi); | ||
162 | msm_hdmi_audio_update(hdmi); | ||
163 | } | ||
102 | } | 164 | } |
103 | 165 | ||
104 | msm_hdmi_phy_powerup(phy, hdmi->pixclock); | 166 | msm_hdmi_phy_powerup(phy, hdmi->pixclock); |
@@ -134,7 +196,8 @@ static void msm_hdmi_bridge_post_disable(struct drm_bridge *bridge) | |||
134 | if (hdmi->power_on) { | 196 | if (hdmi->power_on) { |
135 | power_off(bridge); | 197 | power_off(bridge); |
136 | hdmi->power_on = false; | 198 | hdmi->power_on = false; |
137 | msm_hdmi_audio_update(hdmi); | 199 | if (hdmi->hdmi_mode) |
200 | msm_hdmi_audio_update(hdmi); | ||
138 | msm_hdmi_phy_resource_disable(phy); | 201 | msm_hdmi_phy_resource_disable(phy); |
139 | } | 202 | } |
140 | } | 203 | } |
@@ -196,7 +259,8 @@ static void msm_hdmi_bridge_mode_set(struct drm_bridge *bridge, | |||
196 | DBG("frame_ctrl=%08x", frame_ctrl); | 259 | DBG("frame_ctrl=%08x", frame_ctrl); |
197 | hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl); | 260 | hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl); |
198 | 261 | ||
199 | msm_hdmi_audio_update(hdmi); | 262 | if (hdmi->hdmi_mode) |
263 | msm_hdmi_audio_update(hdmi); | ||
200 | } | 264 | } |
201 | 265 | ||
202 | static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = { | 266 | static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = { |