0001
0002
0003
0004
0005
0006
0007 #include <linux/delay.h>
0008 #include <drm/drm_bridge_connector.h>
0009 #include <drm/drm_edid.h>
0010
0011 #include "msm_kms.h"
0012 #include "hdmi.h"
0013
0014 void msm_hdmi_bridge_destroy(struct drm_bridge *bridge)
0015 {
0016 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
0017
0018 msm_hdmi_hpd_disable(hdmi_bridge);
0019 drm_bridge_remove(bridge);
0020 }
0021
0022 static void msm_hdmi_power_on(struct drm_bridge *bridge)
0023 {
0024 struct drm_device *dev = bridge->dev;
0025 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
0026 struct hdmi *hdmi = hdmi_bridge->hdmi;
0027 const struct hdmi_platform_config *config = hdmi->config;
0028 int i, ret;
0029
0030 pm_runtime_get_sync(&hdmi->pdev->dev);
0031
0032 ret = regulator_bulk_enable(config->pwr_reg_cnt, hdmi->pwr_regs);
0033 if (ret)
0034 DRM_DEV_ERROR(dev->dev, "failed to enable pwr regulator: %d\n", ret);
0035
0036 if (config->pwr_clk_cnt > 0) {
0037 DBG("pixclock: %lu", hdmi->pixclock);
0038 ret = clk_set_rate(hdmi->pwr_clks[0], hdmi->pixclock);
0039 if (ret) {
0040 DRM_DEV_ERROR(dev->dev, "failed to set pixel clk: %s (%d)\n",
0041 config->pwr_clk_names[0], ret);
0042 }
0043 }
0044
0045 for (i = 0; i < config->pwr_clk_cnt; i++) {
0046 ret = clk_prepare_enable(hdmi->pwr_clks[i]);
0047 if (ret) {
0048 DRM_DEV_ERROR(dev->dev, "failed to enable pwr clk: %s (%d)\n",
0049 config->pwr_clk_names[i], ret);
0050 }
0051 }
0052 }
0053
0054 static void power_off(struct drm_bridge *bridge)
0055 {
0056 struct drm_device *dev = bridge->dev;
0057 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
0058 struct hdmi *hdmi = hdmi_bridge->hdmi;
0059 const struct hdmi_platform_config *config = hdmi->config;
0060 int i, ret;
0061
0062
0063
0064
0065 mdelay(16 + 4);
0066
0067 for (i = 0; i < config->pwr_clk_cnt; i++)
0068 clk_disable_unprepare(hdmi->pwr_clks[i]);
0069
0070 ret = regulator_bulk_disable(config->pwr_reg_cnt, hdmi->pwr_regs);
0071 if (ret)
0072 DRM_DEV_ERROR(dev->dev, "failed to disable pwr regulator: %d\n", ret);
0073
0074 pm_runtime_put(&hdmi->pdev->dev);
0075 }
0076
0077 #define AVI_IFRAME_LINE_NUMBER 1
0078
0079 static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi)
0080 {
0081 struct drm_crtc *crtc = hdmi->encoder->crtc;
0082 const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
0083 union hdmi_infoframe frame;
0084 u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];
0085 u32 val;
0086 int len;
0087
0088 drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
0089 hdmi->connector, mode);
0090
0091 len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer));
0092 if (len < 0) {
0093 DRM_DEV_ERROR(&hdmi->pdev->dev,
0094 "failed to configure avi infoframe\n");
0095 return;
0096 }
0097
0098
0099
0100
0101
0102
0103
0104 hdmi_write(hdmi, REG_HDMI_AVI_INFO(0),
0105 buffer[3] |
0106 buffer[4] << 8 |
0107 buffer[5] << 16 |
0108 buffer[6] << 24);
0109
0110 hdmi_write(hdmi, REG_HDMI_AVI_INFO(1),
0111 buffer[7] |
0112 buffer[8] << 8 |
0113 buffer[9] << 16 |
0114 buffer[10] << 24);
0115
0116 hdmi_write(hdmi, REG_HDMI_AVI_INFO(2),
0117 buffer[11] |
0118 buffer[12] << 8 |
0119 buffer[13] << 16 |
0120 buffer[14] << 24);
0121
0122 hdmi_write(hdmi, REG_HDMI_AVI_INFO(3),
0123 buffer[15] |
0124 buffer[16] << 8 |
0125 buffer[1] << 24);
0126
0127 hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0,
0128 HDMI_INFOFRAME_CTRL0_AVI_SEND |
0129 HDMI_INFOFRAME_CTRL0_AVI_CONT);
0130
0131 val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1);
0132 val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK;
0133 val |= HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE(AVI_IFRAME_LINE_NUMBER);
0134 hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val);
0135 }
0136
0137 static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge)
0138 {
0139 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
0140 struct hdmi *hdmi = hdmi_bridge->hdmi;
0141 struct hdmi_phy *phy = hdmi->phy;
0142
0143 DBG("power up");
0144
0145 if (!hdmi->power_on) {
0146 msm_hdmi_phy_resource_enable(phy);
0147 msm_hdmi_power_on(bridge);
0148 hdmi->power_on = true;
0149 if (hdmi->hdmi_mode) {
0150 msm_hdmi_config_avi_infoframe(hdmi);
0151 msm_hdmi_audio_update(hdmi);
0152 }
0153 }
0154
0155 msm_hdmi_phy_powerup(phy, hdmi->pixclock);
0156
0157 msm_hdmi_set_mode(hdmi, true);
0158
0159 if (hdmi->hdcp_ctrl)
0160 msm_hdmi_hdcp_on(hdmi->hdcp_ctrl);
0161 }
0162
0163 static void msm_hdmi_bridge_post_disable(struct drm_bridge *bridge)
0164 {
0165 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
0166 struct hdmi *hdmi = hdmi_bridge->hdmi;
0167 struct hdmi_phy *phy = hdmi->phy;
0168
0169 if (hdmi->hdcp_ctrl)
0170 msm_hdmi_hdcp_off(hdmi->hdcp_ctrl);
0171
0172 DBG("power down");
0173 msm_hdmi_set_mode(hdmi, false);
0174
0175 msm_hdmi_phy_powerdown(phy);
0176
0177 if (hdmi->power_on) {
0178 power_off(bridge);
0179 hdmi->power_on = false;
0180 if (hdmi->hdmi_mode)
0181 msm_hdmi_audio_update(hdmi);
0182 msm_hdmi_phy_resource_disable(phy);
0183 }
0184 }
0185
0186 static void msm_hdmi_bridge_mode_set(struct drm_bridge *bridge,
0187 const struct drm_display_mode *mode,
0188 const struct drm_display_mode *adjusted_mode)
0189 {
0190 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
0191 struct hdmi *hdmi = hdmi_bridge->hdmi;
0192 int hstart, hend, vstart, vend;
0193 uint32_t frame_ctrl;
0194
0195 mode = adjusted_mode;
0196
0197 hdmi->pixclock = mode->clock * 1000;
0198
0199 hstart = mode->htotal - mode->hsync_start;
0200 hend = mode->htotal - mode->hsync_start + mode->hdisplay;
0201
0202 vstart = mode->vtotal - mode->vsync_start - 1;
0203 vend = mode->vtotal - mode->vsync_start + mode->vdisplay - 1;
0204
0205 DBG("htotal=%d, vtotal=%d, hstart=%d, hend=%d, vstart=%d, vend=%d",
0206 mode->htotal, mode->vtotal, hstart, hend, vstart, vend);
0207
0208 hdmi_write(hdmi, REG_HDMI_TOTAL,
0209 HDMI_TOTAL_H_TOTAL(mode->htotal - 1) |
0210 HDMI_TOTAL_V_TOTAL(mode->vtotal - 1));
0211
0212 hdmi_write(hdmi, REG_HDMI_ACTIVE_HSYNC,
0213 HDMI_ACTIVE_HSYNC_START(hstart) |
0214 HDMI_ACTIVE_HSYNC_END(hend));
0215 hdmi_write(hdmi, REG_HDMI_ACTIVE_VSYNC,
0216 HDMI_ACTIVE_VSYNC_START(vstart) |
0217 HDMI_ACTIVE_VSYNC_END(vend));
0218
0219 if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
0220 hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2,
0221 HDMI_VSYNC_TOTAL_F2_V_TOTAL(mode->vtotal));
0222 hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2,
0223 HDMI_VSYNC_ACTIVE_F2_START(vstart + 1) |
0224 HDMI_VSYNC_ACTIVE_F2_END(vend + 1));
0225 } else {
0226 hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2,
0227 HDMI_VSYNC_TOTAL_F2_V_TOTAL(0));
0228 hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2,
0229 HDMI_VSYNC_ACTIVE_F2_START(0) |
0230 HDMI_VSYNC_ACTIVE_F2_END(0));
0231 }
0232
0233 frame_ctrl = 0;
0234 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
0235 frame_ctrl |= HDMI_FRAME_CTRL_HSYNC_LOW;
0236 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
0237 frame_ctrl |= HDMI_FRAME_CTRL_VSYNC_LOW;
0238 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
0239 frame_ctrl |= HDMI_FRAME_CTRL_INTERLACED_EN;
0240 DBG("frame_ctrl=%08x", frame_ctrl);
0241 hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl);
0242
0243 if (hdmi->hdmi_mode)
0244 msm_hdmi_audio_update(hdmi);
0245 }
0246
0247 static struct edid *msm_hdmi_bridge_get_edid(struct drm_bridge *bridge,
0248 struct drm_connector *connector)
0249 {
0250 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
0251 struct hdmi *hdmi = hdmi_bridge->hdmi;
0252 struct edid *edid;
0253 uint32_t hdmi_ctrl;
0254
0255 hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
0256 hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
0257
0258 edid = drm_get_edid(connector, hdmi->i2c);
0259
0260 hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
0261
0262 hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
0263
0264 return edid;
0265 }
0266
0267 static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
0268 const struct drm_display_info *info,
0269 const struct drm_display_mode *mode)
0270 {
0271 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
0272 struct hdmi *hdmi = hdmi_bridge->hdmi;
0273 const struct hdmi_platform_config *config = hdmi->config;
0274 struct msm_drm_private *priv = bridge->dev->dev_private;
0275 struct msm_kms *kms = priv->kms;
0276 long actual, requested;
0277
0278 requested = 1000 * mode->clock;
0279
0280
0281
0282
0283
0284 if (kms->funcs->round_pixclk)
0285 actual = kms->funcs->round_pixclk(kms,
0286 requested, hdmi_bridge->hdmi->encoder);
0287 else if (config->pwr_clk_cnt > 0)
0288 actual = clk_round_rate(hdmi->pwr_clks[0], requested);
0289 else
0290 actual = requested;
0291
0292 DBG("requested=%ld, actual=%ld", requested, actual);
0293
0294 if (actual != requested)
0295 return MODE_CLOCK_RANGE;
0296
0297 return 0;
0298 }
0299
0300 static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
0301 .pre_enable = msm_hdmi_bridge_pre_enable,
0302 .post_disable = msm_hdmi_bridge_post_disable,
0303 .mode_set = msm_hdmi_bridge_mode_set,
0304 .mode_valid = msm_hdmi_bridge_mode_valid,
0305 .get_edid = msm_hdmi_bridge_get_edid,
0306 .detect = msm_hdmi_bridge_detect,
0307 };
0308
0309 static void
0310 msm_hdmi_hotplug_work(struct work_struct *work)
0311 {
0312 struct hdmi_bridge *hdmi_bridge =
0313 container_of(work, struct hdmi_bridge, hpd_work);
0314 struct drm_bridge *bridge = &hdmi_bridge->base;
0315
0316 drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge));
0317 }
0318
0319
0320 struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
0321 {
0322 struct drm_bridge *bridge = NULL;
0323 struct hdmi_bridge *hdmi_bridge;
0324 int ret;
0325
0326 hdmi_bridge = devm_kzalloc(hdmi->dev->dev,
0327 sizeof(*hdmi_bridge), GFP_KERNEL);
0328 if (!hdmi_bridge) {
0329 ret = -ENOMEM;
0330 goto fail;
0331 }
0332
0333 hdmi_bridge->hdmi = hdmi;
0334 INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work);
0335
0336 bridge = &hdmi_bridge->base;
0337 bridge->funcs = &msm_hdmi_bridge_funcs;
0338 bridge->ddc = hdmi->i2c;
0339 bridge->type = DRM_MODE_CONNECTOR_HDMIA;
0340 bridge->ops = DRM_BRIDGE_OP_HPD |
0341 DRM_BRIDGE_OP_DETECT |
0342 DRM_BRIDGE_OP_EDID;
0343
0344 drm_bridge_add(bridge);
0345
0346 ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
0347 if (ret)
0348 goto fail;
0349
0350 return bridge;
0351
0352 fail:
0353 if (bridge)
0354 msm_hdmi_bridge_destroy(bridge);
0355
0356 return ERR_PTR(ret);
0357 }