sun4i_hdmi_enc.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2016 Maxime Ripard
  4. *
  5. * Maxime Ripard <maxime.ripard@free-electrons.com>
  6. */
  7. #include <linux/clk.h>
  8. #include <linux/component.h>
  9. #include <linux/iopoll.h>
  10. #include <linux/module.h>
  11. #include <linux/of_device.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/pm_runtime.h>
  14. #include <linux/regmap.h>
  15. #include <linux/reset.h>
  16. #include <drm/drm_atomic_helper.h>
  17. #include <drm/drm_edid.h>
  18. #include <drm/drm_encoder.h>
  19. #include <drm/drm_of.h>
  20. #include <drm/drm_panel.h>
  21. #include <drm/drm_print.h>
  22. #include <drm/drm_probe_helper.h>
  23. #include <drm/drm_simple_kms_helper.h>
  24. #include "sun4i_backend.h"
  25. #include "sun4i_crtc.h"
  26. #include "sun4i_drv.h"
  27. #include "sun4i_hdmi.h"
  28. static inline struct sun4i_hdmi *
  29. drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
  30. {
  31. return container_of(encoder, struct sun4i_hdmi,
  32. encoder);
  33. }
  34. static inline struct sun4i_hdmi *
  35. drm_connector_to_sun4i_hdmi(struct drm_connector *connector)
  36. {
  37. return container_of(connector, struct sun4i_hdmi,
  38. connector);
  39. }
  40. static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
  41. struct drm_display_mode *mode)
  42. {
  43. struct hdmi_avi_infoframe frame;
  44. u8 buffer[17];
  45. int i, ret;
  46. ret = drm_hdmi_avi_infoframe_from_display_mode(&frame,
  47. &hdmi->connector, mode);
  48. if (ret < 0) {
  49. DRM_ERROR("Failed to get infoframes from mode\n");
  50. return ret;
  51. }
  52. ret = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
  53. if (ret < 0) {
  54. DRM_ERROR("Failed to pack infoframes\n");
  55. return ret;
  56. }
  57. for (i = 0; i < sizeof(buffer); i++)
  58. writeb(buffer[i], hdmi->base + SUN4I_HDMI_AVI_INFOFRAME_REG(i));
  59. return 0;
  60. }
  61. static int sun4i_hdmi_atomic_check(struct drm_encoder *encoder,
  62. struct drm_crtc_state *crtc_state,
  63. struct drm_connector_state *conn_state)
  64. {
  65. struct drm_display_mode *mode = &crtc_state->mode;
  66. if (mode->flags & DRM_MODE_FLAG_DBLCLK)
  67. return -EINVAL;
  68. return 0;
  69. }
  70. static void sun4i_hdmi_disable(struct drm_encoder *encoder)
  71. {
  72. struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
  73. u32 val;
  74. DRM_DEBUG_DRIVER("Disabling the HDMI Output\n");
  75. val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
  76. val &= ~SUN4I_HDMI_VID_CTRL_ENABLE;
  77. writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
  78. clk_disable_unprepare(hdmi->tmds_clk);
  79. }
  80. static void sun4i_hdmi_enable(struct drm_encoder *encoder)
  81. {
  82. struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
  83. struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
  84. u32 val = 0;
  85. DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
  86. clk_prepare_enable(hdmi->tmds_clk);
  87. sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
  88. val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
  89. val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
  90. writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0));
  91. val = SUN4I_HDMI_VID_CTRL_ENABLE;
  92. if (hdmi->hdmi_monitor)
  93. val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE;
  94. writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
  95. }
  96. static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
  97. struct drm_display_mode *mode,
  98. struct drm_display_mode *adjusted_mode)
  99. {
  100. struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
  101. unsigned int x, y;
  102. u32 val;
  103. clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
  104. clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
  105. /* Set input sync enable */
  106. writel(SUN4I_HDMI_UNKNOWN_INPUT_SYNC,
  107. hdmi->base + SUN4I_HDMI_UNKNOWN_REG);
  108. /*
  109. * Setup output pad (?) controls
  110. *
  111. * This is done here instead of at probe/bind time because
  112. * the controller seems to toggle some of the bits on its own.
  113. *
  114. * We can't just initialize the register there, we need to
  115. * protect the clock bits that have already been read out and
  116. * cached by the clock framework.
  117. */
  118. val = readl(hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
  119. val &= SUN4I_HDMI_PAD_CTRL1_HALVE_CLK;
  120. val |= hdmi->variant->pad_ctrl1_init_val;
  121. writel(val, hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
  122. val = readl(hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
  123. /* Setup timing registers */
  124. writel(SUN4I_HDMI_VID_TIMING_X(mode->hdisplay) |
  125. SUN4I_HDMI_VID_TIMING_Y(mode->vdisplay),
  126. hdmi->base + SUN4I_HDMI_VID_TIMING_ACT_REG);
  127. x = mode->htotal - mode->hsync_start;
  128. y = mode->vtotal - mode->vsync_start;
  129. writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y),
  130. hdmi->base + SUN4I_HDMI_VID_TIMING_BP_REG);
  131. x = mode->hsync_start - mode->hdisplay;
  132. y = mode->vsync_start - mode->vdisplay;
  133. writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y),
  134. hdmi->base + SUN4I_HDMI_VID_TIMING_FP_REG);
  135. x = mode->hsync_end - mode->hsync_start;
  136. y = mode->vsync_end - mode->vsync_start;
  137. writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y),
  138. hdmi->base + SUN4I_HDMI_VID_TIMING_SPW_REG);
  139. val = SUN4I_HDMI_VID_TIMING_POL_TX_CLK;
  140. if (mode->flags & DRM_MODE_FLAG_PHSYNC)
  141. val |= SUN4I_HDMI_VID_TIMING_POL_HSYNC;
  142. if (mode->flags & DRM_MODE_FLAG_PVSYNC)
  143. val |= SUN4I_HDMI_VID_TIMING_POL_VSYNC;
  144. writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG);
  145. }
  146. static enum drm_mode_status sun4i_hdmi_mode_valid(struct drm_encoder *encoder,
  147. const struct drm_display_mode *mode)
  148. {
  149. struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
  150. unsigned long rate = mode->clock * 1000;
  151. unsigned long diff = rate / 200; /* +-0.5% allowed by HDMI spec */
  152. long rounded_rate;
  153. /* 165 MHz is the typical max pixelclock frequency for HDMI <= 1.2 */
  154. if (rate > 165000000)
  155. return MODE_CLOCK_HIGH;
  156. rounded_rate = clk_round_rate(hdmi->tmds_clk, rate);
  157. if (rounded_rate > 0 &&
  158. max_t(unsigned long, rounded_rate, rate) -
  159. min_t(unsigned long, rounded_rate, rate) < diff)
  160. return MODE_OK;
  161. return MODE_NOCLOCK;
  162. }
  163. static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = {
  164. .atomic_check = sun4i_hdmi_atomic_check,
  165. .disable = sun4i_hdmi_disable,
  166. .enable = sun4i_hdmi_enable,
  167. .mode_set = sun4i_hdmi_mode_set,
  168. .mode_valid = sun4i_hdmi_mode_valid,
  169. };
  170. static int sun4i_hdmi_get_modes(struct drm_connector *connector)
  171. {
  172. struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
  173. struct edid *edid;
  174. int ret;
  175. edid = drm_get_edid(connector, hdmi->ddc_i2c ?: hdmi->i2c);
  176. if (!edid)
  177. return 0;
  178. hdmi->hdmi_monitor = drm_detect_hdmi_monitor(edid);
  179. DRM_DEBUG_DRIVER("Monitor is %s monitor\n",
  180. hdmi->hdmi_monitor ? "an HDMI" : "a DVI");
  181. drm_connector_update_edid_property(connector, edid);
  182. cec_s_phys_addr_from_edid(hdmi->cec_adap, edid);
  183. ret = drm_add_edid_modes(connector, edid);
  184. kfree(edid);
  185. return ret;
  186. }
  187. static struct i2c_adapter *sun4i_hdmi_get_ddc(struct device *dev)
  188. {
  189. struct device_node *phandle, *remote;
  190. struct i2c_adapter *ddc;
  191. remote = of_graph_get_remote_node(dev->of_node, 1, -1);
  192. if (!remote)
  193. return ERR_PTR(-EINVAL);
  194. phandle = of_parse_phandle(remote, "ddc-i2c-bus", 0);
  195. of_node_put(remote);
  196. if (!phandle)
  197. return ERR_PTR(-ENODEV);
  198. ddc = of_get_i2c_adapter_by_node(phandle);
  199. of_node_put(phandle);
  200. if (!ddc)
  201. return ERR_PTR(-EPROBE_DEFER);
  202. return ddc;
  203. }
  204. static const struct drm_connector_helper_funcs sun4i_hdmi_connector_helper_funcs = {
  205. .get_modes = sun4i_hdmi_get_modes,
  206. };
  207. static enum drm_connector_status
  208. sun4i_hdmi_connector_detect(struct drm_connector *connector, bool force)
  209. {
  210. struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
  211. unsigned long reg;
  212. reg = readl(hdmi->base + SUN4I_HDMI_HPD_REG);
  213. if (!(reg & SUN4I_HDMI_HPD_HIGH)) {
  214. cec_phys_addr_invalidate(hdmi->cec_adap);
  215. return connector_status_disconnected;
  216. }
  217. return connector_status_connected;
  218. }
  219. static const struct drm_connector_funcs sun4i_hdmi_connector_funcs = {
  220. .detect = sun4i_hdmi_connector_detect,
  221. .fill_modes = drm_helper_probe_single_connector_modes,
  222. .destroy = drm_connector_cleanup,
  223. .reset = drm_atomic_helper_connector_reset,
  224. .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
  225. .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
  226. };
  227. #ifdef CONFIG_DRM_SUN4I_HDMI_CEC
  228. static int sun4i_hdmi_cec_pin_read(struct cec_adapter *adap)
  229. {
  230. struct sun4i_hdmi *hdmi = cec_get_drvdata(adap);
  231. return readl(hdmi->base + SUN4I_HDMI_CEC) & SUN4I_HDMI_CEC_RX;
  232. }
  233. static void sun4i_hdmi_cec_pin_low(struct cec_adapter *adap)
  234. {
  235. struct sun4i_hdmi *hdmi = cec_get_drvdata(adap);
  236. /* Start driving the CEC pin low */
  237. writel(SUN4I_HDMI_CEC_ENABLE, hdmi->base + SUN4I_HDMI_CEC);
  238. }
  239. static void sun4i_hdmi_cec_pin_high(struct cec_adapter *adap)
  240. {
  241. struct sun4i_hdmi *hdmi = cec_get_drvdata(adap);
  242. /*
  243. * Stop driving the CEC pin, the pull up will take over
  244. * unless another CEC device is driving the pin low.
  245. */
  246. writel(0, hdmi->base + SUN4I_HDMI_CEC);
  247. }
  248. static const struct cec_pin_ops sun4i_hdmi_cec_pin_ops = {
  249. .read = sun4i_hdmi_cec_pin_read,
  250. .low = sun4i_hdmi_cec_pin_low,
  251. .high = sun4i_hdmi_cec_pin_high,
  252. };
  253. #endif
  254. #define SUN4I_HDMI_PAD_CTRL1_MASK (GENMASK(24, 7) | GENMASK(5, 0))
  255. #define SUN4I_HDMI_PLL_CTRL_MASK (GENMASK(31, 8) | GENMASK(3, 0))
  256. /* Only difference from sun5i is AMP is 4 instead of 6 */
  257. static const struct sun4i_hdmi_variant sun4i_variant = {
  258. .pad_ctrl0_init_val = SUN4I_HDMI_PAD_CTRL0_TXEN |
  259. SUN4I_HDMI_PAD_CTRL0_CKEN |
  260. SUN4I_HDMI_PAD_CTRL0_PWENG |
  261. SUN4I_HDMI_PAD_CTRL0_PWEND |
  262. SUN4I_HDMI_PAD_CTRL0_PWENC |
  263. SUN4I_HDMI_PAD_CTRL0_LDODEN |
  264. SUN4I_HDMI_PAD_CTRL0_LDOCEN |
  265. SUN4I_HDMI_PAD_CTRL0_BIASEN,
  266. .pad_ctrl1_init_val = SUN4I_HDMI_PAD_CTRL1_REG_AMP(4) |
  267. SUN4I_HDMI_PAD_CTRL1_REG_EMP(2) |
  268. SUN4I_HDMI_PAD_CTRL1_REG_DENCK |
  269. SUN4I_HDMI_PAD_CTRL1_REG_DEN |
  270. SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT |
  271. SUN4I_HDMI_PAD_CTRL1_EMP_OPT |
  272. SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT |
  273. SUN4I_HDMI_PAD_CTRL1_AMP_OPT,
  274. .pll_ctrl_init_val = SUN4I_HDMI_PLL_CTRL_VCO_S(8) |
  275. SUN4I_HDMI_PLL_CTRL_CS(7) |
  276. SUN4I_HDMI_PLL_CTRL_CP_S(15) |
  277. SUN4I_HDMI_PLL_CTRL_S(7) |
  278. SUN4I_HDMI_PLL_CTRL_VCO_GAIN(4) |
  279. SUN4I_HDMI_PLL_CTRL_SDIV2 |
  280. SUN4I_HDMI_PLL_CTRL_LDO2_EN |
  281. SUN4I_HDMI_PLL_CTRL_LDO1_EN |
  282. SUN4I_HDMI_PLL_CTRL_HV_IS_33 |
  283. SUN4I_HDMI_PLL_CTRL_BWS |
  284. SUN4I_HDMI_PLL_CTRL_PLL_EN,
  285. .ddc_clk_reg = REG_FIELD(SUN4I_HDMI_DDC_CLK_REG, 0, 6),
  286. .ddc_clk_pre_divider = 2,
  287. .ddc_clk_m_offset = 1,
  288. .field_ddc_en = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 31, 31),
  289. .field_ddc_start = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 30, 30),
  290. .field_ddc_reset = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 0, 0),
  291. .field_ddc_addr_reg = REG_FIELD(SUN4I_HDMI_DDC_ADDR_REG, 0, 31),
  292. .field_ddc_slave_addr = REG_FIELD(SUN4I_HDMI_DDC_ADDR_REG, 0, 6),
  293. .field_ddc_int_status = REG_FIELD(SUN4I_HDMI_DDC_INT_STATUS_REG, 0, 8),
  294. .field_ddc_fifo_clear = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 31, 31),
  295. .field_ddc_fifo_rx_thres = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 4, 7),
  296. .field_ddc_fifo_tx_thres = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 0, 3),
  297. .field_ddc_byte_count = REG_FIELD(SUN4I_HDMI_DDC_BYTE_COUNT_REG, 0, 9),
  298. .field_ddc_cmd = REG_FIELD(SUN4I_HDMI_DDC_CMD_REG, 0, 2),
  299. .field_ddc_sda_en = REG_FIELD(SUN4I_HDMI_DDC_LINE_CTRL_REG, 9, 9),
  300. .field_ddc_sck_en = REG_FIELD(SUN4I_HDMI_DDC_LINE_CTRL_REG, 8, 8),
  301. .ddc_fifo_reg = SUN4I_HDMI_DDC_FIFO_DATA_REG,
  302. .ddc_fifo_has_dir = true,
  303. };
  304. static const struct sun4i_hdmi_variant sun5i_variant = {
  305. .pad_ctrl0_init_val = SUN4I_HDMI_PAD_CTRL0_TXEN |
  306. SUN4I_HDMI_PAD_CTRL0_CKEN |
  307. SUN4I_HDMI_PAD_CTRL0_PWENG |
  308. SUN4I_HDMI_PAD_CTRL0_PWEND |
  309. SUN4I_HDMI_PAD_CTRL0_PWENC |
  310. SUN4I_HDMI_PAD_CTRL0_LDODEN |
  311. SUN4I_HDMI_PAD_CTRL0_LDOCEN |
  312. SUN4I_HDMI_PAD_CTRL0_BIASEN,
  313. .pad_ctrl1_init_val = SUN4I_HDMI_PAD_CTRL1_REG_AMP(6) |
  314. SUN4I_HDMI_PAD_CTRL1_REG_EMP(2) |
  315. SUN4I_HDMI_PAD_CTRL1_REG_DENCK |
  316. SUN4I_HDMI_PAD_CTRL1_REG_DEN |
  317. SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT |
  318. SUN4I_HDMI_PAD_CTRL1_EMP_OPT |
  319. SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT |
  320. SUN4I_HDMI_PAD_CTRL1_AMP_OPT,
  321. .pll_ctrl_init_val = SUN4I_HDMI_PLL_CTRL_VCO_S(8) |
  322. SUN4I_HDMI_PLL_CTRL_CS(7) |
  323. SUN4I_HDMI_PLL_CTRL_CP_S(15) |
  324. SUN4I_HDMI_PLL_CTRL_S(7) |
  325. SUN4I_HDMI_PLL_CTRL_VCO_GAIN(4) |
  326. SUN4I_HDMI_PLL_CTRL_SDIV2 |
  327. SUN4I_HDMI_PLL_CTRL_LDO2_EN |
  328. SUN4I_HDMI_PLL_CTRL_LDO1_EN |
  329. SUN4I_HDMI_PLL_CTRL_HV_IS_33 |
  330. SUN4I_HDMI_PLL_CTRL_BWS |
  331. SUN4I_HDMI_PLL_CTRL_PLL_EN,
  332. .ddc_clk_reg = REG_FIELD(SUN4I_HDMI_DDC_CLK_REG, 0, 6),
  333. .ddc_clk_pre_divider = 2,
  334. .ddc_clk_m_offset = 1,
  335. .field_ddc_en = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 31, 31),
  336. .field_ddc_start = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 30, 30),
  337. .field_ddc_reset = REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 0, 0),
  338. .field_ddc_addr_reg = REG_FIELD(SUN4I_HDMI_DDC_ADDR_REG, 0, 31),
  339. .field_ddc_slave_addr = REG_FIELD(SUN4I_HDMI_DDC_ADDR_REG, 0, 6),
  340. .field_ddc_int_status = REG_FIELD(SUN4I_HDMI_DDC_INT_STATUS_REG, 0, 8),
  341. .field_ddc_fifo_clear = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 31, 31),
  342. .field_ddc_fifo_rx_thres = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 4, 7),
  343. .field_ddc_fifo_tx_thres = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 0, 3),
  344. .field_ddc_byte_count = REG_FIELD(SUN4I_HDMI_DDC_BYTE_COUNT_REG, 0, 9),
  345. .field_ddc_cmd = REG_FIELD(SUN4I_HDMI_DDC_CMD_REG, 0, 2),
  346. .field_ddc_sda_en = REG_FIELD(SUN4I_HDMI_DDC_LINE_CTRL_REG, 9, 9),
  347. .field_ddc_sck_en = REG_FIELD(SUN4I_HDMI_DDC_LINE_CTRL_REG, 8, 8),
  348. .ddc_fifo_reg = SUN4I_HDMI_DDC_FIFO_DATA_REG,
  349. .ddc_fifo_has_dir = true,
  350. };
  351. static const struct sun4i_hdmi_variant sun6i_variant = {
  352. .has_ddc_parent_clk = true,
  353. .has_reset_control = true,
  354. .pad_ctrl0_init_val = 0xff |
  355. SUN4I_HDMI_PAD_CTRL0_TXEN |
  356. SUN4I_HDMI_PAD_CTRL0_CKEN |
  357. SUN4I_HDMI_PAD_CTRL0_PWENG |
  358. SUN4I_HDMI_PAD_CTRL0_PWEND |
  359. SUN4I_HDMI_PAD_CTRL0_PWENC |
  360. SUN4I_HDMI_PAD_CTRL0_LDODEN |
  361. SUN4I_HDMI_PAD_CTRL0_LDOCEN,
  362. .pad_ctrl1_init_val = SUN4I_HDMI_PAD_CTRL1_REG_AMP(6) |
  363. SUN4I_HDMI_PAD_CTRL1_REG_EMP(4) |
  364. SUN4I_HDMI_PAD_CTRL1_REG_DENCK |
  365. SUN4I_HDMI_PAD_CTRL1_REG_DEN |
  366. SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT |
  367. SUN4I_HDMI_PAD_CTRL1_EMP_OPT |
  368. SUN4I_HDMI_PAD_CTRL1_PWSDT |
  369. SUN4I_HDMI_PAD_CTRL1_PWSCK |
  370. SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT |
  371. SUN4I_HDMI_PAD_CTRL1_AMP_OPT |
  372. SUN4I_HDMI_PAD_CTRL1_UNKNOWN,
  373. .pll_ctrl_init_val = SUN4I_HDMI_PLL_CTRL_VCO_S(8) |
  374. SUN4I_HDMI_PLL_CTRL_CS(3) |
  375. SUN4I_HDMI_PLL_CTRL_CP_S(10) |
  376. SUN4I_HDMI_PLL_CTRL_S(4) |
  377. SUN4I_HDMI_PLL_CTRL_VCO_GAIN(4) |
  378. SUN4I_HDMI_PLL_CTRL_SDIV2 |
  379. SUN4I_HDMI_PLL_CTRL_LDO2_EN |
  380. SUN4I_HDMI_PLL_CTRL_LDO1_EN |
  381. SUN4I_HDMI_PLL_CTRL_HV_IS_33 |
  382. SUN4I_HDMI_PLL_CTRL_PLL_EN,
  383. .ddc_clk_reg = REG_FIELD(SUN6I_HDMI_DDC_CLK_REG, 0, 6),
  384. .ddc_clk_pre_divider = 1,
  385. .ddc_clk_m_offset = 2,
  386. .tmds_clk_div_offset = 1,
  387. .field_ddc_en = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 0, 0),
  388. .field_ddc_start = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 27, 27),
  389. .field_ddc_reset = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 31, 31),
  390. .field_ddc_addr_reg = REG_FIELD(SUN6I_HDMI_DDC_ADDR_REG, 1, 31),
  391. .field_ddc_slave_addr = REG_FIELD(SUN6I_HDMI_DDC_ADDR_REG, 1, 7),
  392. .field_ddc_int_status = REG_FIELD(SUN6I_HDMI_DDC_INT_STATUS_REG, 0, 8),
  393. .field_ddc_fifo_clear = REG_FIELD(SUN6I_HDMI_DDC_FIFO_CTRL_REG, 18, 18),
  394. .field_ddc_fifo_rx_thres = REG_FIELD(SUN6I_HDMI_DDC_FIFO_CTRL_REG, 4, 7),
  395. .field_ddc_fifo_tx_thres = REG_FIELD(SUN6I_HDMI_DDC_FIFO_CTRL_REG, 0, 3),
  396. .field_ddc_byte_count = REG_FIELD(SUN6I_HDMI_DDC_CMD_REG, 16, 25),
  397. .field_ddc_cmd = REG_FIELD(SUN6I_HDMI_DDC_CMD_REG, 0, 2),
  398. .field_ddc_sda_en = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 6, 6),
  399. .field_ddc_sck_en = REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 4, 4),
  400. .ddc_fifo_reg = SUN6I_HDMI_DDC_FIFO_DATA_REG,
  401. .ddc_fifo_thres_incl = true,
  402. };
  403. static const struct regmap_config sun4i_hdmi_regmap_config = {
  404. .reg_bits = 32,
  405. .val_bits = 32,
  406. .reg_stride = 4,
  407. .max_register = 0x580,
  408. };
  409. static int sun4i_hdmi_bind(struct device *dev, struct device *master,
  410. void *data)
  411. {
  412. struct platform_device *pdev = to_platform_device(dev);
  413. struct drm_device *drm = data;
  414. struct cec_connector_info conn_info;
  415. struct sun4i_drv *drv = drm->dev_private;
  416. struct sun4i_hdmi *hdmi;
  417. struct resource *res;
  418. u32 reg;
  419. int ret;
  420. hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
  421. if (!hdmi)
  422. return -ENOMEM;
  423. dev_set_drvdata(dev, hdmi);
  424. hdmi->dev = dev;
  425. hdmi->drv = drv;
  426. hdmi->variant = of_device_get_match_data(dev);
  427. if (!hdmi->variant)
  428. return -EINVAL;
  429. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  430. hdmi->base = devm_ioremap_resource(dev, res);
  431. if (IS_ERR(hdmi->base)) {
  432. dev_err(dev, "Couldn't map the HDMI encoder registers\n");
  433. return PTR_ERR(hdmi->base);
  434. }
  435. if (hdmi->variant->has_reset_control) {
  436. hdmi->reset = devm_reset_control_get(dev, NULL);
  437. if (IS_ERR(hdmi->reset)) {
  438. dev_err(dev, "Couldn't get the HDMI reset control\n");
  439. return PTR_ERR(hdmi->reset);
  440. }
  441. ret = reset_control_deassert(hdmi->reset);
  442. if (ret) {
  443. dev_err(dev, "Couldn't deassert HDMI reset\n");
  444. return ret;
  445. }
  446. }
  447. hdmi->bus_clk = devm_clk_get(dev, "ahb");
  448. if (IS_ERR(hdmi->bus_clk)) {
  449. dev_err(dev, "Couldn't get the HDMI bus clock\n");
  450. ret = PTR_ERR(hdmi->bus_clk);
  451. goto err_assert_reset;
  452. }
  453. clk_prepare_enable(hdmi->bus_clk);
  454. hdmi->mod_clk = devm_clk_get(dev, "mod");
  455. if (IS_ERR(hdmi->mod_clk)) {
  456. dev_err(dev, "Couldn't get the HDMI mod clock\n");
  457. ret = PTR_ERR(hdmi->mod_clk);
  458. goto err_disable_bus_clk;
  459. }
  460. clk_prepare_enable(hdmi->mod_clk);
  461. hdmi->pll0_clk = devm_clk_get(dev, "pll-0");
  462. if (IS_ERR(hdmi->pll0_clk)) {
  463. dev_err(dev, "Couldn't get the HDMI PLL 0 clock\n");
  464. ret = PTR_ERR(hdmi->pll0_clk);
  465. goto err_disable_mod_clk;
  466. }
  467. hdmi->pll1_clk = devm_clk_get(dev, "pll-1");
  468. if (IS_ERR(hdmi->pll1_clk)) {
  469. dev_err(dev, "Couldn't get the HDMI PLL 1 clock\n");
  470. ret = PTR_ERR(hdmi->pll1_clk);
  471. goto err_disable_mod_clk;
  472. }
  473. hdmi->regmap = devm_regmap_init_mmio(dev, hdmi->base,
  474. &sun4i_hdmi_regmap_config);
  475. if (IS_ERR(hdmi->regmap)) {
  476. dev_err(dev, "Couldn't create HDMI encoder regmap\n");
  477. ret = PTR_ERR(hdmi->regmap);
  478. goto err_disable_mod_clk;
  479. }
  480. ret = sun4i_tmds_create(hdmi);
  481. if (ret) {
  482. dev_err(dev, "Couldn't create the TMDS clock\n");
  483. goto err_disable_mod_clk;
  484. }
  485. if (hdmi->variant->has_ddc_parent_clk) {
  486. hdmi->ddc_parent_clk = devm_clk_get(dev, "ddc");
  487. if (IS_ERR(hdmi->ddc_parent_clk)) {
  488. dev_err(dev, "Couldn't get the HDMI DDC clock\n");
  489. ret = PTR_ERR(hdmi->ddc_parent_clk);
  490. goto err_disable_mod_clk;
  491. }
  492. } else {
  493. hdmi->ddc_parent_clk = hdmi->tmds_clk;
  494. }
  495. writel(SUN4I_HDMI_CTRL_ENABLE, hdmi->base + SUN4I_HDMI_CTRL_REG);
  496. writel(hdmi->variant->pad_ctrl0_init_val,
  497. hdmi->base + SUN4I_HDMI_PAD_CTRL0_REG);
  498. reg = readl(hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
  499. reg &= SUN4I_HDMI_PLL_CTRL_DIV_MASK;
  500. reg |= hdmi->variant->pll_ctrl_init_val;
  501. writel(reg, hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
  502. ret = sun4i_hdmi_i2c_create(dev, hdmi);
  503. if (ret) {
  504. dev_err(dev, "Couldn't create the HDMI I2C adapter\n");
  505. goto err_disable_mod_clk;
  506. }
  507. hdmi->ddc_i2c = sun4i_hdmi_get_ddc(dev);
  508. if (IS_ERR(hdmi->ddc_i2c)) {
  509. ret = PTR_ERR(hdmi->ddc_i2c);
  510. if (ret == -ENODEV)
  511. hdmi->ddc_i2c = NULL;
  512. else
  513. goto err_del_i2c_adapter;
  514. }
  515. drm_encoder_helper_add(&hdmi->encoder,
  516. &sun4i_hdmi_helper_funcs);
  517. ret = drm_simple_encoder_init(drm, &hdmi->encoder,
  518. DRM_MODE_ENCODER_TMDS);
  519. if (ret) {
  520. dev_err(dev, "Couldn't initialise the HDMI encoder\n");
  521. goto err_put_ddc_i2c;
  522. }
  523. hdmi->encoder.possible_crtcs = drm_of_find_possible_crtcs(drm,
  524. dev->of_node);
  525. if (!hdmi->encoder.possible_crtcs) {
  526. ret = -EPROBE_DEFER;
  527. goto err_put_ddc_i2c;
  528. }
  529. #ifdef CONFIG_DRM_SUN4I_HDMI_CEC
  530. hdmi->cec_adap = cec_pin_allocate_adapter(&sun4i_hdmi_cec_pin_ops,
  531. hdmi, "sun4i", CEC_CAP_DEFAULTS | CEC_CAP_CONNECTOR_INFO);
  532. ret = PTR_ERR_OR_ZERO(hdmi->cec_adap);
  533. if (ret < 0)
  534. goto err_cleanup_connector;
  535. writel(readl(hdmi->base + SUN4I_HDMI_CEC) & ~SUN4I_HDMI_CEC_TX,
  536. hdmi->base + SUN4I_HDMI_CEC);
  537. #endif
  538. drm_connector_helper_add(&hdmi->connector,
  539. &sun4i_hdmi_connector_helper_funcs);
  540. ret = drm_connector_init_with_ddc(drm, &hdmi->connector,
  541. &sun4i_hdmi_connector_funcs,
  542. DRM_MODE_CONNECTOR_HDMIA,
  543. hdmi->ddc_i2c);
  544. if (ret) {
  545. dev_err(dev,
  546. "Couldn't initialise the HDMI connector\n");
  547. goto err_cleanup_connector;
  548. }
  549. cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector);
  550. cec_s_conn_info(hdmi->cec_adap, &conn_info);
  551. /* There is no HPD interrupt, so we need to poll the controller */
  552. hdmi->connector.polled = DRM_CONNECTOR_POLL_CONNECT |
  553. DRM_CONNECTOR_POLL_DISCONNECT;
  554. ret = cec_register_adapter(hdmi->cec_adap, dev);
  555. if (ret < 0)
  556. goto err_cleanup_connector;
  557. drm_connector_attach_encoder(&hdmi->connector, &hdmi->encoder);
  558. return 0;
  559. err_cleanup_connector:
  560. cec_delete_adapter(hdmi->cec_adap);
  561. drm_encoder_cleanup(&hdmi->encoder);
  562. err_put_ddc_i2c:
  563. i2c_put_adapter(hdmi->ddc_i2c);
  564. err_del_i2c_adapter:
  565. i2c_del_adapter(hdmi->i2c);
  566. err_disable_mod_clk:
  567. clk_disable_unprepare(hdmi->mod_clk);
  568. err_disable_bus_clk:
  569. clk_disable_unprepare(hdmi->bus_clk);
  570. err_assert_reset:
  571. reset_control_assert(hdmi->reset);
  572. return ret;
  573. }
  574. static void sun4i_hdmi_unbind(struct device *dev, struct device *master,
  575. void *data)
  576. {
  577. struct sun4i_hdmi *hdmi = dev_get_drvdata(dev);
  578. cec_unregister_adapter(hdmi->cec_adap);
  579. i2c_del_adapter(hdmi->i2c);
  580. i2c_put_adapter(hdmi->ddc_i2c);
  581. clk_disable_unprepare(hdmi->mod_clk);
  582. clk_disable_unprepare(hdmi->bus_clk);
  583. }
  584. static const struct component_ops sun4i_hdmi_ops = {
  585. .bind = sun4i_hdmi_bind,
  586. .unbind = sun4i_hdmi_unbind,
  587. };
  588. static int sun4i_hdmi_probe(struct platform_device *pdev)
  589. {
  590. return component_add(&pdev->dev, &sun4i_hdmi_ops);
  591. }
  592. static int sun4i_hdmi_remove(struct platform_device *pdev)
  593. {
  594. component_del(&pdev->dev, &sun4i_hdmi_ops);
  595. return 0;
  596. }
  597. static const struct of_device_id sun4i_hdmi_of_table[] = {
  598. { .compatible = "allwinner,sun4i-a10-hdmi", .data = &sun4i_variant, },
  599. { .compatible = "allwinner,sun5i-a10s-hdmi", .data = &sun5i_variant, },
  600. { .compatible = "allwinner,sun6i-a31-hdmi", .data = &sun6i_variant, },
  601. { }
  602. };
  603. MODULE_DEVICE_TABLE(of, sun4i_hdmi_of_table);
  604. static struct platform_driver sun4i_hdmi_driver = {
  605. .probe = sun4i_hdmi_probe,
  606. .remove = sun4i_hdmi_remove,
  607. .driver = {
  608. .name = "sun4i-hdmi",
  609. .of_match_table = sun4i_hdmi_of_table,
  610. },
  611. };
  612. module_platform_driver(sun4i_hdmi_driver);
  613. MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
  614. MODULE_DESCRIPTION("Allwinner A10 HDMI Driver");
  615. MODULE_LICENSE("GPL");