1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
4 * Zheng Yang <zhengyang@rock-chips.com>
5 * Yakir Yang <ykk@rock-chips.com>
10 #include <linux/delay.h>
11 #include <linux/err.h>
12 #include <linux/hdmi.h>
13 #include <linux/mfd/syscon.h>
14 #include <linux/module.h>
15 #include <linux/mutex.h>
16 #include <linux/of_device.h>
17 #include <linux/component.h>
18 #include <linux/reset.h>
19 #include <drm/drm_scdc_helper.h>
20 #include <drm/bridge/dw_hdmi.h>
21 #include <drm/drm_atomic_helper.h>
22 #include <drm/drm_edid.h>
23 #include <drm/drm_of.h>
24 #include <drm/drm_probe_helper.h>
25 #include <drm/drm_simple_kms_helper.h>
26 #include <linux/regulator/consumer.h>
30 #include "inno_hdmi.h"
32 #define to_inno_hdmi(x) container_of(x, struct inno_hdmi, x)
34 struct hdmi_data_info {
38 unsigned int enc_in_format;
39 unsigned int enc_out_format;
40 unsigned int colorimetry;
43 struct inno_hdmi_i2c {
44 struct i2c_adapter adap;
50 struct completion cmp;
55 struct drm_device *drm_dev;
62 struct reset_control *tx_rst;
65 struct drm_connector connector;
66 struct drm_encoder encoder;
68 struct inno_hdmi_i2c *i2c;
69 struct i2c_adapter *ddc;
71 unsigned long tmds_rate;
73 struct hdmi_data_info hdmi_data;
74 struct drm_display_mode previous_mode;
75 struct regulator *hdmi_1p8;
76 struct regulator *hdmi_0p9;
77 const struct pre_pll_config *pre_cfg;
78 const struct post_pll_config *post_cfg;
82 CSC_ITU601_16_235_TO_RGB_0_255_8BIT,
83 CSC_ITU601_0_255_TO_RGB_0_255_8BIT,
84 CSC_ITU709_16_235_TO_RGB_0_255_8BIT,
85 CSC_RGB_0_255_TO_ITU601_16_235_8BIT,
86 CSC_RGB_0_255_TO_ITU709_16_235_8BIT,
87 CSC_RGB_0_255_TO_RGB_16_235_8BIT,
90 static const struct pre_pll_config pre_pll_cfg_table[] = {
91 { 25175000, 25175000, 1, 100, 2, 3, 3, 12, 3, 3, 4, 0, 0},
92 { 25200000, 25200000, 1, 100, 2, 3, 3, 12, 3, 3, 4, 0, 0},
93 { 27000000, 27000000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0},
94 { 27027000, 27027000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0},
95 { 27000000, 33750000, 1, 90, 1, 3, 3, 10, 3, 3, 4, 0, 0},
96 { 40000000, 40000000, 1, 80, 2, 2, 2, 12, 2, 2, 2, 0, 0},
97 { 59341000, 59341000, 1, 98, 3, 1, 2, 1, 3, 3, 4, 0, 0xE6AE6B},
98 { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0},
99 { 59341000, 74176250, 1, 98, 0, 3, 3, 1, 3, 3, 4, 0, 0xE6AE6B},
100 { 59400000, 74250000, 1, 99, 1, 2, 2, 1, 3, 3, 4, 0, 0},
101 { 74176000, 74176000, 1, 98, 1, 2, 2, 1, 2, 3, 4, 0, 0xE6AE6B},
102 { 74250000, 74250000, 1, 99, 1, 2, 2, 1, 2, 3, 4, 0, 0},
103 { 74176000, 92720000, 4, 494, 1, 2, 2, 1, 3, 3, 4, 0, 0x816817},
104 { 74250000, 92812500, 4, 495, 1, 2, 2, 1, 3, 3, 4, 0, 0},
105 {148352000, 148352000, 1, 98, 1, 1, 1, 1, 2, 2, 2, 0, 0xE6AE6B},
106 {148500000, 148500000, 1, 99, 1, 1, 1, 1, 2, 2, 2, 0, 0},
107 {148352000, 185440000, 4, 494, 0, 2, 2, 1, 3, 2, 2, 0, 0x816817},
108 {148500000, 185625000, 4, 495, 0, 2, 2, 1, 3, 2, 2, 0, 0},
109 {296703000, 296703000, 1, 98, 0, 1, 1, 1, 0, 2, 2, 0, 0xE6AE6B},
110 {297000000, 297000000, 1, 99, 1, 0, 0, 1, 2, 1, 1, 0, 0},
111 {296703000, 370878750, 4, 494, 1, 2, 0, 1, 3, 1, 1, 0, 0x816817},
112 {297000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 0, 0},
113 {593407000, 296703500, 1, 98, 0, 1, 1, 1, 0, 2, 1, 0, 0xE6AE6B},
114 {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 1, 0, 0},
115 {593407000, 370879375, 4, 494, 1, 2, 0, 1, 3, 1, 1, 1, 0x816817},
116 {594000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 1, 0},
117 {593407000, 593407000, 1, 98, 0, 2, 0, 1, 0, 1, 1, 0, 0xE6AE6B},
118 {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0},
122 static const struct post_pll_config post_pll_cfg_table[] = {
123 {25200000, 1, 80, 7, 3, 1},
124 {27000000, 1, 40, 11, 3, 1},
125 {33750000, 1, 40, 8, 3, 1},
126 //{33750000, 1, 80, 8, 2},
127 {74250000, 1, 20, 1, 3, 1},
128 //{74250000, 18, 80, 8, 2},
129 {148500000, 1, 20, 1, 3, 3},
130 {297000000, 4, 20, 0, 0, 3},
131 {594000000, 4, 20, 0, 0, 0},//postpll_postdiv_en = 0
135 static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
137 return readl_relaxed(hdmi->regs + (offset) * 0x04);
140 static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
142 writel_relaxed(val, hdmi->regs + (offset) * 0x04);
145 static inline void hdmi_modb(struct inno_hdmi *hdmi, u16 offset,
148 u8 temp = hdmi_readb(hdmi, offset) & ~msk;
151 hdmi_writeb(hdmi, offset, temp);
154 static void inno_hdmi_power_up(struct inno_hdmi *hdmi)
158 val = readl_relaxed(hdmi->regs + (0x1b0) * 0x04);
160 writel_relaxed(val, hdmi->regs + (0x1b0) * 0x04);
161 writel_relaxed(0xf, hdmi->regs + (0x1cc) * 0x04);
164 val = readl_relaxed(hdmi->regs + (0x1a0) * 0x04);
166 writel_relaxed(val, hdmi->regs + (0x1a0) * 0x04);
168 val = readl_relaxed(hdmi->regs + (0x1aa) * 0x04);
170 writel_relaxed(val, hdmi->regs + (0x1aa) * 0x04);
172 while (!(readl_relaxed(hdmi->regs + (0x1a9) * 0x04) & 0x1))
174 while (!(readl_relaxed(hdmi->regs + (0x1af) * 0x04) & 0x1))
178 writel_relaxed(0x7, hdmi->regs + (0x1b4) * 0x04);
179 /*turn on serializer*/
180 writel_relaxed(0x70, hdmi->regs + (0x1be) * 0x04);
183 static void inno_hdmi_tx_phy_power_down(struct inno_hdmi *hdmi)
185 hdmi_writeb(hdmi, 0x00, 0x63);
188 static void inno_hdmi_config_pll(struct inno_hdmi *hdmi)
190 u8 reg_1ad_value = hdmi->post_cfg->post_div_en ?
191 hdmi->post_cfg->postdiv : 0x00;
192 u8 reg_1aa_value = hdmi->post_cfg->post_div_en ?
194 if(1 == hdmi->hdmi_data.vic){
195 reg_1ad_value = 0x0d;
198 const reg_value_t cfg_pll_data[] = {
201 {0x1a1, hdmi->pre_cfg->prediv},
202 {0x1a2, 0xf0 | hdmi->pre_cfg->fbdiv>>8},
203 {0x1a3, hdmi->pre_cfg->fbdiv},
204 {0x1a4, ((hdmi->pre_cfg->tmds_div_a << 4) | (hdmi->pre_cfg->tmds_div_b << 2) | (hdmi->pre_cfg->tmds_div_c))},
205 {0x1a5, (hdmi->pre_cfg->pclk_div_b << 5) | hdmi->pre_cfg->pclk_div_a},
206 {0x1a6, (hdmi->pre_cfg->pclk_div_c << 5) | hdmi->pre_cfg->pclk_div_d},
207 {0x1ab, hdmi->post_cfg->prediv},
208 {0x1ac, hdmi->post_cfg->fbdiv & 0xff},
209 {0x1ad, reg_1ad_value},
210 {0x1aa, reg_1aa_value},
215 for (i = 0; i < sizeof(cfg_pll_data) / sizeof(reg_value_t); i++)
217 //dev_info(hdmi->dev, "%s %d reg[%02x],val[%02x]\n",__func__, __LINE__,cfg_pll_data[i].reg,cfg_pll_data[i].value);
218 //writel_relaxed(cfg_pll_data[i].value, hdmi->regs + (cfg_pll_data[i].reg) * 0x04);
219 hdmi_writeb(hdmi, cfg_pll_data[i].reg, cfg_pll_data[i].value);
224 static void inno_hdmi_config_1920x1080p60(struct inno_hdmi *hdmi)
227 const reg_value_t cfg_pll_data[] = {
228 /* config pll: 1080p, 60hz*/
245 for (i = 0; i < sizeof(cfg_pll_data) / sizeof(reg_value_t); i++)
246 writel_relaxed(cfg_pll_data[i].value, hdmi->regs + (cfg_pll_data[i].reg) * 0x04);
251 static void inno_hdmi_tx_ctrl(struct inno_hdmi *hdmi)
253 hdmi_writeb(hdmi, 0x9f, 0x06);
254 hdmi_writeb(hdmi, 0xa7, hdmi->hdmi_data.vic);
257 static void inno_hdmi_tx_phy_param_config(struct inno_hdmi *hdmi)
259 inno_hdmi_config_1920x1080p60(hdmi);
260 inno_hdmi_tx_ctrl(hdmi);
263 static void inno_hdmi_tx_phy_power_on(struct inno_hdmi *hdmi)
265 const reg_value_t pwon_data[] = {
269 for (i = 0; i < sizeof(pwon_data)/sizeof(reg_value_t); i++) {
270 //writel_relaxed(pwon_data[i].value, hdmi->regs + (pwon_data[i].reg) * 0x04);
271 hdmi_writeb(hdmi, pwon_data[i].reg, pwon_data[i].value);
276 void inno_hdmi_tmds_driver_on(struct inno_hdmi *hdmi)
278 //writel_relaxed(0x8f, hdmi->regs + (0x1b2) * 0x04);
279 hdmi_writeb(hdmi, 0x1b2, 0x8f);
283 static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi)
287 ddc_bus_freq = (hdmi->tmds_rate >> 2) / HDMI_SCL_RATE;
289 hdmi_writeb(hdmi, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
290 hdmi_writeb(hdmi, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
292 /* Clear the EDID interrupt flag and mute the interrupt */
293 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
294 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
297 static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable)
300 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
302 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF);
305 static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode)
309 inno_hdmi_sys_power(hdmi, true);
313 inno_hdmi_sys_power(hdmi, false);
317 DRM_DEV_ERROR(hdmi->dev, "Unknown power mode %d\n", mode);
321 static void inno_hdmi_init(struct inno_hdmi *hdmi)
323 inno_hdmi_power_up(hdmi);
324 inno_hdmi_tx_phy_power_down(hdmi);
325 inno_hdmi_tx_phy_param_config(hdmi);
327 inno_hdmi_tx_phy_power_on(hdmi);
328 inno_hdmi_tmds_driver_on(hdmi);
330 writel_relaxed(0x0, hdmi->regs + (0xce) * 0x04);
331 writel_relaxed(0x1, hdmi->regs + (0xce) * 0x04);
335 static void inno_hdmi_reset(struct inno_hdmi *hdmi)
341 val = v_INT_POL_HIGH;
342 hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val);
344 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
347 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
350 inno_hdmi_set_pwr_mode(hdmi, NORMAL);
354 struct pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi *hdmi,
357 const struct pre_pll_config *cfg = pre_pll_cfg_table;
358 rate = (rate / 1000) * 1000;
360 for (; cfg->pixclock != 0; cfg++)
361 if (cfg->tmdsclock == rate && cfg->pixclock == rate)
364 if (cfg->pixclock == 0)
365 return ERR_PTR(-EINVAL);
370 #define PRE_PLL_POWER_DOWN BIT(0)
372 /* phy tuning values for an undocumented set of registers */
373 static const struct phy_config inno_phy_cfg[] = {
375 0x07, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x08, 0x08,
376 0x00, 0xac, 0xcc, 0xcc, 0xcc,
380 0x0b, 0x0d, 0x0d, 0x0d, 0x07, 0x15, 0x08, 0x08, 0x08,
381 0x3f, 0xac, 0xcc, 0xcd, 0xdd,
385 0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08,
386 0x00, 0xac, 0xcc, 0xcc, 0xcc,
388 }, { /* sentinel */ },
391 static int inno_hdmi_phy_clk_set_rate(struct inno_hdmi *hdmi,unsigned long rate)
393 unsigned long tmdsclock;
394 hdmi->post_cfg = post_pll_cfg_table;
396 tmdsclock = hdmi->tmds_rate;
397 dev_info(hdmi->dev, "%s rate %lu tmdsclk %lu\n",__func__, rate, tmdsclock);
399 hdmi->pre_cfg = inno_hdmi_phy_get_pre_pll_cfg(hdmi, tmdsclock);
400 if (IS_ERR(hdmi->pre_cfg))
401 return PTR_ERR(hdmi->pre_cfg);
403 for (; hdmi->post_cfg->tmdsclock != 0; hdmi->post_cfg++)
404 if (tmdsclock <= hdmi->post_cfg->tmdsclock)
407 dev_info(hdmi->dev, "%s hdmi->pre_cfg->pixclock = %lu\n",__func__, hdmi->pre_cfg->pixclock);
408 dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmdsclock = %lu\n",__func__, hdmi->pre_cfg->tmdsclock);
409 dev_info(hdmi->dev, "%s hdmi->pre_cfg->prediv = %d\n",__func__, hdmi->pre_cfg->prediv);
410 dev_info(hdmi->dev, "%s hdmi->pre_cfg->fbdiv = %d\n",__func__, hdmi->pre_cfg->fbdiv);
411 dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmds_div_a = %d\n",__func__, hdmi->pre_cfg->tmds_div_a);
412 dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmds_div_b = %d\n",__func__, hdmi->pre_cfg->tmds_div_b);
413 dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmds_div_c = %d\n",__func__, hdmi->pre_cfg->tmds_div_c);
414 dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_a = %d\n",__func__, hdmi->pre_cfg->pclk_div_a);
415 dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_b = %d\n",__func__, hdmi->pre_cfg->pclk_div_b);
416 dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_c = %d\n",__func__, hdmi->pre_cfg->pclk_div_c);
417 dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_d = %d\n",__func__, hdmi->pre_cfg->pclk_div_d);
418 dev_info(hdmi->dev, "%s hdmi->pre_cfg->vco_div_5_en = %d\n",__func__, hdmi->pre_cfg->vco_div_5_en);
419 dev_info(hdmi->dev, "%s hdmi->pre_cfg->fracdiv = %d\n",__func__, hdmi->pre_cfg->fracdiv);
422 dev_info(hdmi->dev, "*******************************************************\n");
424 dev_info(hdmi->dev, "%s hdmi->post_cfg->tmdsclock = %lu\n",__func__, hdmi->post_cfg->tmdsclock);
425 dev_info(hdmi->dev, "%s hdmi->post_cfg->prediv = %d\n",__func__, hdmi->post_cfg->prediv);
426 dev_info(hdmi->dev, "%s hdmi->post_cfg->fbdiv = %d\n",__func__, hdmi->post_cfg->fbdiv);
427 dev_info(hdmi->dev, "%s hdmi->post_cfg->postdiv = %d\n",__func__, hdmi->post_cfg->postdiv);
428 dev_info(hdmi->dev, "%s hdmi->post_cfg->post_div_en = %d\n",__func__, hdmi->post_cfg->post_div_en);
429 dev_info(hdmi->dev, "%s hdmi->post_cfg->version = %d\n",__func__, hdmi->post_cfg->version);
431 inno_hdmi_config_pll(hdmi);
432 //inno_hdmi_tx_ctrl(hdmi);
434 #if 0 //pre pll + post pll configire
436 /*pre-pll power down*/
437 hdmi_modb(hdmi, 0x1a0, INNO_PRE_PLL_POWER_DOWN, INNO_PRE_PLL_POWER_DOWN);
439 /* Configure pre-pll */
440 hdmi_modb(hdmi, 0x1a0, INNO_PCLK_VCO_DIV_5_MASK, INNO_PCLK_VCO_DIV_5(hdmi->pre_cfg->vco_div_5_en));
441 hdmi_writeb(hdmi, 0x1a1, INNO_PRE_PLL_PRE_DIV(hdmi->pre_cfg->prediv));
444 val = INNO_SPREAD_SPECTRUM_MOD_DISABLE;
445 if (!hdmi->pre_cfg->fracdiv)
446 val |= INNO_PRE_PLL_FRAC_DIV_DISABLE;
447 hdmi_writeb(hdmi, 0x1a2, INNO_PRE_PLL_FB_DIV_11_8(hdmi->pre_cfg->fbdiv | val));
449 hdmi_writeb(hdmi, 0x1a3, INNO_PRE_PLL_FB_DIV_7_0(hdmi->pre_cfg->fbdiv));
451 hdmi_writeb(hdmi, 0x1a5, INNO_PRE_PLL_PCLK_DIV_A(hdmi->pre_cfg->pclk_div_a) |
452 INNO_PRE_PLL_PCLK_DIV_B(hdmi->pre_cfg->pclk_div_b));
454 hdmi_writeb(hdmi, 0x1a6, INNO_PRE_PLL_PCLK_DIV_C(hdmi->pre_cfg->pclk_div_c) |
455 INNO_PRE_PLL_PCLK_DIV_D(hdmi->pre_cfg->pclk_div_d));
457 hdmi_writeb(hdmi, 0x1a4, INNO_PRE_PLL_TMDSCLK_DIV_C(hdmi->pre_cfg->tmds_div_c) |
458 INNO_PRE_PLL_TMDSCLK_DIV_A(hdmi->pre_cfg->tmds_div_a) |
459 INNO_PRE_PLL_TMDSCLK_DIV_B(hdmi->pre_cfg->tmds_div_b));
461 hdmi_writeb(hdmi, 0x1d3, INNO_PRE_PLL_FRAC_DIV_7_0(hdmi->pre_cfg->fracdiv));
462 hdmi_writeb(hdmi, 0x1d2, INNO_PRE_PLL_FRAC_DIV_15_8(hdmi->pre_cfg->fracdiv));
463 hdmi_writeb(hdmi, 0x1d1, INNO_PRE_PLL_FRAC_DIV_23_16(hdmi->pre_cfg->fracdiv));
465 /*pre-pll power down*/
466 hdmi_modb(hdmi, 0x1a0, INNO_PRE_PLL_POWER_DOWN, 0);
468 const struct phy_config *phy_cfg = inno_phy_cfg;
470 for (; phy_cfg->tmdsclock != 0; phy_cfg++)
471 if (tmdsclock <= phy_cfg->tmdsclock)
474 hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_POWER_DOWN, INNO_POST_PLL_POWER_DOWN);
476 hdmi_writeb(hdmi, 0x1ac, INNO_POST_PLL_FB_DIV_7_0(hdmi->post_cfg->fbdiv));
478 if (hdmi->post_cfg->postdiv == 1) {
479 hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_REFCLK_SEL_TMDS, INNO_POST_PLL_REFCLK_SEL_TMDS);
480 hdmi_modb(hdmi, 0x1aa, BIT(4), INNO_POST_PLL_FB_DIV_8(hdmi->post_cfg->fbdiv));
481 hdmi_modb(hdmi, 0x1ab, INNO_POST_PLL_Pre_DIV_MASK, INNO_POST_PLL_PRE_DIV(hdmi->post_cfg->prediv));
483 v = (hdmi->post_cfg->postdiv / 2) - 1;
484 v &= INNO_POST_PLL_POST_DIV_MASK;
485 hdmi_modb(hdmi, 0x1ad, INNO_POST_PLL_POST_DIV_MASK, v);
486 hdmi_modb(hdmi, 0x1aa, BIT(4), INNO_POST_PLL_FB_DIV_8(hdmi->post_cfg->fbdiv));
487 hdmi_modb(hdmi, 0x1ab, INNO_POST_PLL_Pre_DIV_MASK, INNO_POST_PLL_PRE_DIV(hdmi->post_cfg->prediv));
488 hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_REFCLK_SEL_TMDS, INNO_POST_PLL_REFCLK_SEL_TMDS);
489 hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_POST_DIV_ENABLE, INNO_POST_PLL_POST_DIV_ENABLE);
492 for (v = 0; v < 14; v++){
493 hdmi_writeb(hdmi, 0x1b5 + v, phy_cfg->regs[v]);
496 if (phy_cfg->tmdsclock > 340000000) {
497 /* Set termination resistor to 100ohm */
498 v = clk_get_rate(hdmi->sys_clk) / 100000;
500 hdmi_writeb(hdmi, 0x1c5, INNO_TERM_RESISTOR_CALIB_SPEED_14_8(v)
501 | INNO_BYPASS_TERM_RESISTOR_CALIB);
503 hdmi_writeb(hdmi, 0x1c6, INNO_TERM_RESISTOR_CALIB_SPEED_7_0(v));
504 hdmi_writeb(hdmi, 0x1c7, INNO_TERM_RESISTOR_100);
505 hdmi_modb(hdmi, 0x1c5, INNO_BYPASS_TERM_RESISTOR_CALIB, 0);
507 hdmi_writeb(hdmi, 0x1c5, INNO_BYPASS_TERM_RESISTOR_CALIB);
509 /* clk termination resistor is 50ohm (parallel resistors) */
510 if (phy_cfg->tmdsclock > 165000000){
511 hdmi_modb(hdmi, 0x1c8,
512 INNO_ESD_DETECT_MASK,
513 INNO_TERM_RESISTOR_200);
515 /* data termination resistor for D2, D1 and D0 is 150ohm */
516 for (v = 0; v < 3; v++){
517 hdmi_modb(hdmi, 0x1c9 + v,
518 INNO_ESD_DETECT_MASK,
519 INNO_TERM_RESISTOR_200);
523 hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_POWER_DOWN, 0);
530 static int inno_hdmi_setup(struct inno_hdmi *hdmi,
531 struct drm_display_mode *mode)
535 val = readl_relaxed(hdmi->regs + (0x1b0) * 0x04);
537 hdmi_writeb(hdmi, 0x1b0, val);
538 hdmi_writeb(hdmi, 0x1cc, 0xf);
539 hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
541 hdmi->tmds_rate = mode->clock * 1000;
542 inno_hdmi_phy_clk_set_rate(hdmi,hdmi->tmds_rate);
544 while (!(hdmi_readb(hdmi, 0x1a9) & 0x1))
546 while (!(hdmi_readb(hdmi, 0x1af) & 0x1))
550 hdmi_writeb(hdmi, 0x1b4, 0x7);
551 /*turn on serializer*/
552 hdmi_writeb(hdmi, 0x1be, 0x70);
553 inno_hdmi_tx_phy_power_down(hdmi);
555 inno_hdmi_tx_ctrl(hdmi);
557 hdmi_writeb(hdmi, 0x35, 0x01);
558 hdmi_writeb(hdmi, 0x38, 0x04);
559 hdmi_writeb(hdmi, 0x40, 0x18);
560 hdmi_writeb(hdmi, 0x41, 0x80);
562 inno_hdmi_tx_phy_power_on(hdmi);
563 inno_hdmi_tmds_driver_on(hdmi);
565 hdmi_writeb(hdmi, 0xce, 0x0);
566 hdmi_writeb(hdmi, 0xce, 0x1);
571 static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder,
572 struct drm_display_mode *mode,
573 struct drm_display_mode *adj_mode)
575 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
577 inno_hdmi_setup(hdmi, adj_mode);
579 /* Store the display mode for plugin/DPMS poweron events */
580 memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
583 static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
585 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
587 inno_hdmi_set_pwr_mode(hdmi, NORMAL);
590 static void inno_hdmi_encoder_disable(struct drm_encoder *encoder)
592 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
594 inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR);
597 static bool inno_hdmi_encoder_mode_fixup(struct drm_encoder *encoder,
598 const struct drm_display_mode *mode,
599 struct drm_display_mode *adj_mode)
605 inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
606 struct drm_crtc_state *crtc_state,
607 struct drm_connector_state *conn_state)
612 static const struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
613 .enable = inno_hdmi_encoder_enable,
614 .disable = inno_hdmi_encoder_disable,
615 .mode_fixup = inno_hdmi_encoder_mode_fixup,
616 .mode_set = inno_hdmi_encoder_mode_set,
617 .atomic_check = inno_hdmi_encoder_atomic_check,
620 static enum drm_connector_status
621 inno_hdmi_connector_detect(struct drm_connector *connector, bool force)
623 struct inno_hdmi *hdmi = to_inno_hdmi(connector);
625 return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
626 connector_status_connected : connector_status_disconnected;
629 static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
631 struct inno_hdmi *hdmi = to_inno_hdmi(connector);
638 edid = drm_get_edid(connector, hdmi->ddc);
640 hdmi->hdmi_data.sink_is_hdmi = drm_detect_hdmi_monitor(edid);
641 hdmi->hdmi_data.sink_has_audio = drm_detect_monitor_audio(edid);
642 drm_connector_update_edid_property(connector, edid);
643 ret = drm_add_edid_modes(connector, edid);
650 static const struct dw_hdmi_mpll_config starfive_mpll_cfg[] = {
736 static enum drm_mode_status
737 inno_hdmi_connector_mode_valid(struct drm_connector *connector,
738 struct drm_display_mode *mode)
741 const struct dw_hdmi_mpll_config *mpll_cfg = starfive_mpll_cfg;
742 int pclk = mode->clock * 1000;
746 for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) {
747 if (pclk == mpll_cfg[i].mpixelclock) {
753 return (valid) ? MODE_OK : MODE_BAD;
755 u32 vic = drm_match_cea_mode(mode);
766 inno_hdmi_probe_single_connector_modes(struct drm_connector *connector,
767 uint32_t maxX, uint32_t maxY)
769 return drm_helper_probe_single_connector_modes(connector, 3840, 2160);//3840x2160
772 static void inno_hdmi_connector_destroy(struct drm_connector *connector)
774 drm_connector_unregister(connector);
775 drm_connector_cleanup(connector);
778 static const struct drm_connector_funcs inno_hdmi_connector_funcs = {
779 .fill_modes = inno_hdmi_probe_single_connector_modes,
780 .detect = inno_hdmi_connector_detect,
781 .destroy = inno_hdmi_connector_destroy,
782 .reset = drm_atomic_helper_connector_reset,
783 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
784 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
787 static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = {
788 .get_modes = inno_hdmi_connector_get_modes,
789 .mode_valid = inno_hdmi_connector_mode_valid,
792 static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi)
794 struct drm_encoder *encoder = &hdmi->encoder;
795 struct device *dev = hdmi->dev;
797 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
800 * If we failed to find the CRTC(s) which this encoder is
801 * supposed to be connected to, it's because the CRTC has
802 * not been registered yet. Defer probing, and hope that
803 * the required CRTC is added later.
805 if (encoder->possible_crtcs == 0)
806 return -EPROBE_DEFER;
808 drm_encoder_helper_add(encoder, &inno_hdmi_encoder_helper_funcs);
809 drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
811 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
813 drm_connector_helper_add(&hdmi->connector,
814 &inno_hdmi_connector_helper_funcs);
815 drm_connector_init_with_ddc(drm, &hdmi->connector,
816 &inno_hdmi_connector_funcs,
817 DRM_MODE_CONNECTOR_HDMIA,
820 drm_connector_attach_encoder(&hdmi->connector, encoder);
825 static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
827 struct inno_hdmi_i2c *i2c = hdmi->i2c;
830 stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
831 if (!(stat & m_INT_EDID_READY))
834 /* Clear HDMI EDID interrupt flag */
835 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
842 static irqreturn_t inno_hdmi_hardirq(int irq, void *dev_id)
844 struct inno_hdmi *hdmi = dev_id;
845 irqreturn_t ret = IRQ_NONE;
849 ret = inno_hdmi_i2c_irq(hdmi);
851 interrupt = hdmi_readb(hdmi, HDMI_STATUS);
852 if (interrupt & m_INT_HOTPLUG) {
853 hdmi_modb(hdmi, HDMI_STATUS, m_INT_HOTPLUG, m_INT_HOTPLUG);
854 ret = IRQ_WAKE_THREAD;
860 static irqreturn_t inno_hdmi_irq(int irq, void *dev_id)
862 struct inno_hdmi *hdmi = dev_id;
864 drm_helper_hpd_irq_event(hdmi->connector.dev);
869 static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
871 int length = msgs->len;
875 ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
880 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
885 static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
888 * The DDC module only support read EDID message, so
889 * we assume that each word write to this i2c adapter
890 * should be the offset of EDID word address.
892 if ((msgs->len != 1) ||
893 ((msgs->addr != DDC_ADDR) && (msgs->addr != DDC_SEGMENT_ADDR)))
896 reinit_completion(&hdmi->i2c->cmp);
898 if (msgs->addr == DDC_SEGMENT_ADDR)
899 hdmi->i2c->segment_addr = msgs->buf[0];
900 if (msgs->addr == DDC_ADDR)
901 hdmi->i2c->ddc_addr = msgs->buf[0];
903 /* Set edid fifo first addr */
904 hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
906 /* Set edid word address 0x00/0x80 */
907 hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
909 /* Set edid segment pointer */
910 hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
915 static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap,
916 struct i2c_msg *msgs, int num)
918 struct inno_hdmi *hdmi = i2c_get_adapdata(adap);
919 struct inno_hdmi_i2c *i2c = hdmi->i2c;
922 mutex_lock(&i2c->lock);
924 /* Clear the EDID interrupt flag and unmute the interrupt */
925 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, m_INT_EDID_READY);
926 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
928 for (i = 0; i < num; i++) {
929 DRM_DEV_DEBUG(hdmi->dev,
930 "xfer: num: %d/%d, len: %d, flags: %#x\n",
931 i + 1, num, msgs[i].len, msgs[i].flags);
933 if (msgs[i].flags & I2C_M_RD)
934 ret = inno_hdmi_i2c_read(hdmi, &msgs[i]);
936 ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
945 /* Mute HDMI EDID interrupt */
946 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
948 mutex_unlock(&i2c->lock);
953 static u32 inno_hdmi_i2c_func(struct i2c_adapter *adapter)
955 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
958 static const struct i2c_algorithm inno_hdmi_algorithm = {
959 .master_xfer = inno_hdmi_i2c_xfer,
960 .functionality = inno_hdmi_i2c_func,
963 static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
965 struct i2c_adapter *adap;
966 struct inno_hdmi_i2c *i2c;
969 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
971 return ERR_PTR(-ENOMEM);
973 mutex_init(&i2c->lock);
974 init_completion(&i2c->cmp);
977 adap->class = I2C_CLASS_DDC;
978 adap->owner = THIS_MODULE;
979 adap->dev.parent = hdmi->dev;
980 adap->algo = &inno_hdmi_algorithm;
981 strlcpy(adap->name, "Inno HDMI", sizeof(adap->name));
982 i2c_set_adapdata(adap, hdmi);
984 ret = i2c_add_adapter(adap);
986 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
987 devm_kfree(hdmi->dev, i2c);
993 DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver success\n", adap->name);
998 static int inno_hdmi_get_clk_rst(struct device *dev, struct inno_hdmi *hdmi)
1000 hdmi->sys_clk = devm_clk_get(dev, "sysclk");
1001 if (IS_ERR(hdmi->sys_clk)) {
1002 DRM_DEV_ERROR(dev, "Unable to get HDMI sysclk clk\n");
1003 return PTR_ERR(hdmi->sys_clk);
1005 hdmi->mclk = devm_clk_get(dev, "mclk");
1006 if (IS_ERR(hdmi->mclk)) {
1007 DRM_DEV_ERROR(dev, "Unable to get HDMI mclk clk\n");
1008 return PTR_ERR(hdmi->mclk);
1010 hdmi->bclk = devm_clk_get(dev, "bclk");
1011 if (IS_ERR(hdmi->bclk)) {
1012 DRM_DEV_ERROR(dev, "Unable to get HDMI bclk clk\n");
1013 return PTR_ERR(hdmi->bclk);
1015 hdmi->tx_rst = reset_control_get_exclusive(dev, "hdmi_tx");
1016 if (IS_ERR(hdmi->tx_rst)) {
1017 DRM_DEV_ERROR(dev, "Unable to get HDMI tx rst\n");
1018 return PTR_ERR(hdmi->tx_rst);
1023 static int inno_hdmi_en_clk_deas_rst(struct device *dev, struct inno_hdmi *hdmi)
1027 ret = clk_prepare_enable(hdmi->sys_clk);
1030 "Cannot enable HDMI sys clock: %d\n", ret);
1033 ret = clk_prepare_enable(hdmi->mclk);
1036 "Cannot enable HDMI mclk clock: %d\n", ret);
1039 ret = clk_prepare_enable(hdmi->bclk);
1042 "Cannot enable HDMI bclk clock: %d\n", ret);
1046 ret = reset_control_deassert(hdmi->tx_rst);
1048 dev_err(dev, "failed to deassert tx_rst\n");
1055 static int inno_hdmi_bind(struct device *dev, struct device *master,
1058 struct platform_device *pdev = to_platform_device(dev);
1059 struct drm_device *drm = data;
1060 struct inno_hdmi *hdmi;
1061 struct resource *iores;
1065 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
1070 hdmi->drm_dev = drm;
1072 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1073 hdmi->regs = devm_ioremap_resource(dev, iores);
1074 if (IS_ERR(hdmi->regs))
1075 return PTR_ERR(hdmi->regs);
1077 hdmi->hdmi_1p8 = devm_regulator_get(dev, "hdmi_1p8");
1078 if (IS_ERR(hdmi->hdmi_1p8))
1079 return PTR_ERR(hdmi->hdmi_1p8);
1081 hdmi->hdmi_0p9 = devm_regulator_get(dev, "hdmi_0p9");
1082 if (IS_ERR(hdmi->hdmi_0p9))
1083 return PTR_ERR(hdmi->hdmi_0p9);
1086 ret = regulator_enable(hdmi->hdmi_1p8);
1088 dev_err(dev, "Cannot enable hdmi_1p8 regulator\n");
1092 ret = regulator_enable(hdmi->hdmi_0p9);
1094 dev_err(dev, "Cannot enable hdmi_0p9 regulator\n");
1099 ret = inno_hdmi_get_clk_rst(dev, hdmi);
1100 ret = inno_hdmi_en_clk_deas_rst(dev, hdmi);
1102 irq = platform_get_irq(pdev, 0);
1105 goto err_disable_clk;
1107 #ifdef CONFIG_DRM_I2C_NXP_TDA998X
1108 hdmi->hdmi_data.vic = 0x10;
1109 inno_hdmi_init(hdmi);
1111 inno_hdmi_reset(hdmi);
1113 hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
1114 if (IS_ERR(hdmi->ddc)) {
1115 ret = PTR_ERR(hdmi->ddc);
1117 goto err_disable_clk;
1120 hdmi->tmds_rate = 51200000;
1122 inno_hdmi_i2c_init(hdmi);
1124 ret = inno_hdmi_register(drm, hdmi);
1126 goto err_put_adapter;
1128 dev_set_drvdata(dev, hdmi);
1130 /* Unmute hotplug interrupt */
1131 hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
1133 ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
1134 inno_hdmi_irq, IRQF_SHARED,
1135 dev_name(dev), hdmi);
1137 goto err_cleanup_hdmi;
1141 hdmi->connector.funcs->destroy(&hdmi->connector);
1142 hdmi->encoder.funcs->destroy(&hdmi->encoder);
1144 i2c_put_adapter(hdmi->ddc);
1146 //clk_disable_unprepare(hdmi->pclk);
1148 regulator_disable(hdmi->hdmi_1p8);
1153 static void inno_hdmi_unbind(struct device *dev, struct device *master,
1156 struct inno_hdmi *hdmi = dev_get_drvdata(dev);
1159 hdmi->connector.funcs->destroy(&hdmi->connector);
1160 hdmi->encoder.funcs->destroy(&hdmi->encoder);
1162 i2c_put_adapter(hdmi->ddc);
1164 ret = reset_control_assert(hdmi->tx_rst);
1166 dev_err(dev, "failed to assert tx_rst\n");
1168 clk_disable_unprepare(hdmi->sys_clk);
1169 clk_disable_unprepare(hdmi->mclk);
1170 clk_disable_unprepare(hdmi->bclk);
1172 regulator_disable(hdmi->hdmi_1p8);
1174 regulator_disable(hdmi->hdmi_0p9);
1177 static const struct component_ops inno_hdmi_ops = {
1178 .bind = inno_hdmi_bind,
1179 .unbind = inno_hdmi_unbind,
1182 static int inno_hdmi_probe(struct platform_device *pdev)
1184 return component_add(&pdev->dev, &inno_hdmi_ops);
1187 static int inno_hdmi_remove(struct platform_device *pdev)
1189 component_del(&pdev->dev, &inno_hdmi_ops);
1194 static const struct of_device_id inno_hdmi_dt_ids[] = {
1195 { .compatible = "inno,hdmi",
1199 MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
1201 struct platform_driver inno_hdmi_driver = {
1202 .probe = inno_hdmi_probe,
1203 .remove = inno_hdmi_remove,
1205 .name = "innohdmi-starfive",
1206 .of_match_table = inno_hdmi_dt_ids,