hdmi_bridge.c 9.5 KB

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