22526b4d1d7569dd610a61e4f773f96c8609724f
[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         { 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},
119         { /* sentinel */ }
120 };
121
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
132         { /* sentinel */ }
133 };
134
135 static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
136 {
137         return readl_relaxed(hdmi->regs + (offset) * 0x04);
138 }
139
140 static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
141 {
142         writel_relaxed(val, hdmi->regs + (offset) * 0x04);
143 }
144
145 static inline void hdmi_modb(struct inno_hdmi *hdmi, u16 offset,
146                              u32 msk, u32 val)
147 {
148         u8 temp = hdmi_readb(hdmi, offset) & ~msk;
149
150         temp |= val & msk;
151         hdmi_writeb(hdmi, offset, temp);
152 }
153
154 static void inno_hdmi_power_up(struct inno_hdmi *hdmi)
155 {
156         u8 val;
157
158         val = readl_relaxed(hdmi->regs + (0x1b0) * 0x04);
159         val |= 0x4;
160         writel_relaxed(val, hdmi->regs + (0x1b0) * 0x04);
161         writel_relaxed(0xf, hdmi->regs + (0x1cc) * 0x04);
162
163         /*turn on pre-PLL*/
164         val = readl_relaxed(hdmi->regs + (0x1a0) * 0x04);
165         val &= ~(0x1);
166         writel_relaxed(val, hdmi->regs + (0x1a0) * 0x04);
167         /*turn on post-PLL*/
168         val = readl_relaxed(hdmi->regs + (0x1aa) * 0x04);
169         val &= ~(0x1);
170         writel_relaxed(val, hdmi->regs + (0x1aa) * 0x04);
171
172         while (!(readl_relaxed(hdmi->regs + (0x1a9) * 0x04) & 0x1))
173         ;
174         while (!(readl_relaxed(hdmi->regs + (0x1af) * 0x04) & 0x1))
175         ;
176
177         /*turn on LDO*/
178         writel_relaxed(0x7, hdmi->regs + (0x1b4) * 0x04);
179         /*turn on serializer*/
180         writel_relaxed(0x70, hdmi->regs + (0x1be) * 0x04);
181 }
182
183 static void inno_hdmi_tx_phy_power_down(struct inno_hdmi *hdmi)
184 {       
185         hdmi_writeb(hdmi, 0x00, 0x63);
186 }
187
188 static void inno_hdmi_config_pll(struct inno_hdmi *hdmi)
189 {
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 ?
193                  0x0e : 0x02;
194         if(1 == hdmi->hdmi_data.vic){
195                 reg_1ad_value = 0x0d;
196         }
197
198         const reg_value_t cfg_pll_data[] = {
199                 {0x1a0, 0x01},
200                 {0x1aa, 0x0f},
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},
211                 {0x1a0, 0x00},
212         };
213
214         int i;
215         for (i = 0; i < sizeof(cfg_pll_data) / sizeof(reg_value_t); i++)
216         {
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);
220         }
221         return;
222 }
223
224 static void inno_hdmi_config_1920x1080p60(struct inno_hdmi *hdmi)
225 {
226
227         const reg_value_t cfg_pll_data[] = {
228                 /* config pll: 1080p, 60hz*/
229                 {0x1a0, 0x01},
230                 {0x1aa, 0x0f},
231                 {0x1a1, 0x01},
232                 {0x1a2, 0xf0},
233                 {0x1a3, 0x63},
234                 {0x1a4, 0x15},
235                 {0x1a5, 0x41},
236                 {0x1a6, 0x42},
237                 {0x1ab, 0x01},
238                 {0x1ac, 0x0a},
239                 {0x1ad, 0x00},
240                 {0x1aa, 0x0e},
241                 {0x1a0, 0x00},
242         };
243
244         int i;
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);
247
248         return;
249 }
250
251 static void inno_hdmi_tx_ctrl(struct inno_hdmi *hdmi)
252 {
253         hdmi_writeb(hdmi, 0x9f, 0x06);
254         hdmi_writeb(hdmi, 0xa7, hdmi->hdmi_data.vic);
255 }
256
257 static void inno_hdmi_tx_phy_param_config(struct inno_hdmi *hdmi)
258 {
259         inno_hdmi_config_1920x1080p60(hdmi);
260         inno_hdmi_tx_ctrl(hdmi);
261 }
262
263 static void inno_hdmi_tx_phy_power_on(struct inno_hdmi *hdmi)
264 {
265         const reg_value_t pwon_data[] = {
266                 {0x00, 0x61},
267         };
268         int i;
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);
272         }
273         return;
274 }
275
276 void inno_hdmi_tmds_driver_on(struct inno_hdmi *hdmi)
277 {
278         //writel_relaxed(0x8f, hdmi->regs + (0x1b2) * 0x04);
279         hdmi_writeb(hdmi, 0x1b2, 0x8f);
280 }
281
282
283 static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi)
284 {
285         int ddc_bus_freq;
286
287         ddc_bus_freq = (hdmi->tmds_rate >> 2) / HDMI_SCL_RATE;
288
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);
291
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);
295 }
296
297 static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable)
298 {
299         if (enable)
300                 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
301         else
302                 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF);
303 }
304
305 static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode)
306 {
307         switch (mode) {
308         case NORMAL:
309                 inno_hdmi_sys_power(hdmi, true);
310                 break;
311
312         case LOWER_PWR:
313                 inno_hdmi_sys_power(hdmi, false);
314                 break;
315
316         default:
317                 DRM_DEV_ERROR(hdmi->dev, "Unknown power mode %d\n", mode);
318         }
319 }
320
321 static void inno_hdmi_init(struct inno_hdmi *hdmi)
322 {
323         inno_hdmi_power_up(hdmi);
324         inno_hdmi_tx_phy_power_down(hdmi);
325         inno_hdmi_tx_phy_param_config(hdmi);
326
327         inno_hdmi_tx_phy_power_on(hdmi);
328         inno_hdmi_tmds_driver_on(hdmi);
329
330         writel_relaxed(0x0, hdmi->regs + (0xce) * 0x04);
331         writel_relaxed(0x1, hdmi->regs + (0xce) * 0x04);
332
333 }
334
335 static void inno_hdmi_reset(struct inno_hdmi *hdmi)
336 {
337         u32 val;
338         u32 msk;
339
340         msk = m_INT_POL;
341         val = v_INT_POL_HIGH;
342         hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val);
343
344         hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
345         udelay(100);
346
347         hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
348         udelay(100);
349
350         inno_hdmi_set_pwr_mode(hdmi, NORMAL);
351 }
352
353  static const
354  struct pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi *hdmi,
355                                                           unsigned long rate)
356 {
357         const struct pre_pll_config *cfg = pre_pll_cfg_table;
358         rate = (rate / 1000) * 1000;
359
360         for (; cfg->pixclock != 0; cfg++)
361                 if (cfg->tmdsclock == rate && cfg->pixclock == rate)
362                         break;
363
364         if (cfg->pixclock == 0)
365                 return ERR_PTR(-EINVAL);
366
367         return cfg;
368 }
369
370 #define PRE_PLL_POWER_DOWN                      BIT(0)
371
372  /* phy tuning values for an undocumented set of registers */
373  static const struct phy_config inno_phy_cfg[] = {
374          {       165000000, {
375                          0x07, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x08, 0x08,
376                          0x00, 0xac, 0xcc, 0xcc, 0xcc,
377                  },
378          }, {
379                  340000000, {
380                          0x0b, 0x0d, 0x0d, 0x0d, 0x07, 0x15, 0x08, 0x08, 0x08,
381                          0x3f, 0xac, 0xcc, 0xcd, 0xdd,
382                  },
383          }, {
384                  594000000, {
385                          0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08,
386                          0x00, 0xac, 0xcc, 0xcc, 0xcc,
387                  },
388          }, { /* sentinel */ },
389  };
390
391  static int inno_hdmi_phy_clk_set_rate(struct inno_hdmi *hdmi,unsigned long rate)
392  {
393         unsigned long tmdsclock;
394         hdmi->post_cfg = post_pll_cfg_table;
395
396         tmdsclock = hdmi->tmds_rate;
397         dev_info(hdmi->dev, "%s rate %lu tmdsclk %lu\n",__func__, rate, tmdsclock);
398
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);
402
403         for (; hdmi->post_cfg->tmdsclock != 0; hdmi->post_cfg++)
404                 if (tmdsclock <= hdmi->post_cfg->tmdsclock)
405                         break;
406
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);
420
421
422         dev_info(hdmi->dev, "*******************************************************\n");
423
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);
430
431         inno_hdmi_config_pll(hdmi);
432         //inno_hdmi_tx_ctrl(hdmi);
433
434 #if 0 //pre pll + post pll configire
435
436         /*pre-pll power down*/
437         hdmi_modb(hdmi, 0x1a0, INNO_PRE_PLL_POWER_DOWN, INNO_PRE_PLL_POWER_DOWN);
438
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));
442
443         u32 val;
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));
448
449         hdmi_writeb(hdmi, 0x1a3, INNO_PRE_PLL_FB_DIV_7_0(hdmi->pre_cfg->fbdiv));
450
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));
453
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));
456
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));
460
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));
464
465         /*pre-pll power down*/
466         hdmi_modb(hdmi, 0x1a0, INNO_PRE_PLL_POWER_DOWN, 0);
467
468         const struct phy_config *phy_cfg = inno_phy_cfg;
469
470         for (; phy_cfg->tmdsclock != 0; phy_cfg++)
471                 if (tmdsclock <= phy_cfg->tmdsclock)
472                         break;
473
474         hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_POWER_DOWN, INNO_POST_PLL_POWER_DOWN);
475
476         hdmi_writeb(hdmi, 0x1ac, INNO_POST_PLL_FB_DIV_7_0(hdmi->post_cfg->fbdiv));
477
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));
482         } else {
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);
490         }
491
492         for (v = 0; v < 14; v++){
493                 hdmi_writeb(hdmi, 0x1b5 + v, phy_cfg->regs[v]);
494         }
495
496         if (phy_cfg->tmdsclock > 340000000) {
497                 /* Set termination resistor to 100ohm */
498                 v = clk_get_rate(hdmi->sys_clk) / 100000;
499         
500                 hdmi_writeb(hdmi, 0x1c5, INNO_TERM_RESISTOR_CALIB_SPEED_14_8(v)
501                            | INNO_BYPASS_TERM_RESISTOR_CALIB);
502         
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);
506         } else {
507                 hdmi_writeb(hdmi, 0x1c5, INNO_BYPASS_TERM_RESISTOR_CALIB);
508
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);
514                 }
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);
520                 }
521         }
522
523         hdmi_modb(hdmi, 0x1aa, INNO_POST_PLL_POWER_DOWN, 0);
524
525
526 #endif
527          return 0;
528  }
529
530 static int inno_hdmi_setup(struct inno_hdmi *hdmi,
531                            struct drm_display_mode *mode)
532 {
533         u8 val;
534
535         val = readl_relaxed(hdmi->regs + (0x1b0) * 0x04);
536         val |= 0x4;
537         hdmi_writeb(hdmi, 0x1b0, val);
538         hdmi_writeb(hdmi, 0x1cc, 0xf);
539         hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
540
541         hdmi->tmds_rate = mode->clock * 1000;
542         inno_hdmi_phy_clk_set_rate(hdmi,hdmi->tmds_rate);
543
544         while (!(hdmi_readb(hdmi, 0x1a9) & 0x1))
545         ;
546         while (!(hdmi_readb(hdmi, 0x1af) & 0x1))
547         ;
548
549         /*turn on LDO*/ 
550         hdmi_writeb(hdmi, 0x1b4, 0x7);
551         /*turn on serializer*/  
552         hdmi_writeb(hdmi, 0x1be, 0x70);
553         inno_hdmi_tx_phy_power_down(hdmi);
554
555         inno_hdmi_tx_ctrl(hdmi);
556
557         hdmi_writeb(hdmi, 0x35, 0x01);
558         hdmi_writeb(hdmi, 0x38, 0x04);
559         hdmi_writeb(hdmi, 0x40, 0x18);
560         hdmi_writeb(hdmi, 0x41, 0x80);
561
562         inno_hdmi_tx_phy_power_on(hdmi);
563         inno_hdmi_tmds_driver_on(hdmi);
564
565         hdmi_writeb(hdmi, 0xce, 0x0);
566         hdmi_writeb(hdmi, 0xce, 0x1);
567
568         return 0;
569 }
570
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)
574 {
575         struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
576
577         inno_hdmi_setup(hdmi, adj_mode);
578
579         /* Store the display mode for plugin/DPMS poweron events */
580         memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
581 }
582
583 static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
584 {
585         struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
586
587         inno_hdmi_set_pwr_mode(hdmi, NORMAL);
588 }
589
590 static void inno_hdmi_encoder_disable(struct drm_encoder *encoder)
591 {
592         struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
593
594         inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR);
595 }
596
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)
600 {
601         return true;
602 }
603
604 static int
605 inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
606                                struct drm_crtc_state *crtc_state,
607                                struct drm_connector_state *conn_state)
608 {
609         return 0;
610 }
611
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,
618 };
619
620 static enum drm_connector_status
621 inno_hdmi_connector_detect(struct drm_connector *connector, bool force)
622 {
623         struct inno_hdmi *hdmi = to_inno_hdmi(connector);
624
625         return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
626                 connector_status_connected : connector_status_disconnected;
627 }
628
629 static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
630 {
631         struct inno_hdmi *hdmi = to_inno_hdmi(connector);
632         struct edid *edid;
633         int ret = 0;
634
635         if (!hdmi->ddc)
636                 return 0;
637
638         edid = drm_get_edid(connector, hdmi->ddc);
639         if (edid) {
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);
644                 kfree(edid);
645         }
646
647         return ret;
648 }
649
650 static const struct dw_hdmi_mpll_config starfive_mpll_cfg[] = {
651         {
652                 25200000, {
653                         { 0x00b3, 0x0000},
654                         { 0x2153, 0x0000},
655                         { 0x40f3, 0x0000}
656                 },
657         }, {
658                 27000000, {
659                         { 0x00b3, 0x0000},
660                         { 0x2153, 0x0000},
661                         { 0x40f3, 0x0000}
662                 },
663         }, {
664                 36000000, {
665                         { 0x00b3, 0x0000},
666                         { 0x2153, 0x0000},
667                         { 0x40f3, 0x0000}
668                 },
669         }, {
670                 40000000, {
671                         { 0x00b3, 0x0000},
672                         { 0x2153, 0x0000},
673                         { 0x40f3, 0x0000}
674                 },
675         }, {
676                 54000000, {
677                         { 0x0072, 0x0001},
678                         { 0x2142, 0x0001},
679                         { 0x40a2, 0x0001},
680                 },
681         }, {
682                 65000000, {
683                         { 0x0072, 0x0001},
684                         { 0x2142, 0x0001},
685                         { 0x40a2, 0x0001},
686                 },
687         }, {
688                 66000000, {
689                         { 0x013e, 0x0003},
690                         { 0x217e, 0x0002},
691                         { 0x4061, 0x0002}
692                 },
693         }, {
694                 74250000, {
695                         { 0x0072, 0x0001},
696                         { 0x2145, 0x0002},
697                         { 0x4061, 0x0002}
698                 },
699         }, {
700                 83500000, {
701                         { 0x0072, 0x0001},
702                 },
703         }, {
704                 108000000, {
705                         { 0x0051, 0x0002},
706                         { 0x2145, 0x0002},
707                         { 0x4061, 0x0002}
708                 },
709         }, {
710                 106500000, {
711                         { 0x0051, 0x0002},
712                         { 0x2145, 0x0002},
713                         { 0x4061, 0x0002}
714                 },
715         }, {
716                 146250000, {
717                         { 0x0051, 0x0002},
718                         { 0x2145, 0x0002},
719                         { 0x4061, 0x0002}
720                 },
721         }, {
722                 148500000, {
723                         { 0x0051, 0x0003},
724                         { 0x214c, 0x0003},
725                         { 0x4064, 0x0003}
726                 },
727         }, {
728                 ~0UL, {
729                         { 0x00a0, 0x000a },
730                         { 0x2001, 0x000f },
731                         { 0x4002, 0x000f },
732                 },
733         }
734 };
735
736 static enum drm_mode_status
737 inno_hdmi_connector_mode_valid(struct drm_connector *connector,
738                                struct drm_display_mode *mode)
739 {
740 #if 0
741         const struct dw_hdmi_mpll_config *mpll_cfg = starfive_mpll_cfg;
742         int pclk = mode->clock * 1000;
743         bool valid = false;
744         int i;
745
746         for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) {
747                 if (pclk == mpll_cfg[i].mpixelclock) {
748                         valid = true;
749                         break;
750                 }
751         }
752
753         return (valid) ? MODE_OK : MODE_BAD;
754 #endif
755         u32 vic = drm_match_cea_mode(mode);
756
757         if (vic >= 1)
758                 return MODE_OK;
759         else
760                 return MODE_BAD;
761
762         //return MODE_OK;
763 }
764
765 static int
766 inno_hdmi_probe_single_connector_modes(struct drm_connector *connector,
767                                        uint32_t maxX, uint32_t maxY)
768 {
769         return drm_helper_probe_single_connector_modes(connector, 3840, 2160);//3840x2160
770 }
771
772 static void inno_hdmi_connector_destroy(struct drm_connector *connector)
773 {
774         drm_connector_unregister(connector);
775         drm_connector_cleanup(connector);
776 }
777
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,
785 };
786
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,
790 };
791
792 static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi)
793 {
794         struct drm_encoder *encoder = &hdmi->encoder;
795         struct device *dev = hdmi->dev;
796
797         encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
798
799         /*
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.
804          */
805         if (encoder->possible_crtcs == 0)
806                 return -EPROBE_DEFER;
807
808         drm_encoder_helper_add(encoder, &inno_hdmi_encoder_helper_funcs);
809         drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
810
811         hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
812
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,
818                                     hdmi->ddc);
819
820         drm_connector_attach_encoder(&hdmi->connector, encoder);
821
822         return 0;
823 }
824
825 static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
826 {
827         struct inno_hdmi_i2c *i2c = hdmi->i2c;
828         u8 stat;
829
830         stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
831         if (!(stat & m_INT_EDID_READY))
832                 return IRQ_NONE;
833
834         /* Clear HDMI EDID interrupt flag */
835         hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
836
837         complete(&i2c->cmp);
838
839         return IRQ_HANDLED;
840 }
841
842 static irqreturn_t inno_hdmi_hardirq(int irq, void *dev_id)
843 {
844         struct inno_hdmi *hdmi = dev_id;
845         irqreturn_t ret = IRQ_NONE;
846         u8 interrupt;
847
848         if (hdmi->i2c)
849                 ret = inno_hdmi_i2c_irq(hdmi);
850
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;
855         }
856
857         return ret;
858 }
859
860 static irqreturn_t inno_hdmi_irq(int irq, void *dev_id)
861 {
862         struct inno_hdmi *hdmi = dev_id;
863
864         drm_helper_hpd_irq_event(hdmi->connector.dev);
865
866         return IRQ_HANDLED;
867 }
868
869 static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
870 {
871         int length = msgs->len;
872         u8 *buf = msgs->buf;
873         int ret;
874
875         ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
876         if (!ret)
877                 return -EAGAIN;
878
879         while (length--)
880                 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
881
882         return 0;
883 }
884
885 static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
886 {
887         /*
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.
891          */
892         if ((msgs->len != 1) ||
893             ((msgs->addr != DDC_ADDR) && (msgs->addr != DDC_SEGMENT_ADDR)))
894                 return -EINVAL;
895
896         reinit_completion(&hdmi->i2c->cmp);
897
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];
902
903         /* Set edid fifo first addr */
904         hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
905
906         /* Set edid word address 0x00/0x80 */
907         hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
908
909         /* Set edid segment pointer */
910         hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
911
912         return 0;
913 }
914
915 static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap,
916                               struct i2c_msg *msgs, int num)
917 {
918         struct inno_hdmi *hdmi = i2c_get_adapdata(adap);
919         struct inno_hdmi_i2c *i2c = hdmi->i2c;
920         int i, ret = 0;
921
922         mutex_lock(&i2c->lock);
923
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);
927
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);
932
933                 if (msgs[i].flags & I2C_M_RD)
934                         ret = inno_hdmi_i2c_read(hdmi, &msgs[i]);
935                 else
936                         ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
937
938                 if (ret < 0)
939                         break;
940         }
941
942         if (!ret)
943                 ret = num;
944
945         /* Mute HDMI EDID interrupt */
946         hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
947
948         mutex_unlock(&i2c->lock);
949
950         return ret;
951 }
952
953 static u32 inno_hdmi_i2c_func(struct i2c_adapter *adapter)
954 {
955         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
956 }
957
958 static const struct i2c_algorithm inno_hdmi_algorithm = {
959         .master_xfer    = inno_hdmi_i2c_xfer,
960         .functionality  = inno_hdmi_i2c_func,
961 };
962
963 static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
964 {
965         struct i2c_adapter *adap;
966         struct inno_hdmi_i2c *i2c;
967         int ret;
968
969         i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
970         if (!i2c)
971                 return ERR_PTR(-ENOMEM);
972
973         mutex_init(&i2c->lock);
974         init_completion(&i2c->cmp);
975
976         adap = &i2c->adap;
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);
983
984         ret = i2c_add_adapter(adap);
985         if (ret) {
986                 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
987                 devm_kfree(hdmi->dev, i2c);
988                 return ERR_PTR(ret);
989         }
990
991         hdmi->i2c = i2c;
992
993         DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver success\n", adap->name);
994
995         return adap;
996 }
997
998 static int inno_hdmi_get_clk_rst(struct device *dev, struct inno_hdmi *hdmi)
999 {
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);
1004         }
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);
1009         }
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);
1014         }
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);
1019         }
1020         return 0;
1021 }
1022
1023 static int inno_hdmi_en_clk_deas_rst(struct device *dev, struct inno_hdmi *hdmi)
1024 {
1025         int ret;
1026
1027         ret = clk_prepare_enable(hdmi->sys_clk);
1028         if (ret) {
1029                 DRM_DEV_ERROR(dev,
1030                               "Cannot enable HDMI sys clock: %d\n", ret);
1031                 return ret;
1032         }
1033         ret = clk_prepare_enable(hdmi->mclk);
1034         if (ret) {
1035                 DRM_DEV_ERROR(dev,
1036                               "Cannot enable HDMI mclk clock: %d\n", ret);
1037                 return ret;
1038         }
1039         ret = clk_prepare_enable(hdmi->bclk);
1040         if (ret) {
1041                 DRM_DEV_ERROR(dev,
1042                               "Cannot enable HDMI bclk clock: %d\n", ret);
1043                 return ret;
1044         }
1045
1046         ret = reset_control_deassert(hdmi->tx_rst);
1047         if (ret < 0) {
1048                 dev_err(dev, "failed to deassert tx_rst\n");
1049                 return ret;
1050     }
1051         return ret;
1052 }
1053
1054
1055 static int inno_hdmi_bind(struct device *dev, struct device *master,
1056                                  void *data)
1057 {
1058         struct platform_device *pdev = to_platform_device(dev);
1059         struct drm_device *drm = data;
1060         struct inno_hdmi *hdmi;
1061         struct resource *iores;
1062         int irq;
1063         int ret;
1064
1065         hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
1066         if (!hdmi)
1067                 return -ENOMEM;
1068
1069         hdmi->dev = dev;
1070         hdmi->drm_dev = drm;
1071
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);
1076
1077         hdmi->hdmi_1p8 = devm_regulator_get(dev, "hdmi_1p8");
1078         if (IS_ERR(hdmi->hdmi_1p8))
1079                 return PTR_ERR(hdmi->hdmi_1p8);
1080
1081         hdmi->hdmi_0p9 = devm_regulator_get(dev, "hdmi_0p9");
1082         if (IS_ERR(hdmi->hdmi_0p9))
1083                 return PTR_ERR(hdmi->hdmi_0p9);
1084
1085         //pmic turn on
1086         ret = regulator_enable(hdmi->hdmi_1p8);
1087         if (ret) {
1088                 dev_err(dev, "Cannot enable hdmi_1p8 regulator\n");
1089                 goto err_reg_1p8;
1090         }
1091         udelay(100);
1092         ret = regulator_enable(hdmi->hdmi_0p9);
1093         if (ret) {
1094                 dev_err(dev, "Cannot enable hdmi_0p9 regulator\n");
1095                 goto err_reg_0p9;
1096         }
1097         udelay(100);
1098
1099         ret = inno_hdmi_get_clk_rst(dev, hdmi);
1100         ret = inno_hdmi_en_clk_deas_rst(dev, hdmi);
1101
1102         irq = platform_get_irq(pdev, 0);
1103         if (irq < 0) {
1104                 ret = irq;
1105                 goto err_disable_clk;
1106         }
1107 #ifdef CONFIG_DRM_I2C_NXP_TDA998X
1108         hdmi->hdmi_data.vic = 0x10;
1109         inno_hdmi_init(hdmi);
1110 #endif
1111         inno_hdmi_reset(hdmi);
1112
1113         hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
1114         if (IS_ERR(hdmi->ddc)) {
1115                 ret = PTR_ERR(hdmi->ddc);
1116                 hdmi->ddc = NULL;
1117                 goto err_disable_clk;
1118         }
1119
1120         hdmi->tmds_rate = 51200000;
1121
1122         inno_hdmi_i2c_init(hdmi);
1123
1124         ret = inno_hdmi_register(drm, hdmi);
1125         if (ret)
1126                 goto err_put_adapter;
1127
1128         dev_set_drvdata(dev, hdmi);
1129
1130         /* Unmute hotplug interrupt */
1131         hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
1132
1133         ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
1134                                         inno_hdmi_irq, IRQF_SHARED,
1135                                         dev_name(dev), hdmi);
1136         if (ret < 0)
1137                 goto err_cleanup_hdmi;
1138
1139         return 0;
1140 err_cleanup_hdmi:
1141         hdmi->connector.funcs->destroy(&hdmi->connector);
1142         hdmi->encoder.funcs->destroy(&hdmi->encoder);
1143 err_put_adapter:
1144         i2c_put_adapter(hdmi->ddc);
1145 err_disable_clk:
1146         //clk_disable_unprepare(hdmi->pclk);
1147 err_reg_0p9:
1148         regulator_disable(hdmi->hdmi_1p8);
1149 err_reg_1p8:
1150         return ret;
1151 }
1152
1153 static void inno_hdmi_unbind(struct device *dev, struct device *master,
1154                              void *data)
1155 {
1156         struct inno_hdmi *hdmi = dev_get_drvdata(dev);
1157         int ret;
1158
1159         hdmi->connector.funcs->destroy(&hdmi->connector);
1160         hdmi->encoder.funcs->destroy(&hdmi->encoder);
1161
1162         i2c_put_adapter(hdmi->ddc);
1163
1164         ret = reset_control_assert(hdmi->tx_rst);
1165         if (ret < 0)
1166                 dev_err(dev, "failed to assert tx_rst\n");
1167
1168         clk_disable_unprepare(hdmi->sys_clk);
1169         clk_disable_unprepare(hdmi->mclk);
1170         clk_disable_unprepare(hdmi->bclk);
1171
1172         regulator_disable(hdmi->hdmi_1p8);
1173         udelay(100);
1174         regulator_disable(hdmi->hdmi_0p9);
1175 }
1176
1177 static const struct component_ops inno_hdmi_ops = {
1178         .bind   = inno_hdmi_bind,
1179         .unbind = inno_hdmi_unbind,
1180 };
1181
1182 static int inno_hdmi_probe(struct platform_device *pdev)
1183 {
1184         return component_add(&pdev->dev, &inno_hdmi_ops);
1185 }
1186
1187 static int inno_hdmi_remove(struct platform_device *pdev)
1188 {
1189         component_del(&pdev->dev, &inno_hdmi_ops);
1190
1191         return 0;
1192 }
1193
1194 static const struct of_device_id inno_hdmi_dt_ids[] = {
1195         { .compatible = "rockchip,rk3036-inno-hdmi",
1196         },
1197         {},
1198 };
1199 MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
1200
1201 struct platform_driver inno_hdmi_driver = {
1202         .probe  = inno_hdmi_probe,
1203         .remove = inno_hdmi_remove,
1204         .driver = {
1205                 .name = "innohdmi-rockchip",
1206                 .of_match_table = inno_hdmi_dt_ids,
1207         },
1208 };