1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2013 Red Hat 4 * Author: Rob Clark <robdclark@gmail.com> 5 */ 6 7 #include <linux/delay.h> 8 #include <drm/drm_bridge_connector.h> 9 #include <drm/drm_edid.h> 10 11 #include "msm_kms.h" 12 #include "hdmi.h" 13 14 static void msm_hdmi_power_on(struct drm_bridge *bridge) 15 { 16 struct drm_device *dev = bridge->dev; 17 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 18 struct hdmi *hdmi = hdmi_bridge->hdmi; 19 const struct hdmi_platform_config *config = hdmi->config; 20 int i, ret; 21 22 pm_runtime_get_sync(&hdmi->pdev->dev); 23 24 ret = regulator_bulk_enable(config->pwr_reg_cnt, hdmi->pwr_regs); 25 if (ret) 26 DRM_DEV_ERROR(dev->dev, "failed to enable pwr regulator: %d\n", ret); 27 28 if (config->pwr_clk_cnt > 0) { 29 DBG("pixclock: %lu", hdmi->pixclock); 30 ret = clk_set_rate(hdmi->pwr_clks[0], hdmi->pixclock); 31 if (ret) { 32 DRM_DEV_ERROR(dev->dev, "failed to set pixel clk: %s (%d)\n", 33 config->pwr_clk_names[0], ret); 34 } 35 } 36 37 for (i = 0; i < config->pwr_clk_cnt; i++) { 38 ret = clk_prepare_enable(hdmi->pwr_clks[i]); 39 if (ret) { 40 DRM_DEV_ERROR(dev->dev, "failed to enable pwr clk: %s (%d)\n", 41 config->pwr_clk_names[i], ret); 42 } 43 } 44 } 45 46 static void power_off(struct drm_bridge *bridge) 47 { 48 struct drm_device *dev = bridge->dev; 49 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 50 struct hdmi *hdmi = hdmi_bridge->hdmi; 51 const struct hdmi_platform_config *config = hdmi->config; 52 int i, ret; 53 54 /* TODO do we need to wait for final vblank somewhere before 55 * cutting the clocks? 56 */ 57 mdelay(16 + 4); 58 59 for (i = 0; i < config->pwr_clk_cnt; i++) 60 clk_disable_unprepare(hdmi->pwr_clks[i]); 61 62 ret = regulator_bulk_disable(config->pwr_reg_cnt, hdmi->pwr_regs); 63 if (ret) 64 DRM_DEV_ERROR(dev->dev, "failed to disable pwr regulator: %d\n", ret); 65 66 pm_runtime_put(&hdmi->pdev->dev); 67 } 68 69 #define AVI_IFRAME_LINE_NUMBER 1 70 71 static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi) 72 { 73 struct drm_crtc *crtc = hdmi->encoder->crtc; 74 const struct drm_display_mode *mode = &crtc->state->adjusted_mode; 75 union hdmi_infoframe frame; 76 u8 buffer[HDMI_INFOFRAME_SIZE(AVI)]; 77 u32 val; 78 int len; 79 80 drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, 81 hdmi->connector, mode); 82 83 len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer)); 84 if (len < 0) { 85 DRM_DEV_ERROR(&hdmi->pdev->dev, 86 "failed to configure avi infoframe\n"); 87 return; 88 } 89 90 /* 91 * the AVI_INFOx registers don't map exactly to how the AVI infoframes 92 * are packed according to the spec. The checksum from the header is 93 * written to the LSB byte of AVI_INFO0 and the version is written to 94 * the third byte from the LSB of AVI_INFO3 95 */ 96 hdmi_write(hdmi, REG_HDMI_AVI_INFO(0), 97 buffer[3] | 98 buffer[4] << 8 | 99 buffer[5] << 16 | 100 buffer[6] << 24); 101 102 hdmi_write(hdmi, REG_HDMI_AVI_INFO(1), 103 buffer[7] | 104 buffer[8] << 8 | 105 buffer[9] << 16 | 106 buffer[10] << 24); 107 108 hdmi_write(hdmi, REG_HDMI_AVI_INFO(2), 109 buffer[11] | 110 buffer[12] << 8 | 111 buffer[13] << 16 | 112 buffer[14] << 24); 113 114 hdmi_write(hdmi, REG_HDMI_AVI_INFO(3), 115 buffer[15] | 116 buffer[16] << 8 | 117 buffer[1] << 24); 118 119 hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, 120 HDMI_INFOFRAME_CTRL0_AVI_SEND | 121 HDMI_INFOFRAME_CTRL0_AVI_CONT); 122 123 val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); 124 val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK; 125 val |= HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE(AVI_IFRAME_LINE_NUMBER); 126 hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); 127 } 128 129 static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge) 130 { 131 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 132 struct hdmi *hdmi = hdmi_bridge->hdmi; 133 struct hdmi_phy *phy = hdmi->phy; 134 135 DBG("power up"); 136 137 if (!hdmi->power_on) { 138 msm_hdmi_phy_resource_enable(phy); 139 msm_hdmi_power_on(bridge); 140 hdmi->power_on = true; 141 if (hdmi->hdmi_mode) { 142 msm_hdmi_config_avi_infoframe(hdmi); 143 msm_hdmi_audio_update(hdmi); 144 } 145 } 146 147 msm_hdmi_phy_powerup(phy, hdmi->pixclock); 148 149 msm_hdmi_set_mode(hdmi, true); 150 151 if (hdmi->hdcp_ctrl) 152 msm_hdmi_hdcp_on(hdmi->hdcp_ctrl); 153 } 154 155 static void msm_hdmi_bridge_post_disable(struct drm_bridge *bridge) 156 { 157 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 158 struct hdmi *hdmi = hdmi_bridge->hdmi; 159 struct hdmi_phy *phy = hdmi->phy; 160 161 if (hdmi->hdcp_ctrl) 162 msm_hdmi_hdcp_off(hdmi->hdcp_ctrl); 163 164 DBG("power down"); 165 msm_hdmi_set_mode(hdmi, false); 166 167 msm_hdmi_phy_powerdown(phy); 168 169 if (hdmi->power_on) { 170 power_off(bridge); 171 hdmi->power_on = false; 172 if (hdmi->hdmi_mode) 173 msm_hdmi_audio_update(hdmi); 174 msm_hdmi_phy_resource_disable(phy); 175 } 176 } 177 178 static void msm_hdmi_bridge_mode_set(struct drm_bridge *bridge, 179 const struct drm_display_mode *mode, 180 const struct drm_display_mode *adjusted_mode) 181 { 182 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 183 struct hdmi *hdmi = hdmi_bridge->hdmi; 184 int hstart, hend, vstart, vend; 185 uint32_t frame_ctrl; 186 187 mode = adjusted_mode; 188 189 hdmi->pixclock = mode->clock * 1000; 190 191 hstart = mode->htotal - mode->hsync_start; 192 hend = mode->htotal - mode->hsync_start + mode->hdisplay; 193 194 vstart = mode->vtotal - mode->vsync_start - 1; 195 vend = mode->vtotal - mode->vsync_start + mode->vdisplay - 1; 196 197 DBG("htotal=%d, vtotal=%d, hstart=%d, hend=%d, vstart=%d, vend=%d", 198 mode->htotal, mode->vtotal, hstart, hend, vstart, vend); 199 200 hdmi_write(hdmi, REG_HDMI_TOTAL, 201 HDMI_TOTAL_H_TOTAL(mode->htotal - 1) | 202 HDMI_TOTAL_V_TOTAL(mode->vtotal - 1)); 203 204 hdmi_write(hdmi, REG_HDMI_ACTIVE_HSYNC, 205 HDMI_ACTIVE_HSYNC_START(hstart) | 206 HDMI_ACTIVE_HSYNC_END(hend)); 207 hdmi_write(hdmi, REG_HDMI_ACTIVE_VSYNC, 208 HDMI_ACTIVE_VSYNC_START(vstart) | 209 HDMI_ACTIVE_VSYNC_END(vend)); 210 211 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 212 hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2, 213 HDMI_VSYNC_TOTAL_F2_V_TOTAL(mode->vtotal)); 214 hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2, 215 HDMI_VSYNC_ACTIVE_F2_START(vstart + 1) | 216 HDMI_VSYNC_ACTIVE_F2_END(vend + 1)); 217 } else { 218 hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2, 219 HDMI_VSYNC_TOTAL_F2_V_TOTAL(0)); 220 hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2, 221 HDMI_VSYNC_ACTIVE_F2_START(0) | 222 HDMI_VSYNC_ACTIVE_F2_END(0)); 223 } 224 225 frame_ctrl = 0; 226 if (mode->flags & DRM_MODE_FLAG_NHSYNC) 227 frame_ctrl |= HDMI_FRAME_CTRL_HSYNC_LOW; 228 if (mode->flags & DRM_MODE_FLAG_NVSYNC) 229 frame_ctrl |= HDMI_FRAME_CTRL_VSYNC_LOW; 230 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 231 frame_ctrl |= HDMI_FRAME_CTRL_INTERLACED_EN; 232 DBG("frame_ctrl=%08x", frame_ctrl); 233 hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl); 234 235 if (hdmi->hdmi_mode) 236 msm_hdmi_audio_update(hdmi); 237 } 238 239 static const struct drm_edid *msm_hdmi_bridge_edid_read(struct drm_bridge *bridge, 240 struct drm_connector *connector) 241 { 242 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 243 struct hdmi *hdmi = hdmi_bridge->hdmi; 244 const struct drm_edid *drm_edid; 245 uint32_t hdmi_ctrl; 246 247 hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL); 248 hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE); 249 250 drm_edid = drm_edid_read_ddc(connector, hdmi->i2c); 251 252 hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl); 253 254 if (drm_edid) { 255 /* 256 * FIXME: This should use connector->display_info.is_hdmi from a 257 * path that has read the EDID and called 258 * drm_edid_connector_update(). 259 */ 260 const struct edid *edid = drm_edid_raw(drm_edid); 261 262 hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid); 263 } 264 265 return drm_edid; 266 } 267 268 static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge, 269 const struct drm_display_info *info, 270 const struct drm_display_mode *mode) 271 { 272 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 273 struct hdmi *hdmi = hdmi_bridge->hdmi; 274 const struct hdmi_platform_config *config = hdmi->config; 275 struct msm_drm_private *priv = bridge->dev->dev_private; 276 struct msm_kms *kms = priv->kms; 277 long actual, requested; 278 279 requested = 1000 * mode->clock; 280 281 /* for mdp5/apq8074, we manage our own pixel clk (as opposed to 282 * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder 283 * instead): 284 */ 285 if (kms->funcs->round_pixclk) 286 actual = kms->funcs->round_pixclk(kms, 287 requested, hdmi_bridge->hdmi->encoder); 288 else if (config->pwr_clk_cnt > 0) 289 actual = clk_round_rate(hdmi->pwr_clks[0], requested); 290 else 291 actual = requested; 292 293 DBG("requested=%ld, actual=%ld", requested, actual); 294 295 if (actual != requested) 296 return MODE_CLOCK_RANGE; 297 298 return 0; 299 } 300 301 static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = { 302 .pre_enable = msm_hdmi_bridge_pre_enable, 303 .post_disable = msm_hdmi_bridge_post_disable, 304 .mode_set = msm_hdmi_bridge_mode_set, 305 .mode_valid = msm_hdmi_bridge_mode_valid, 306 .edid_read = msm_hdmi_bridge_edid_read, 307 .detect = msm_hdmi_bridge_detect, 308 }; 309 310 static void 311 msm_hdmi_hotplug_work(struct work_struct *work) 312 { 313 struct hdmi_bridge *hdmi_bridge = 314 container_of(work, struct hdmi_bridge, hpd_work); 315 struct drm_bridge *bridge = &hdmi_bridge->base; 316 317 drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge)); 318 } 319 320 /* initialize bridge */ 321 int msm_hdmi_bridge_init(struct hdmi *hdmi) 322 { 323 struct drm_bridge *bridge = NULL; 324 struct hdmi_bridge *hdmi_bridge; 325 int ret; 326 327 hdmi_bridge = devm_kzalloc(hdmi->dev->dev, 328 sizeof(*hdmi_bridge), GFP_KERNEL); 329 if (!hdmi_bridge) 330 return -ENOMEM; 331 332 hdmi_bridge->hdmi = hdmi; 333 INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work); 334 335 bridge = &hdmi_bridge->base; 336 bridge->funcs = &msm_hdmi_bridge_funcs; 337 bridge->ddc = hdmi->i2c; 338 bridge->type = DRM_MODE_CONNECTOR_HDMIA; 339 bridge->ops = DRM_BRIDGE_OP_HPD | 340 DRM_BRIDGE_OP_DETECT | 341 DRM_BRIDGE_OP_EDID; 342 343 ret = devm_drm_bridge_add(hdmi->dev->dev, bridge); 344 if (ret) 345 return ret; 346 347 ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); 348 if (ret) 349 return ret; 350 351 hdmi->bridge = bridge; 352 353 return 0; 354 } 355