riscv:linux:drm
[platform/kernel/linux-starfive.git] / drivers / gpu / drm / verisilicon / inno_hdmi.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
4  *    Zheng Yang <zhengyang@rock-chips.com>
5  *    Yakir Yang <ykk@rock-chips.com>
6  */
7
8 #include <linux/irq.h>
9 #include <linux/clk.h>
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>
27
28 #include "vs_drv.h"
29
30 #include "inno_hdmi.h"
31
32 #define to_inno_hdmi(x) container_of(x, struct inno_hdmi, x)
33
34 struct hdmi_data_info {
35         int vic;
36         bool sink_is_hdmi;
37         bool sink_has_audio;
38         unsigned int enc_in_format;
39         unsigned int enc_out_format;
40         unsigned int colorimetry;
41 };
42
43 struct inno_hdmi_i2c {
44         struct i2c_adapter adap;
45
46         u8 ddc_addr;
47         u8 segment_addr;
48
49         struct mutex lock;
50         struct completion cmp;
51 };
52
53 struct inno_hdmi {
54         struct device *dev;
55         struct drm_device *drm_dev;
56
57         int irq;
58         struct clk *pclk;
59         struct clk *sys_clk;
60         struct clk *mclk;
61         struct clk *bclk;
62         struct reset_control *tx_rst;
63         void __iomem *regs;
64
65         struct drm_connector    connector;
66         struct drm_encoder      encoder;
67
68         struct inno_hdmi_i2c *i2c;
69         struct i2c_adapter *ddc;
70
71         unsigned long tmds_rate;
72
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;
79 };
80
81 enum {
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,
88 };
89
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         { 27000000,  33750000, 1,  90, 1, 3, 3, 10, 3, 3, 4, 0, 0},
95         { 40000000,  40000000, 1,  80, 2, 2, 2, 12, 2, 2, 2, 0, 0},
96         { 59341000,  59341000, 1,  98, 3, 1, 2,  1, 3, 3, 4, 0, 0xE6AE6B},
97         { 59400000,  59400000, 1,  99, 3, 1, 1,  1, 3, 3, 4, 0, 0},
98         { 59341000,  74176250, 1,  98, 0, 3, 3,  1, 3, 3, 4, 0, 0xE6AE6B},
99         { 59400000,  74250000, 1,  99, 1, 2, 2,  1, 3, 3, 4, 0, 0},
100         { 74176000,  74176000, 1,  98, 1, 2, 2,  1, 2, 3, 4, 0, 0xE6AE6B},
101         { 74250000,  74250000, 1,  99, 1, 2, 2,  1, 2, 3, 4, 0, 0},
102         { 74176000,  92720000, 4, 494, 1, 2, 2,  1, 3, 3, 4, 0, 0x816817},
103         { 74250000,  92812500, 4, 495, 1, 2, 2,  1, 3, 3, 4, 0, 0},
104         {148352000, 148352000, 1,  98, 1, 1, 1,  1, 2, 2, 2, 0, 0xE6AE6B},
105         {148500000, 148500000, 1,  99, 1, 1, 1,  1, 2, 2, 2, 0, 0},
106         {148352000, 185440000, 4, 494, 0, 2, 2,  1, 3, 2, 2, 0, 0x816817},
107         {148500000, 185625000, 4, 495, 0, 2, 2,  1, 3, 2, 2, 0, 0},
108         {296703000, 296703000, 1,  98, 0, 1, 1,  1, 0, 2, 2, 0, 0xE6AE6B},
109         {297000000, 297000000, 1,  99, 1, 0, 0,  1, 2, 1, 1, 0, 0},
110         {296703000, 370878750, 4, 494, 1, 2, 0,  1, 3, 1, 1, 0, 0x816817},
111         {297000000, 371250000, 4, 495, 1, 2, 0,  1, 3, 1, 1, 0, 0},
112         {593407000, 296703500, 1,  98, 0, 1, 1,  1, 0, 2, 1, 0, 0xE6AE6B},
113         {594000000, 297000000, 1,  99, 0, 1, 1,  1, 0, 2, 1, 0, 0},
114         {593407000, 370879375, 4, 494, 1, 2, 0,  1, 3, 1, 1, 1, 0x816817},
115         {594000000, 371250000, 4, 495, 1, 2, 0,  1, 3, 1, 1, 1, 0},
116         {593407000, 593407000, 1,  98, 0, 2, 0,  1, 0, 1, 1, 0, 0xE6AE6B},
117         {594000000, 594000000, 1,  99, 0, 2, 0,  1, 0, 1, 1, 0, 0},
118         { /* sentinel */ }
119 };
120
121 static const struct post_pll_config post_pll_cfg_table[] = {
122         {25200000,      1, 80, 7, 3, 1},
123         {27000000,      1, 40, 11, 3, 1},
124         {33750000,      1, 40, 8, 3, 1},
125         //{33750000,    1, 80, 8, 2},
126         {74250000,      1, 20, 1, 3, 1},
127         //{74250000, 18, 80, 8, 2},
128         {148500000, 1, 20, 1, 3, 3},
129         {297000000, 4, 20, 0, 0, 3},
130         {594000000, 4, 20, 0, 0, 0},//postpll_postdiv_en = 0
131         { /* sentinel */ }
132 };
133
134 static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
135 {
136         return readl_relaxed(hdmi->regs + (offset) * 0x04);
137 }
138
139 static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
140 {
141         writel_relaxed(val, hdmi->regs + (offset) * 0x04);
142 }
143
144 static inline void hdmi_modb(struct inno_hdmi *hdmi, u16 offset,
145                              u32 msk, u32 val)
146 {
147         u8 temp = hdmi_readb(hdmi, offset) & ~msk;
148
149         temp |= val & msk;
150         hdmi_writeb(hdmi, offset, temp);
151 }
152
153 static void inno_hdmi_power_up(struct inno_hdmi *hdmi)
154 {
155         u8 val;
156
157         val = readl_relaxed(hdmi->regs + (0x1b0) * 0x04);
158         val |= 0x4;
159         writel_relaxed(val, hdmi->regs + (0x1b0) * 0x04);
160         writel_relaxed(0xf, hdmi->regs + (0x1cc) * 0x04);
161
162         /*turn on pre-PLL*/
163         val = readl_relaxed(hdmi->regs + (0x1a0) * 0x04);
164         val &= ~(0x1);
165         writel_relaxed(val, hdmi->regs + (0x1a0) * 0x04);
166         /*turn on post-PLL*/
167         val = readl_relaxed(hdmi->regs + (0x1aa) * 0x04);
168         val &= ~(0x1);
169         writel_relaxed(val, hdmi->regs + (0x1aa) * 0x04);
170
171         while (!(readl_relaxed(hdmi->regs + (0x1a9) * 0x04) & 0x1))
172         ;
173         while (!(readl_relaxed(hdmi->regs + (0x1af) * 0x04) & 0x1))
174         ;
175
176         /*turn on LDO*/
177         writel_relaxed(0x7, hdmi->regs + (0x1b4) * 0x04);
178         /*turn on serializer*/
179         writel_relaxed(0x70, hdmi->regs + (0x1be) * 0x04);
180 }
181
182 static void inno_hdmi_tx_phy_power_down(struct inno_hdmi *hdmi)
183 {       
184         hdmi_writeb(hdmi, 0x00, 0x63);
185 }
186
187 static void inno_hdmi_config_pll(struct inno_hdmi *hdmi)
188 {
189         u8 reg_1ad_value = hdmi->post_cfg->post_div_en ?
190                  hdmi->post_cfg->postdiv : 0x00;
191         u8 reg_1aa_value = hdmi->post_cfg->post_div_en ?
192                  0x0e : 0x02;
193         if(1 == hdmi->hdmi_data.vic){
194                 reg_1ad_value = 0x0d;
195         }
196
197         const reg_value_t cfg_pll_data[] = {
198                 {0x1a0, 0x01},
199                 {0x1aa, 0x0f},
200                 {0x1a1, hdmi->pre_cfg->prediv},
201                 {0x1a2, 0xf0 | hdmi->pre_cfg->fbdiv>>8},
202                 {0x1a3, hdmi->pre_cfg->fbdiv},
203                 {0x1a4, ((hdmi->pre_cfg->tmds_div_a << 4) | (hdmi->pre_cfg->tmds_div_b << 2) | (hdmi->pre_cfg->tmds_div_c))},
204                 {0x1a5, (hdmi->pre_cfg->pclk_div_b << 5) | hdmi->pre_cfg->pclk_div_a},
205                 {0x1a6, (hdmi->pre_cfg->pclk_div_c << 5) | hdmi->pre_cfg->pclk_div_d},
206                 {0x1ab, hdmi->post_cfg->prediv},
207                 {0x1ac, hdmi->post_cfg->fbdiv & 0xff},
208                 {0x1ad, reg_1ad_value},
209                 {0x1aa, reg_1aa_value},
210                 {0x1a0, 0x00},
211         };
212
213         int i;
214         for (i = 0; i < sizeof(cfg_pll_data) / sizeof(reg_value_t); i++)
215         {
216                 //dev_info(hdmi->dev, "%s %d reg[%02x],val[%02x]\n",__func__, __LINE__,cfg_pll_data[i].reg,cfg_pll_data[i].value);
217                 //writel_relaxed(cfg_pll_data[i].value, hdmi->regs + (cfg_pll_data[i].reg) * 0x04);
218                 hdmi_writeb(hdmi, cfg_pll_data[i].reg, cfg_pll_data[i].value);
219         }
220         return;
221 }
222
223 static void inno_hdmi_config_1920x1080p60(struct inno_hdmi *hdmi)
224 {
225
226         const reg_value_t cfg_pll_data[] = {
227                 /* config pll: 1080p, 60hz*/
228                 {0x1a0, 0x01},
229                 {0x1aa, 0x0f},
230                 {0x1a1, 0x01},
231                 {0x1a2, 0xf0},
232                 {0x1a3, 0x63},
233                 {0x1a4, 0x15},
234                 {0x1a5, 0x41},
235                 {0x1a6, 0x42},
236                 {0x1ab, 0x01},
237                 {0x1ac, 0x0a},
238                 {0x1ad, 0x00},
239                 {0x1aa, 0x0e},
240                 {0x1a0, 0x00},
241         };
242
243         int i;
244         for (i = 0; i < sizeof(cfg_pll_data) / sizeof(reg_value_t); i++)
245                 writel_relaxed(cfg_pll_data[i].value, hdmi->regs + (cfg_pll_data[i].reg) * 0x04);
246
247         return;
248 }
249
250 static void inno_hdmi_tx_ctrl(struct inno_hdmi *hdmi)
251 {
252         hdmi_writeb(hdmi, 0x9f, 0x06);
253         hdmi_writeb(hdmi, 0xa7, hdmi->hdmi_data.vic);
254 }
255
256 static void inno_hdmi_tx_phy_param_config(struct inno_hdmi *hdmi)
257 {
258         inno_hdmi_config_1920x1080p60(hdmi);
259         inno_hdmi_tx_ctrl(hdmi);
260 }
261
262 static void inno_hdmi_tx_phy_power_on(struct inno_hdmi *hdmi)
263 {
264         const reg_value_t pwon_data[] = {
265                 {0x00, 0x61},
266         };
267         int i;
268         for (i = 0; i < sizeof(pwon_data)/sizeof(reg_value_t); i++) {
269                 //writel_relaxed(pwon_data[i].value, hdmi->regs + (pwon_data[i].reg) * 0x04);
270                 hdmi_writeb(hdmi, pwon_data[i].reg, pwon_data[i].value);
271         }
272         return;
273 }
274
275 void inno_hdmi_tmds_driver_on(struct inno_hdmi *hdmi)
276 {
277         //writel_relaxed(0x8f, hdmi->regs + (0x1b2) * 0x04);
278         hdmi_writeb(hdmi, 0x1b2, 0x8f);
279 }
280
281
282 static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi)
283 {
284         int ddc_bus_freq;
285
286         ddc_bus_freq = (hdmi->tmds_rate >> 2) / HDMI_SCL_RATE;
287
288         hdmi_writeb(hdmi, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
289         hdmi_writeb(hdmi, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
290
291         /* Clear the EDID interrupt flag and mute the interrupt */
292         hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
293         hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
294 }
295
296 static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable)
297 {
298         if (enable)
299                 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
300         else
301                 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF);
302 }
303
304 static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode)
305 {
306         switch (mode) {
307         case NORMAL:
308                 inno_hdmi_sys_power(hdmi, true);
309                 break;
310
311         case LOWER_PWR:
312                 inno_hdmi_sys_power(hdmi, false);
313                 break;
314
315         default:
316                 DRM_DEV_ERROR(hdmi->dev, "Unknown power mode %d\n", mode);
317         }
318 }
319
320 static void inno_hdmi_init(struct inno_hdmi *hdmi)
321 {
322         inno_hdmi_power_up(hdmi);
323         inno_hdmi_tx_phy_power_down(hdmi);
324         inno_hdmi_tx_phy_param_config(hdmi);
325
326         inno_hdmi_tx_phy_power_on(hdmi);
327         inno_hdmi_tmds_driver_on(hdmi);
328
329         writel_relaxed(0x0, hdmi->regs + (0xce) * 0x04);
330         writel_relaxed(0x1, hdmi->regs + (0xce) * 0x04);
331
332 }
333
334 static void inno_hdmi_reset(struct inno_hdmi *hdmi)
335 {
336         u32 val;
337         u32 msk;
338
339         msk = m_INT_POL;
340         val = v_INT_POL_HIGH;
341         hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val);
342
343         hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
344         udelay(100);
345
346         hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
347         udelay(100);
348
349         inno_hdmi_set_pwr_mode(hdmi, NORMAL);
350 }
351
352  static const
353  struct pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi *hdmi,
354                                                           unsigned long rate)
355 {
356         const struct pre_pll_config *cfg = pre_pll_cfg_table;
357         rate = (rate / 1000) * 1000;
358
359         for (; cfg->pixclock != 0; cfg++)
360                 if (cfg->tmdsclock == rate && cfg->pixclock == rate)
361                         break;
362
363         if (cfg->pixclock == 0)
364                 return ERR_PTR(-EINVAL);
365
366         return cfg;
367 }
368
369 #define PRE_PLL_POWER_DOWN                      BIT(0)
370
371  /* phy tuning values for an undocumented set of registers */
372  static const struct phy_config inno_phy_cfg[] = {
373          {       165000000, {
374                          0x07, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x08, 0x08,
375                          0x00, 0xac, 0xcc, 0xcc, 0xcc,
376                  },
377          }, {
378                  340000000, {
379                          0x0b, 0x0d, 0x0d, 0x0d, 0x07, 0x15, 0x08, 0x08, 0x08,
380                          0x3f, 0xac, 0xcc, 0xcd, 0xdd,
381                  },
382          }, {
383                  594000000, {
384                          0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08,
385                          0x00, 0xac, 0xcc, 0xcc, 0xcc,
386                  },
387          }, { /* sentinel */ },
388  };
389
390  static int inno_hdmi_phy_clk_set_rate(struct inno_hdmi *hdmi,unsigned long rate)
391  {
392         unsigned long tmdsclock;
393         hdmi->post_cfg = post_pll_cfg_table;
394
395         tmdsclock = hdmi->tmds_rate;
396         dev_info(hdmi->dev, "%s rate %lu tmdsclk %lu\n",__func__, rate, tmdsclock);
397
398         hdmi->pre_cfg = inno_hdmi_phy_get_pre_pll_cfg(hdmi, tmdsclock);
399         if (IS_ERR(hdmi->pre_cfg))
400         return PTR_ERR(hdmi->pre_cfg);
401
402         for (; hdmi->post_cfg->tmdsclock != 0; hdmi->post_cfg++)
403                 if (tmdsclock <= hdmi->post_cfg->tmdsclock)
404                         break;
405
406         dev_info(hdmi->dev, "%s hdmi->pre_cfg->pixclock = %lu\n",__func__, hdmi->pre_cfg->pixclock);
407         dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmdsclock = %lu\n",__func__, hdmi->pre_cfg->tmdsclock);
408         dev_info(hdmi->dev, "%s hdmi->pre_cfg->prediv = %d\n",__func__, hdmi->pre_cfg->prediv);
409         dev_info(hdmi->dev, "%s hdmi->pre_cfg->fbdiv = %d\n",__func__, hdmi->pre_cfg->fbdiv);
410         dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmds_div_a = %d\n",__func__, hdmi->pre_cfg->tmds_div_a);
411         dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmds_div_b = %d\n",__func__, hdmi->pre_cfg->tmds_div_b);
412         dev_info(hdmi->dev, "%s hdmi->pre_cfg->tmds_div_c = %d\n",__func__, hdmi->pre_cfg->tmds_div_c);
413         dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_a = %d\n",__func__, hdmi->pre_cfg->pclk_div_a);
414         dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_b = %d\n",__func__, hdmi->pre_cfg->pclk_div_b);
415         dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_c = %d\n",__func__, hdmi->pre_cfg->pclk_div_c);
416         dev_info(hdmi->dev, "%s hdmi->pre_cfg->pclk_div_d = %d\n",__func__, hdmi->pre_cfg->pclk_div_d);
417         dev_info(hdmi->dev, "%s hdmi->pre_cfg->vco_div_5_en = %d\n",__func__, hdmi->pre_cfg->vco_div_5_en);
418         dev_info(hdmi->dev, "%s hdmi->pre_cfg->fracdiv = %d\n",__func__, hdmi->pre_cfg->fracdiv);
419
420
421         dev_info(hdmi->dev, "*******************************************************\n");
422
423         dev_info(hdmi->dev, "%s hdmi->post_cfg->tmdsclock = %lu\n",__func__, hdmi->post_cfg->tmdsclock);
424         dev_info(hdmi->dev, "%s hdmi->post_cfg->prediv = %d\n",__func__, hdmi->post_cfg->prediv);
425         dev_info(hdmi->dev, "%s hdmi->post_cfg->fbdiv = %d\n",__func__, hdmi->post_cfg->fbdiv);
426         dev_info(hdmi->dev, "%s hdmi->post_cfg->postdiv = %d\n",__func__, hdmi->post_cfg->postdiv);
427         dev_info(hdmi->dev, "%s hdmi->post_cfg->post_div_en = %d\n",__func__, hdmi->post_cfg->post_div_en);
428         dev_info(hdmi->dev, "%s hdmi->post_cfg->version = %d\n",__func__, hdmi->post_cfg->version);
429
430         inno_hdmi_config_pll(hdmi);
431         //inno_hdmi_tx_ctrl(hdmi);
432
433 #if 0 //pre pll + post pll configire
434
435         /*pre-pll power down*/
436         hdmi_modb(hdmi, 0x1a0, INNO_PRE_PLL_POWER_DOWN, INNO_PRE_PLL_POWER_DOWN);
437
438         /* Configure pre-pll */
439         hdmi_modb(hdmi, 0x1a0, INNO_PCLK_VCO_DIV_5_MASK, INNO_PCLK_VCO_DIV_5(hdmi->pre_cfg->vco_div_5_en));
440         hdmi_writeb(hdmi, 0x1a1, INNO_PRE_PLL_PRE_DIV(hdmi->pre_cfg->prediv));
441
442         u32 val;
443         val = INNO_SPREAD_SPECTRUM_MOD_DISABLE;
444         if (!hdmi->pre_cfg->fracdiv)
445                 val |= INNO_PRE_PLL_FRAC_DIV_DISABLE;
446         hdmi_writeb(hdmi, 0x1a2, INNO_PRE_PLL_FB_DIV_11_8(hdmi->pre_cfg->fbdiv | val));
447
448         hdmi_writeb(hdmi, 0x1a3, INNO_PRE_PLL_FB_DIV_7_0(hdmi->pre_cfg->fbdiv));
449
450         hdmi_writeb(hdmi, 0x1a5, INNO_PRE_PLL_PCLK_DIV_A(hdmi->pre_cfg->pclk_div_a) |
451                         INNO_PRE_PLL_PCLK_DIV_B(hdmi->pre_cfg->pclk_div_b));
452
453         hdmi_writeb(hdmi, 0x1a6, INNO_PRE_PLL_PCLK_DIV_C(hdmi->pre_cfg->pclk_div_c) |
454                         INNO_PRE_PLL_PCLK_DIV_D(hdmi->pre_cfg->pclk_div_d));
455
456         hdmi_writeb(hdmi, 0x1a4, INNO_PRE_PLL_TMDSCLK_DIV_C(hdmi->pre_cfg->tmds_div_c) |
457                         INNO_PRE_PLL_TMDSCLK_DIV_A(hdmi->pre_cfg->tmds_div_a) |
458                         INNO_PRE_PLL_TMDSCLK_DIV_B(hdmi->pre_cfg->tmds_div_b));
459
460         hdmi_writeb(hdmi, 0x1d3, INNO_PRE_PLL_FRAC_DIV_7_0(hdmi->pre_cfg->fracdiv));
461         hdmi_writeb(hdmi, 0x1d2, INNO_PRE_PLL_FRAC_DIV_15_8(hdmi->pre_cfg->fracdiv));
462         hdmi_writeb(hdmi, 0x1d1, INNO_PRE_PLL_FRAC_DIV_23_16(hdmi->pre_cfg->fracdiv));
463
464         /*pre-pll power down*/
465         hdmi_modb(hdmi, 0x1a0, INNO_PRE_PLL_POWER_DOWN, 0);
466
467         const struct phy_config *phy_cfg = inno_phy_cfg;
468
469         for (; phy_cfg->tmdsclock != 0; phy_cfg++)
470                 if (tmdsclock <= phy_cfg->tmdsclock)
471                         break;
472
473         hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_POWER_DOWN, INNO_POST_PLL_POWER_DOWN);
474
475         hdmi_writeb(hdmi, 0x1ac, INNO_POST_PLL_FB_DIV_7_0(hdmi->post_cfg->fbdiv));
476
477         if (hdmi->post_cfg->postdiv == 1) {
478                 hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_REFCLK_SEL_TMDS, INNO_POST_PLL_REFCLK_SEL_TMDS);
479                 hdmi_modb(hdmi, 0x1aa, BIT(4), INNO_POST_PLL_FB_DIV_8(hdmi->post_cfg->fbdiv));
480                 hdmi_modb(hdmi, 0x1ab, INNO_POST_PLL_Pre_DIV_MASK, INNO_POST_PLL_PRE_DIV(hdmi->post_cfg->prediv));
481         } else {
482                 v = (hdmi->post_cfg->postdiv / 2) - 1;
483                 v &= INNO_POST_PLL_POST_DIV_MASK;
484                 hdmi_modb(hdmi, 0x1ad, INNO_POST_PLL_POST_DIV_MASK, v);
485                 hdmi_modb(hdmi, 0x1aa, BIT(4), INNO_POST_PLL_FB_DIV_8(hdmi->post_cfg->fbdiv));
486                 hdmi_modb(hdmi, 0x1ab, INNO_POST_PLL_Pre_DIV_MASK, INNO_POST_PLL_PRE_DIV(hdmi->post_cfg->prediv));
487                 hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_REFCLK_SEL_TMDS, INNO_POST_PLL_REFCLK_SEL_TMDS);
488                 hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_POST_DIV_ENABLE, INNO_POST_PLL_POST_DIV_ENABLE);
489         }
490
491         for (v = 0; v < 14; v++){
492                 hdmi_writeb(hdmi, 0x1b5 + v, phy_cfg->regs[v]);
493         }
494
495         if (phy_cfg->tmdsclock > 340000000) {
496                 /* Set termination resistor to 100ohm */
497                 v = clk_get_rate(hdmi->sys_clk) / 100000;
498         
499                 hdmi_writeb(hdmi, 0x1c5, INNO_TERM_RESISTOR_CALIB_SPEED_14_8(v)
500                            | INNO_BYPASS_TERM_RESISTOR_CALIB);
501         
502                 hdmi_writeb(hdmi, 0x1c6, INNO_TERM_RESISTOR_CALIB_SPEED_7_0(v));
503                 hdmi_writeb(hdmi, 0x1c7, INNO_TERM_RESISTOR_100);               
504                 hdmi_modb(hdmi, 0x1c5, INNO_BYPASS_TERM_RESISTOR_CALIB, 0);
505         } else {
506                 hdmi_writeb(hdmi, 0x1c5, INNO_BYPASS_TERM_RESISTOR_CALIB);
507
508                 /* clk termination resistor is 50ohm (parallel resistors) */
509                 if (phy_cfg->tmdsclock > 165000000){
510                         hdmi_modb(hdmi, 0x1c8,
511                                          INNO_ESD_DETECT_MASK,
512                                          INNO_TERM_RESISTOR_200);
513                 }
514                 /* data termination resistor for D2, D1 and D0 is 150ohm */
515                 for (v = 0; v < 3; v++){
516                         hdmi_modb(hdmi, 0x1c9 + v,
517                                          INNO_ESD_DETECT_MASK,
518                                          INNO_TERM_RESISTOR_200);
519                 }
520         }
521
522         hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_POWER_DOWN, 0);
523
524
525 #endif
526          return 0;
527  }
528
529 static int inno_hdmi_setup(struct inno_hdmi *hdmi,
530                            struct drm_display_mode *mode)
531 {
532         u8 val;
533
534         val = readl_relaxed(hdmi->regs + (0x1b0) * 0x04);
535         val |= 0x4;
536         hdmi_writeb(hdmi, 0x1b0, val);
537         hdmi_writeb(hdmi, 0x1cc, 0xf);
538         hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
539
540         hdmi->tmds_rate = mode->clock * 1000;
541         inno_hdmi_phy_clk_set_rate(hdmi,hdmi->tmds_rate);
542
543         while (!(hdmi_readb(hdmi, 0x1a9) & 0x1))
544         ;
545         while (!(hdmi_readb(hdmi, 0x1af) & 0x1))
546         ;
547
548         /*turn on LDO*/ 
549         hdmi_writeb(hdmi, 0x1b4, 0x7);
550         /*turn on serializer*/  
551         hdmi_writeb(hdmi, 0x1be, 0x70);
552         inno_hdmi_tx_phy_power_down(hdmi);
553
554         inno_hdmi_tx_ctrl(hdmi);
555
556         hdmi_writeb(hdmi, 0x35, 0x01);
557         hdmi_writeb(hdmi, 0x38, 0x04);
558         hdmi_writeb(hdmi, 0x40, 0x18);
559         hdmi_writeb(hdmi, 0x41, 0x80);
560
561         inno_hdmi_tx_phy_power_on(hdmi);
562         inno_hdmi_tmds_driver_on(hdmi);
563
564         hdmi_writeb(hdmi, 0xce, 0x0);
565         hdmi_writeb(hdmi, 0xce, 0x1);
566
567         return 0;
568 }
569
570 static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder,
571                                        struct drm_display_mode *mode,
572                                        struct drm_display_mode *adj_mode)
573 {
574         struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
575
576         inno_hdmi_setup(hdmi, adj_mode);
577
578         /* Store the display mode for plugin/DPMS poweron events */
579         memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
580 }
581
582 static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
583 {
584         struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
585
586         inno_hdmi_set_pwr_mode(hdmi, NORMAL);
587 }
588
589 static void inno_hdmi_encoder_disable(struct drm_encoder *encoder)
590 {
591         struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
592
593         hdmi_modb(hdmi, 0x1b2, 0xf, 0);
594         hdmi_modb(hdmi, 0x1be, 0xf, 0);
595         hdmi_modb(hdmi, 0x1b4, 0xf, 0);
596         hdmi_modb(hdmi, 0x1a0, 1, 1);
597         hdmi_modb(hdmi, 0x1aa, 1, 1);
598         hdmi_modb(hdmi, 0x1cc, 0x0f, 0);
599         hdmi_modb(hdmi, 0x1b0, 1<<2, 0);
600
601         inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR);
602 }
603
604 static bool inno_hdmi_encoder_mode_fixup(struct drm_encoder *encoder,
605                                          const struct drm_display_mode *mode,
606                                          struct drm_display_mode *adj_mode)
607 {
608         return true;
609 }
610
611 static int
612 inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
613                                struct drm_crtc_state *crtc_state,
614                                struct drm_connector_state *conn_state)
615 {
616         return 0;
617 }
618
619 static const struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
620         .enable     = inno_hdmi_encoder_enable,
621         .disable    = inno_hdmi_encoder_disable,
622         .mode_fixup = inno_hdmi_encoder_mode_fixup,
623         .mode_set   = inno_hdmi_encoder_mode_set,
624         .atomic_check = inno_hdmi_encoder_atomic_check,
625 };
626
627 static enum drm_connector_status
628 inno_hdmi_connector_detect(struct drm_connector *connector, bool force)
629 {
630         struct inno_hdmi *hdmi = to_inno_hdmi(connector);
631
632         return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
633                 connector_status_connected : connector_status_disconnected;
634 }
635
636 static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
637 {
638         struct inno_hdmi *hdmi = to_inno_hdmi(connector);
639         struct edid *edid;
640         int ret = 0;
641
642         if (!hdmi->ddc)
643                 return 0;
644
645         edid = drm_get_edid(connector, hdmi->ddc);
646         if (edid) {
647                 hdmi->hdmi_data.sink_is_hdmi = drm_detect_hdmi_monitor(edid);
648                 hdmi->hdmi_data.sink_has_audio = drm_detect_monitor_audio(edid);
649                 drm_connector_update_edid_property(connector, edid);
650                 ret = drm_add_edid_modes(connector, edid);
651                 kfree(edid);
652         }
653
654         return ret;
655 }
656
657 static const struct dw_hdmi_mpll_config starfive_mpll_cfg[] = {
658         {
659                 25200000, {
660                         { 0x00b3, 0x0000},
661                         { 0x2153, 0x0000},
662                         { 0x40f3, 0x0000}
663                 },
664         }, {
665                 27000000, {
666                         { 0x00b3, 0x0000},
667                         { 0x2153, 0x0000},
668                         { 0x40f3, 0x0000}
669                 },
670         }, {
671                 36000000, {
672                         { 0x00b3, 0x0000},
673                         { 0x2153, 0x0000},
674                         { 0x40f3, 0x0000}
675                 },
676         }, {
677                 40000000, {
678                         { 0x00b3, 0x0000},
679                         { 0x2153, 0x0000},
680                         { 0x40f3, 0x0000}
681                 },
682         }, {
683                 54000000, {
684                         { 0x0072, 0x0001},
685                         { 0x2142, 0x0001},
686                         { 0x40a2, 0x0001},
687                 },
688         }, {
689                 65000000, {
690                         { 0x0072, 0x0001},
691                         { 0x2142, 0x0001},
692                         { 0x40a2, 0x0001},
693                 },
694         }, {
695                 66000000, {
696                         { 0x013e, 0x0003},
697                         { 0x217e, 0x0002},
698                         { 0x4061, 0x0002}
699                 },
700         }, {
701                 74250000, {
702                         { 0x0072, 0x0001},
703                         { 0x2145, 0x0002},
704                         { 0x4061, 0x0002}
705                 },
706         }, {
707                 83500000, {
708                         { 0x0072, 0x0001},
709                 },
710         }, {
711                 108000000, {
712                         { 0x0051, 0x0002},
713                         { 0x2145, 0x0002},
714                         { 0x4061, 0x0002}
715                 },
716         }, {
717                 106500000, {
718                         { 0x0051, 0x0002},
719                         { 0x2145, 0x0002},
720                         { 0x4061, 0x0002}
721                 },
722         }, {
723                 146250000, {
724                         { 0x0051, 0x0002},
725                         { 0x2145, 0x0002},
726                         { 0x4061, 0x0002}
727                 },
728         }, {
729                 148500000, {
730                         { 0x0051, 0x0003},
731                         { 0x214c, 0x0003},
732                         { 0x4064, 0x0003}
733                 },
734         }, {
735                 ~0UL, {
736                         { 0x00a0, 0x000a },
737                         { 0x2001, 0x000f },
738                         { 0x4002, 0x000f },
739                 },
740         }
741 };
742
743 static enum drm_mode_status
744 inno_hdmi_connector_mode_valid(struct drm_connector *connector,
745                                struct drm_display_mode *mode)
746 {
747 #if 0
748         const struct dw_hdmi_mpll_config *mpll_cfg = starfive_mpll_cfg;
749         int pclk = mode->clock * 1000;
750         bool valid = false;
751         int i;
752
753         for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) {
754                 if (pclk == mpll_cfg[i].mpixelclock) {
755                         valid = true;
756                         break;
757                 }
758         }
759
760         return (valid) ? MODE_OK : MODE_BAD;
761 #endif
762         u32 vic = drm_match_cea_mode(mode);
763
764         if (vic >= 1)
765                 return MODE_OK;
766         else
767                 return MODE_BAD;
768
769         //return MODE_OK;
770 }
771
772 static int
773 inno_hdmi_probe_single_connector_modes(struct drm_connector *connector,
774                                        uint32_t maxX, uint32_t maxY)
775 {
776         return drm_helper_probe_single_connector_modes(connector, 3840, 2160);//3840x2160
777 }
778
779 static void inno_hdmi_connector_destroy(struct drm_connector *connector)
780 {
781         drm_connector_unregister(connector);
782         drm_connector_cleanup(connector);
783 }
784
785 static const struct drm_connector_funcs inno_hdmi_connector_funcs = {
786         .fill_modes = inno_hdmi_probe_single_connector_modes,
787         .detect = inno_hdmi_connector_detect,
788         .destroy = inno_hdmi_connector_destroy,
789         .reset = drm_atomic_helper_connector_reset,
790         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
791         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
792 };
793
794 static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = {
795         .get_modes = inno_hdmi_connector_get_modes,
796         .mode_valid = inno_hdmi_connector_mode_valid,
797 };
798
799 static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi)
800 {
801         struct drm_encoder *encoder = &hdmi->encoder;
802         struct device *dev = hdmi->dev;
803
804         encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
805
806         /*
807          * If we failed to find the CRTC(s) which this encoder is
808          * supposed to be connected to, it's because the CRTC has
809          * not been registered yet.  Defer probing, and hope that
810          * the required CRTC is added later.
811          */
812         if (encoder->possible_crtcs == 0)
813                 return -EPROBE_DEFER;
814
815         drm_encoder_helper_add(encoder, &inno_hdmi_encoder_helper_funcs);
816         drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
817
818         hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
819
820         drm_connector_helper_add(&hdmi->connector,
821                                  &inno_hdmi_connector_helper_funcs);
822         drm_connector_init_with_ddc(drm, &hdmi->connector,
823                                     &inno_hdmi_connector_funcs,
824                                     DRM_MODE_CONNECTOR_HDMIA,
825                                     hdmi->ddc);
826
827         drm_connector_attach_encoder(&hdmi->connector, encoder);
828
829         return 0;
830 }
831
832 static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
833 {
834         struct inno_hdmi_i2c *i2c = hdmi->i2c;
835         u8 stat;
836
837         stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
838         if (!(stat & m_INT_EDID_READY))
839                 return IRQ_NONE;
840
841         /* Clear HDMI EDID interrupt flag */
842         hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
843
844         complete(&i2c->cmp);
845
846         return IRQ_HANDLED;
847 }
848
849 static irqreturn_t inno_hdmi_hardirq(int irq, void *dev_id)
850 {
851         struct inno_hdmi *hdmi = dev_id;
852         irqreturn_t ret = IRQ_NONE;
853         u8 interrupt;
854
855         if (hdmi->i2c)
856                 ret = inno_hdmi_i2c_irq(hdmi);
857
858         interrupt = hdmi_readb(hdmi, HDMI_STATUS);
859         if (interrupt & m_INT_HOTPLUG) {
860                 hdmi_modb(hdmi, HDMI_STATUS, m_INT_HOTPLUG, m_INT_HOTPLUG);
861                 ret = IRQ_WAKE_THREAD;
862         }
863
864         return ret;
865 }
866
867 static irqreturn_t inno_hdmi_irq(int irq, void *dev_id)
868 {
869         struct inno_hdmi *hdmi = dev_id;
870
871         drm_helper_hpd_irq_event(hdmi->connector.dev);
872
873         return IRQ_HANDLED;
874 }
875
876 static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
877 {
878         int length = msgs->len;
879         u8 *buf = msgs->buf;
880         int ret;
881
882         ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
883         if (!ret)
884                 return -EAGAIN;
885
886         while (length--)
887                 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
888
889         return 0;
890 }
891
892 static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
893 {
894         /*
895          * The DDC module only support read EDID message, so
896          * we assume that each word write to this i2c adapter
897          * should be the offset of EDID word address.
898          */
899         if ((msgs->len != 1) ||
900             ((msgs->addr != DDC_ADDR) && (msgs->addr != DDC_SEGMENT_ADDR)))
901                 return -EINVAL;
902
903         reinit_completion(&hdmi->i2c->cmp);
904
905         if (msgs->addr == DDC_SEGMENT_ADDR)
906                 hdmi->i2c->segment_addr = msgs->buf[0];
907         if (msgs->addr == DDC_ADDR)
908                 hdmi->i2c->ddc_addr = msgs->buf[0];
909
910         /* Set edid fifo first addr */
911         hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
912
913         /* Set edid word address 0x00/0x80 */
914         hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
915
916         /* Set edid segment pointer */
917         hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
918
919         return 0;
920 }
921
922 static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap,
923                               struct i2c_msg *msgs, int num)
924 {
925         struct inno_hdmi *hdmi = i2c_get_adapdata(adap);
926         struct inno_hdmi_i2c *i2c = hdmi->i2c;
927         int i, ret = 0;
928
929         mutex_lock(&i2c->lock);
930
931         /* Clear the EDID interrupt flag and unmute the interrupt */
932         hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, m_INT_EDID_READY);
933         hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
934
935         for (i = 0; i < num; i++) {
936                 DRM_DEV_DEBUG(hdmi->dev,
937                               "xfer: num: %d/%d, len: %d, flags: %#x\n",
938                               i + 1, num, msgs[i].len, msgs[i].flags);
939
940                 if (msgs[i].flags & I2C_M_RD)
941                         ret = inno_hdmi_i2c_read(hdmi, &msgs[i]);
942                 else
943                         ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
944
945                 if (ret < 0)
946                         break;
947         }
948
949         if (!ret)
950                 ret = num;
951
952         /* Mute HDMI EDID interrupt */
953         hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
954
955         mutex_unlock(&i2c->lock);
956
957         return ret;
958 }
959
960 static u32 inno_hdmi_i2c_func(struct i2c_adapter *adapter)
961 {
962         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
963 }
964
965 static const struct i2c_algorithm inno_hdmi_algorithm = {
966         .master_xfer    = inno_hdmi_i2c_xfer,
967         .functionality  = inno_hdmi_i2c_func,
968 };
969
970 static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
971 {
972         struct i2c_adapter *adap;
973         struct inno_hdmi_i2c *i2c;
974         int ret;
975
976         i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
977         if (!i2c)
978                 return ERR_PTR(-ENOMEM);
979
980         mutex_init(&i2c->lock);
981         init_completion(&i2c->cmp);
982
983         adap = &i2c->adap;
984         adap->class = I2C_CLASS_DDC;
985         adap->owner = THIS_MODULE;
986         adap->dev.parent = hdmi->dev;
987         adap->algo = &inno_hdmi_algorithm;
988         strlcpy(adap->name, "Inno HDMI", sizeof(adap->name));
989         i2c_set_adapdata(adap, hdmi);
990
991         ret = i2c_add_adapter(adap);
992         if (ret) {
993                 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
994                 devm_kfree(hdmi->dev, i2c);
995                 return ERR_PTR(ret);
996         }
997
998         hdmi->i2c = i2c;
999
1000         DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver success\n", adap->name);
1001
1002         return adap;
1003 }
1004
1005 static int inno_hdmi_get_clk_rst(struct device *dev, struct inno_hdmi *hdmi)
1006 {
1007         hdmi->sys_clk = devm_clk_get(dev, "sysclk");
1008         if (IS_ERR(hdmi->sys_clk)) {
1009                 DRM_DEV_ERROR(dev, "Unable to get HDMI sysclk clk\n");
1010                 return PTR_ERR(hdmi->sys_clk);
1011         }
1012         hdmi->mclk = devm_clk_get(dev, "mclk");
1013         if (IS_ERR(hdmi->mclk)) {
1014                 DRM_DEV_ERROR(dev, "Unable to get HDMI mclk clk\n");
1015                 return PTR_ERR(hdmi->mclk);
1016         }
1017         hdmi->bclk = devm_clk_get(dev, "bclk");
1018         if (IS_ERR(hdmi->bclk)) {
1019                 DRM_DEV_ERROR(dev, "Unable to get HDMI bclk clk\n");
1020                 return PTR_ERR(hdmi->bclk);
1021         }
1022         hdmi->tx_rst = reset_control_get_exclusive(dev, "hdmi_tx");
1023         if (IS_ERR(hdmi->tx_rst)) {
1024                 DRM_DEV_ERROR(dev, "Unable to get HDMI tx rst\n");
1025                 return PTR_ERR(hdmi->tx_rst);
1026         }
1027         return 0;
1028 }
1029
1030 static int inno_hdmi_en_clk_deas_rst(struct device *dev, struct inno_hdmi *hdmi)
1031 {
1032         int ret;
1033
1034         ret = clk_prepare_enable(hdmi->sys_clk);
1035         if (ret) {
1036                 DRM_DEV_ERROR(dev,
1037                               "Cannot enable HDMI sys clock: %d\n", ret);
1038                 return ret;
1039         }
1040         ret = clk_prepare_enable(hdmi->mclk);
1041         if (ret) {
1042                 DRM_DEV_ERROR(dev,
1043                               "Cannot enable HDMI mclk clock: %d\n", ret);
1044                 return ret;
1045         }
1046         ret = clk_prepare_enable(hdmi->bclk);
1047         if (ret) {
1048                 DRM_DEV_ERROR(dev,
1049                               "Cannot enable HDMI bclk clock: %d\n", ret);
1050                 return ret;
1051         }
1052
1053         ret = reset_control_deassert(hdmi->tx_rst);
1054         if (ret < 0) {
1055                 dev_err(dev, "failed to deassert tx_rst\n");
1056                 return ret;
1057     }
1058         return ret;
1059 }
1060
1061
1062 static int inno_hdmi_bind(struct device *dev, struct device *master,
1063                                  void *data)
1064 {
1065         struct platform_device *pdev = to_platform_device(dev);
1066         struct drm_device *drm = data;
1067         struct inno_hdmi *hdmi;
1068         struct resource *iores;
1069         int irq;
1070         int ret;
1071
1072         hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
1073         if (!hdmi)
1074                 return -ENOMEM;
1075
1076         hdmi->dev = dev;
1077         hdmi->drm_dev = drm;
1078
1079         iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1080         hdmi->regs = devm_ioremap_resource(dev, iores);
1081         if (IS_ERR(hdmi->regs))
1082                 return PTR_ERR(hdmi->regs);
1083
1084         hdmi->hdmi_1p8 = devm_regulator_get(dev, "hdmi_1p8");
1085         if (IS_ERR(hdmi->hdmi_1p8))
1086                 return PTR_ERR(hdmi->hdmi_1p8);
1087
1088         hdmi->hdmi_0p9 = devm_regulator_get(dev, "hdmi_0p9");
1089         if (IS_ERR(hdmi->hdmi_0p9))
1090                 return PTR_ERR(hdmi->hdmi_0p9);
1091
1092         //pmic turn on
1093         ret = regulator_enable(hdmi->hdmi_1p8);
1094         if (ret) {
1095                 dev_err(dev, "Cannot enable hdmi_1p8 regulator\n");
1096                 goto err_reg_1p8;
1097         }
1098         udelay(100);
1099         ret = regulator_enable(hdmi->hdmi_0p9);
1100         if (ret) {
1101                 dev_err(dev, "Cannot enable hdmi_0p9 regulator\n");
1102                 goto err_reg_0p9;
1103         }
1104         udelay(100);
1105
1106         ret = inno_hdmi_get_clk_rst(dev, hdmi);
1107         ret = inno_hdmi_en_clk_deas_rst(dev, hdmi);
1108
1109         irq = platform_get_irq(pdev, 0);
1110         if (irq < 0) {
1111                 ret = irq;
1112                 goto err_disable_clk;
1113         }
1114 #ifdef CONFIG_DRM_I2C_NXP_TDA998X
1115         hdmi->hdmi_data.vic = 0x10;
1116         inno_hdmi_init(hdmi);
1117 #endif
1118         inno_hdmi_reset(hdmi);
1119
1120         hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
1121         if (IS_ERR(hdmi->ddc)) {
1122                 ret = PTR_ERR(hdmi->ddc);
1123                 hdmi->ddc = NULL;
1124                 goto err_disable_clk;
1125         }
1126
1127         hdmi->tmds_rate = 51200000;
1128
1129         inno_hdmi_i2c_init(hdmi);
1130
1131         ret = inno_hdmi_register(drm, hdmi);
1132         if (ret)
1133                 goto err_put_adapter;
1134
1135         dev_set_drvdata(dev, hdmi);
1136
1137         /* Unmute hotplug interrupt */
1138         hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
1139
1140         ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
1141                                         inno_hdmi_irq, IRQF_SHARED,
1142                                         dev_name(dev), hdmi);
1143         if (ret < 0)
1144                 goto err_cleanup_hdmi;
1145
1146         return 0;
1147 err_cleanup_hdmi:
1148         hdmi->connector.funcs->destroy(&hdmi->connector);
1149         hdmi->encoder.funcs->destroy(&hdmi->encoder);
1150 err_put_adapter:
1151         i2c_put_adapter(hdmi->ddc);
1152 err_disable_clk:
1153         //clk_disable_unprepare(hdmi->pclk);
1154 err_reg_0p9:
1155         regulator_disable(hdmi->hdmi_1p8);
1156 err_reg_1p8:
1157         return ret;
1158 }
1159
1160 static void inno_hdmi_unbind(struct device *dev, struct device *master,
1161                              void *data)
1162 {
1163         struct inno_hdmi *hdmi = dev_get_drvdata(dev);
1164         int ret;
1165
1166         hdmi->connector.funcs->destroy(&hdmi->connector);
1167         hdmi->encoder.funcs->destroy(&hdmi->encoder);
1168
1169         i2c_put_adapter(hdmi->ddc);
1170
1171         ret = reset_control_assert(hdmi->tx_rst);
1172         if (ret < 0)
1173                 dev_err(dev, "failed to assert tx_rst\n");
1174
1175         clk_disable_unprepare(hdmi->sys_clk);
1176         clk_disable_unprepare(hdmi->mclk);
1177         clk_disable_unprepare(hdmi->bclk);
1178
1179         regulator_disable(hdmi->hdmi_1p8);
1180         udelay(100);
1181         regulator_disable(hdmi->hdmi_0p9);
1182 }
1183
1184 static const struct component_ops inno_hdmi_ops = {
1185         .bind   = inno_hdmi_bind,
1186         .unbind = inno_hdmi_unbind,
1187 };
1188
1189 static int inno_hdmi_probe(struct platform_device *pdev)
1190 {
1191         return component_add(&pdev->dev, &inno_hdmi_ops);
1192 }
1193
1194 static int inno_hdmi_remove(struct platform_device *pdev)
1195 {
1196         component_del(&pdev->dev, &inno_hdmi_ops);
1197
1198         return 0;
1199 }
1200
1201 static const struct of_device_id inno_hdmi_dt_ids[] = {
1202         { .compatible = "inno,hdmi",
1203         },
1204         {},
1205 };
1206 MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
1207
1208 struct platform_driver inno_hdmi_driver = {
1209         .probe  = inno_hdmi_probe,
1210         .remove = inno_hdmi_remove,
1211         .driver = {
1212                 .name = "innohdmi-starfive",
1213                 .of_match_table = inno_hdmi_dt_ids,
1214         },
1215 };