diff options
| -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 = { |
