]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - drivers/video/rockchip/rk_hdmi.c
clk: convert API to match reset/mailbox style
[karo-tx-uboot.git] / drivers / video / rockchip / rk_hdmi.c
1 /*
2  * Copyright (c) 2015 Google, Inc
3  * Copyright 2014 Rockchip Inc.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <clk.h>
10 #include <display.h>
11 #include <dm.h>
12 #include <edid.h>
13 #include <regmap.h>
14 #include <syscon.h>
15 #include <asm/gpio.h>
16 #include <asm/io.h>
17 #include <asm/arch/clock.h>
18 #include <asm/arch/grf_rk3288.h>
19 #include <asm/arch/hdmi_rk3288.h>
20 #include <power/regulator.h>
21
22 struct tmds_n_cts {
23         u32 tmds;
24         u32 cts;
25         u32 n;
26 };
27
28 struct rk_hdmi_priv {
29         struct rk3288_hdmi *regs;
30         struct rk3288_grf *grf;
31 };
32
33 static const struct tmds_n_cts n_cts_table[] = {
34         {
35                 .tmds = 25175, .n = 6144, .cts = 25175,
36         }, {
37                 .tmds = 25200, .n = 6144, .cts = 25200,
38         }, {
39                 .tmds = 27000, .n = 6144, .cts = 27000,
40         }, {
41                 .tmds = 27027, .n = 6144, .cts = 27027,
42         }, {
43                 .tmds = 40000, .n = 6144, .cts = 40000,
44         }, {
45                 .tmds = 54000, .n = 6144, .cts = 54000,
46         }, {
47                 .tmds = 54054, .n = 6144, .cts = 54054,
48         }, {
49                 .tmds = 65000, .n = 6144, .cts = 65000,
50         }, {
51                 .tmds = 74176, .n = 11648, .cts = 140625,
52         }, {
53                 .tmds = 74250, .n = 6144, .cts = 74250,
54         }, {
55                 .tmds = 83500, .n = 6144, .cts = 83500,
56         }, {
57                 .tmds = 106500, .n = 6144, .cts = 106500,
58         }, {
59                 .tmds = 108000, .n = 6144, .cts = 108000,
60         }, {
61                 .tmds = 148352, .n = 5824, .cts = 140625,
62         }, {
63                 .tmds = 148500, .n = 6144, .cts = 148500,
64         }, {
65                 .tmds = 297000, .n = 5120, .cts = 247500,
66         }
67 };
68
69 struct hdmi_mpll_config {
70         u64 mpixelclock;
71         /* Mode of Operation and PLL Dividers Control Register */
72         u32 cpce;
73         /* PLL Gmp Control Register */
74         u32 gmp;
75         /* PLL Current COntrol Register */
76         u32 curr;
77 };
78
79 struct hdmi_phy_config {
80         u64 mpixelclock;
81         u32 sym_ctr;    /* clock symbol and transmitter control */
82         u32 term;       /* transmission termination value */
83         u32 vlev_ctr;   /* voltage level control */
84 };
85
86 static const struct hdmi_phy_config rockchip_phy_config[] = {
87         {
88                 .mpixelclock = 74250,
89                 .sym_ctr = 0x8009, .term = 0x0004, .vlev_ctr = 0x0272,
90         }, {
91                 .mpixelclock = 148500,
92                 .sym_ctr = 0x802b, .term = 0x0004, .vlev_ctr = 0x028d,
93         }, {
94                 .mpixelclock = 297000,
95                 .sym_ctr = 0x8039, .term = 0x0005, .vlev_ctr = 0x028d,
96         }, {
97                 .mpixelclock = ~0ul,
98                 .sym_ctr = 0x0000, .term = 0x0000, .vlev_ctr = 0x0000,
99         }
100 };
101
102 static const struct hdmi_mpll_config rockchip_mpll_cfg[] = {
103         {
104                 .mpixelclock = 40000,
105                 .cpce = 0x00b3, .gmp = 0x0000, .curr = 0x0018,
106         }, {
107                 .mpixelclock = 65000,
108                 .cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028,
109         }, {
110                 .mpixelclock = 66000,
111                 .cpce = 0x013e, .gmp = 0x0003, .curr = 0x0038,
112         }, {
113                 .mpixelclock = 83500,
114                 .cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028,
115         }, {
116                 .mpixelclock = 146250,
117                 .cpce = 0x0051, .gmp = 0x0002, .curr = 0x0038,
118         }, {
119                 .mpixelclock = 148500,
120                 .cpce = 0x0051, .gmp = 0x0003, .curr = 0x0000,
121         }, {
122                 .mpixelclock = ~0ul,
123                 .cpce = 0x0051, .gmp = 0x0003, .curr = 0x0000,
124         }
125 };
126
127 static const u32 csc_coeff_default[3][4] = {
128         { 0x2000, 0x0000, 0x0000, 0x0000 },
129         { 0x0000, 0x2000, 0x0000, 0x0000 },
130         { 0x0000, 0x0000, 0x2000, 0x0000 }
131 };
132
133 static void hdmi_set_clock_regenerator(struct rk3288_hdmi *regs, u32 n, u32 cts)
134 {
135         u8 cts3;
136         u8 n3;
137
138         /* first set ncts_atomic_write (if present) */
139         n3 = HDMI_AUD_N3_NCTS_ATOMIC_WRITE;
140         writel(n3, &regs->aud_n3);
141
142         /* set cts_manual (if present) */
143         cts3 = HDMI_AUD_CTS3_CTS_MANUAL;
144
145         cts3 |= HDMI_AUD_CTS3_N_SHIFT_1 << HDMI_AUD_CTS3_N_SHIFT_OFFSET;
146         cts3 |= (cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK;
147
148         /* write cts values; cts3 must be written first */
149         writel(cts3, &regs->aud_cts3);
150         writel((cts >> 8) & 0xff, &regs->aud_cts2);
151         writel(cts & 0xff, &regs->aud_cts1);
152
153         /* write n values; n1 must be written last */
154         n3 |= (n >> 16) & HDMI_AUD_N3_AUDN19_16_MASK;
155         writel(n3, &regs->aud_n3);
156         writel((n >> 8) & 0xff, &regs->aud_n2);
157         writel(n & 0xff, &regs->aud_n1);
158
159         writel(HDMI_AUD_INPUTCLKFS_128, &regs->aud_inputclkfs);
160 }
161
162 static int hdmi_lookup_n_cts(u32 pixel_clk)
163 {
164         int i;
165
166         for (i = 0; i < ARRAY_SIZE(n_cts_table); i++)
167                 if (pixel_clk <= n_cts_table[i].tmds)
168                         break;
169
170         if (i >= ARRAY_SIZE(n_cts_table))
171                 return -1;
172
173         return i;
174 }
175
176 static void hdmi_audio_set_samplerate(struct rk3288_hdmi *regs, u32 pixel_clk)
177 {
178         u32 clk_n, clk_cts;
179         int index;
180
181         index = hdmi_lookup_n_cts(pixel_clk);
182         if (index == -1) {
183                 debug("audio not supported for pixel clk %d\n", pixel_clk);
184                 return;
185         }
186
187         clk_n = n_cts_table[index].n;
188         clk_cts = n_cts_table[index].cts;
189         hdmi_set_clock_regenerator(regs, clk_n, clk_cts);
190 }
191
192 /*
193  * this submodule is responsible for the video data synchronization.
194  * for example, for rgb 4:4:4 input, the data map is defined as
195  *                      pin{47~40} <==> r[7:0]
196  *                      pin{31~24} <==> g[7:0]
197  *                      pin{15~8}  <==> b[7:0]
198  */
199 static void hdmi_video_sample(struct rk3288_hdmi *regs)
200 {
201         u32 color_format = 0x01;
202         u8 val;
203
204         val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
205               ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
206               HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
207
208         writel(val, &regs->tx_invid0);
209
210         /* enable tx stuffing: when de is inactive, fix the output data to 0 */
211         val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
212               HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
213               HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
214         writel(val, &regs->tx_instuffing);
215         writel(0x0, &regs->tx_gydata0);
216         writel(0x0, &regs->tx_gydata1);
217         writel(0x0, &regs->tx_rcrdata0);
218         writel(0x0, &regs->tx_rcrdata1);
219         writel(0x0, &regs->tx_bcbdata0);
220         writel(0x0, &regs->tx_bcbdata1);
221 }
222
223 static void hdmi_update_csc_coeffs(struct rk3288_hdmi *regs)
224 {
225         u32 i, j;
226         u32 csc_scale = 1;
227
228         /* the csc registers are sequential, alternating msb then lsb */
229         for (i = 0; i < ARRAY_SIZE(csc_coeff_default); i++) {
230                 for (j = 0; j < ARRAY_SIZE(csc_coeff_default[0]); j++) {
231                         u32 coeff = csc_coeff_default[i][j];
232                         writel(coeff >> 8, &regs->csc_coef[i][j].msb);
233                         writel(coeff && 0xff, &regs->csc_coef[i][j].lsb);
234                 }
235         }
236
237         clrsetbits_le32(&regs->csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK,
238                         csc_scale);
239 }
240
241 static void hdmi_video_csc(struct rk3288_hdmi *regs)
242 {
243         u32 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
244         u32 interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
245
246         /* configure the csc registers */
247         writel(interpolation, &regs->csc_cfg);
248         clrsetbits_le32(&regs->csc_scale,
249                         HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK, color_depth);
250
251         hdmi_update_csc_coeffs(regs);
252 }
253
254 static void hdmi_video_packetize(struct rk3288_hdmi *regs)
255 {
256         u32 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
257         u32 remap_size = HDMI_VP_REMAP_YCC422_16BIT;
258         u32 color_depth = 0;
259         u8 val, vp_conf;
260
261         /* set the packetizer registers */
262         val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
263                 HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
264                 ((0 << HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
265                 HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
266         writel(val, &regs->vp_pr_cd);
267
268         clrsetbits_le32(&regs->vp_stuff, HDMI_VP_STUFF_PR_STUFFING_MASK,
269                         HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE);
270
271         /* data from pixel repeater block */
272         vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
273                   HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
274
275         clrsetbits_le32(&regs->vp_conf, HDMI_VP_CONF_PR_EN_MASK |
276                         HDMI_VP_CONF_BYPASS_SELECT_MASK, vp_conf);
277
278         clrsetbits_le32(&regs->vp_stuff, HDMI_VP_STUFF_IDEFAULT_PHASE_MASK,
279                         1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET);
280
281         writel(remap_size, &regs->vp_remap);
282
283         vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
284                   HDMI_VP_CONF_PP_EN_DISABLE |
285                   HDMI_VP_CONF_YCC422_EN_DISABLE;
286
287         clrsetbits_le32(&regs->vp_conf, HDMI_VP_CONF_BYPASS_EN_MASK |
288                         HDMI_VP_CONF_PP_EN_ENMASK | HDMI_VP_CONF_YCC422_EN_MASK,
289                         vp_conf);
290
291         clrsetbits_le32(&regs->vp_stuff, HDMI_VP_STUFF_PP_STUFFING_MASK |
292                         HDMI_VP_STUFF_YCC422_STUFFING_MASK,
293                         HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
294                         HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE);
295
296         clrsetbits_le32(&regs->vp_conf, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
297                         output_select);
298 }
299
300 static inline void hdmi_phy_test_clear(struct rk3288_hdmi *regs, u8 bit)
301 {
302         clrsetbits_le32(&regs->phy_tst0, HDMI_PHY_TST0_TSTCLR_MASK,
303                         bit << HDMI_PHY_TST0_TSTCLR_OFFSET);
304 }
305
306 static int hdmi_phy_wait_i2c_done(struct rk3288_hdmi *regs, u32 msec)
307 {
308         ulong start;
309         u32 val;
310
311         start = get_timer(0);
312         do {
313                 val = readl(&regs->ih_i2cmphy_stat0);
314                 if (val & 0x3) {
315                         writel(val, &regs->ih_i2cmphy_stat0);
316                         return 0;
317                 }
318
319                 udelay(100);
320         } while (get_timer(start) < msec);
321
322         return 1;
323 }
324
325 static void hdmi_phy_i2c_write(struct rk3288_hdmi *regs, uint data, uint addr)
326 {
327         writel(0xff, &regs->ih_i2cmphy_stat0);
328         writel(addr, &regs->phy_i2cm_address_addr);
329         writel((u8)(data >> 8), &regs->phy_i2cm_datao_1_addr);
330         writel((u8)(data >> 0), &regs->phy_i2cm_datao_0_addr);
331         writel(HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
332                &regs->phy_i2cm_operation_addr);
333
334         hdmi_phy_wait_i2c_done(regs, 1000);
335 }
336
337 static void hdmi_phy_enable_power(struct rk3288_hdmi *regs, uint enable)
338 {
339         clrsetbits_le32(&regs->phy_conf0, HDMI_PHY_CONF0_PDZ_MASK,
340                         enable << HDMI_PHY_CONF0_PDZ_OFFSET);
341 }
342
343 static void hdmi_phy_enable_tmds(struct rk3288_hdmi *regs, uint enable)
344 {
345         clrsetbits_le32(&regs->phy_conf0, HDMI_PHY_CONF0_ENTMDS_MASK,
346                         enable << HDMI_PHY_CONF0_ENTMDS_OFFSET);
347 }
348
349 static void hdmi_phy_enable_spare(struct rk3288_hdmi *regs, uint enable)
350 {
351         clrsetbits_le32(&regs->phy_conf0, HDMI_PHY_CONF0_SPARECTRL_MASK,
352                         enable << HDMI_PHY_CONF0_SPARECTRL_OFFSET);
353 }
354
355 static void hdmi_phy_gen2_pddq(struct rk3288_hdmi *regs, uint enable)
356 {
357         clrsetbits_le32(&regs->phy_conf0, HDMI_PHY_CONF0_GEN2_PDDQ_MASK,
358                         enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET);
359 }
360
361 static void hdmi_phy_gen2_txpwron(struct rk3288_hdmi *regs, uint enable)
362 {
363         clrsetbits_le32(&regs->phy_conf0,
364                         HDMI_PHY_CONF0_GEN2_TXPWRON_MASK,
365                         enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET);
366 }
367
368 static void hdmi_phy_sel_data_en_pol(struct rk3288_hdmi *regs, uint enable)
369 {
370         clrsetbits_le32(&regs->phy_conf0,
371                         HDMI_PHY_CONF0_SELDATAENPOL_MASK,
372                         enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET);
373 }
374
375 static void hdmi_phy_sel_interface_control(struct rk3288_hdmi *regs,
376                                            uint enable)
377 {
378         clrsetbits_le32(&regs->phy_conf0, HDMI_PHY_CONF0_SELDIPIF_MASK,
379                         enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET);
380 }
381
382 static int hdmi_phy_configure(struct rk3288_hdmi *regs, u32 mpixelclock)
383 {
384         ulong start;
385         u8 i, val;
386
387         writel(HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
388                &regs->mc_flowctrl);
389
390         /* gen2 tx power off */
391         hdmi_phy_gen2_txpwron(regs, 0);
392
393         /* gen2 pddq */
394         hdmi_phy_gen2_pddq(regs, 1);
395
396         /* phy reset */
397         writel(HDMI_MC_PHYRSTZ_DEASSERT, &regs->mc_phyrstz);
398         writel(HDMI_MC_PHYRSTZ_ASSERT, &regs->mc_phyrstz);
399         writel(HDMI_MC_HEACPHY_RST_ASSERT, &regs->mc_heacphy_rst);
400
401         hdmi_phy_test_clear(regs, 1);
402         writel(HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2, &regs->phy_i2cm_slave_addr);
403         hdmi_phy_test_clear(regs, 0);
404
405         /* pll/mpll cfg - always match on final entry */
406         for (i = 0; rockchip_mpll_cfg[i].mpixelclock != (~0ul); i++)
407                 if (mpixelclock <= rockchip_mpll_cfg[i].mpixelclock)
408                         break;
409
410         hdmi_phy_i2c_write(regs, rockchip_mpll_cfg[i].cpce, PHY_OPMODE_PLLCFG);
411         hdmi_phy_i2c_write(regs, rockchip_mpll_cfg[i].gmp, PHY_PLLGMPCTRL);
412         hdmi_phy_i2c_write(regs, rockchip_mpll_cfg[i].curr, PHY_PLLCURRCTRL);
413
414         hdmi_phy_i2c_write(regs, 0x0000, PHY_PLLPHBYCTRL);
415         hdmi_phy_i2c_write(regs, 0x0006, PHY_PLLCLKBISTPHASE);
416
417         for (i = 0; rockchip_phy_config[i].mpixelclock != (~0ul); i++)
418                 if (mpixelclock <= rockchip_phy_config[i].mpixelclock)
419                         break;
420
421         /*
422          * resistance term 133ohm cfg
423          * preemp cgf 0.00
424          * tx/ck lvl 10
425          */
426         hdmi_phy_i2c_write(regs, rockchip_phy_config[i].term, PHY_TXTERM);
427         hdmi_phy_i2c_write(regs, rockchip_phy_config[i].sym_ctr,
428                            PHY_CKSYMTXCTRL);
429         hdmi_phy_i2c_write(regs, rockchip_phy_config[i].vlev_ctr, PHY_VLEVCTRL);
430
431         /* remove clk term */
432         hdmi_phy_i2c_write(regs, 0x8000, PHY_CKCALCTRL);
433
434         hdmi_phy_enable_power(regs, 1);
435
436         /* toggle tmds enable */
437         hdmi_phy_enable_tmds(regs, 0);
438         hdmi_phy_enable_tmds(regs, 1);
439
440         /* gen2 tx power on */
441         hdmi_phy_gen2_txpwron(regs, 1);
442         hdmi_phy_gen2_pddq(regs, 0);
443
444         hdmi_phy_enable_spare(regs, 1);
445
446         /* wait for phy pll lock */
447         start = get_timer(0);
448         do {
449                 val = readl(&regs->phy_stat0);
450                 if (!(val & HDMI_PHY_TX_PHY_LOCK))
451                         return 0;
452
453                 udelay(100);
454         } while (get_timer(start) < 5);
455
456         return -1;
457 }
458
459 static int hdmi_phy_init(struct rk3288_hdmi *regs, uint mpixelclock)
460 {
461         int i, ret;
462
463         /* hdmi phy spec says to do the phy initialization sequence twice */
464         for (i = 0; i < 2; i++) {
465                 hdmi_phy_sel_data_en_pol(regs, 1);
466                 hdmi_phy_sel_interface_control(regs, 0);
467                 hdmi_phy_enable_tmds(regs, 0);
468                 hdmi_phy_enable_power(regs, 0);
469
470                 /* enable csc */
471                 ret = hdmi_phy_configure(regs, mpixelclock);
472                 if (ret) {
473                         debug("hdmi phy config failure %d\n", ret);
474                         return ret;
475                 }
476         }
477
478         return 0;
479 }
480
481 static void hdmi_av_composer(struct rk3288_hdmi *regs,
482                              const struct display_timing *edid)
483 {
484         u8 mdataenablepolarity = 1;
485         u8 inv_val;
486         uint hbl;
487         uint vbl;
488
489         hbl = edid->hback_porch.typ + edid->hfront_porch.typ +
490                         edid->hsync_len.typ;
491         vbl = edid->vback_porch.typ + edid->vfront_porch.typ +
492                         edid->vsync_len.typ;
493
494         /* set up hdmi_fc_invidconf */
495         inv_val = HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE;
496
497         inv_val |= (edid->flags & DISPLAY_FLAGS_HSYNC_HIGH ?
498                    HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
499                    HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
500
501         inv_val |= (edid->flags & DISPLAY_FLAGS_VSYNC_HIGH ?
502                    HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
503                    HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
504
505         inv_val |= (mdataenablepolarity ?
506                    HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
507                    HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
508
509         /*
510          * TODO(sjg@chromium.org>: Need to check for HDMI / DVI
511          * inv_val |= (edid->hdmi_monitor_detected ?
512          *         HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
513          *         HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE);
514          */
515         inv_val |= HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE;
516
517         inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
518
519         inv_val |= HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
520
521         writel(inv_val, &regs->fc_invidconf);
522
523         /* set up horizontal active pixel width */
524         writel(edid->hactive.typ >> 8, &regs->fc_inhactv1);
525         writel(edid->hactive.typ, &regs->fc_inhactv0);
526
527         /* set up vertical active lines */
528         writel(edid->vactive.typ >> 8, &regs->fc_invactv1);
529         writel(edid->vactive.typ, &regs->fc_invactv0);
530
531         /* set up horizontal blanking pixel region width */
532         writel(hbl >> 8, &regs->fc_inhblank1);
533         writel(hbl, &regs->fc_inhblank0);
534
535         /* set up vertical blanking pixel region width */
536         writel(vbl, &regs->fc_invblank);
537
538         /* set up hsync active edge delay width (in pixel clks) */
539         writel(edid->hfront_porch.typ >> 8, &regs->fc_hsyncindelay1);
540         writel(edid->hfront_porch.typ, &regs->fc_hsyncindelay0);
541
542         /* set up vsync active edge delay (in lines) */
543         writel(edid->vfront_porch.typ, &regs->fc_vsyncindelay);
544
545         /* set up hsync active pulse width (in pixel clks) */
546         writel(edid->hsync_len.typ >> 8, &regs->fc_hsyncinwidth1);
547         writel(edid->hsync_len.typ, &regs->fc_hsyncinwidth0);
548
549         /* set up vsync active edge delay (in lines) */
550         writel(edid->vsync_len.typ, &regs->fc_vsyncinwidth);
551 }
552
553 /* hdmi initialization step b.4 */
554 static void hdmi_enable_video_path(struct rk3288_hdmi *regs)
555 {
556         u8 clkdis;
557
558         /* control period minimum duration */
559         writel(12, &regs->fc_ctrldur);
560         writel(32, &regs->fc_exctrldur);
561         writel(1, &regs->fc_exctrlspac);
562
563         /* set to fill tmds data channels */
564         writel(0x0b, &regs->fc_ch0pream);
565         writel(0x16, &regs->fc_ch1pream);
566         writel(0x21, &regs->fc_ch2pream);
567
568         /* enable pixel clock and tmds data path */
569         clkdis = 0x7f;
570         clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
571         writel(clkdis, &regs->mc_clkdis);
572
573         clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
574         writel(clkdis, &regs->mc_clkdis);
575
576         clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
577         writel(clkdis, &regs->mc_clkdis);
578 }
579
580 /* workaround to clear the overflow condition */
581 static void hdmi_clear_overflow(struct rk3288_hdmi *regs)
582 {
583         u8 val, count;
584
585         /* tmds software reset */
586         writel((u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, &regs->mc_swrstz);
587
588         val = readl(&regs->fc_invidconf);
589
590         for (count = 0; count < 4; count++)
591                 writel(val, &regs->fc_invidconf);
592 }
593
594 static void hdmi_audio_set_format(struct rk3288_hdmi *regs)
595 {
596         writel(HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_IN_EN_0,
597                &regs->aud_conf0);
598
599
600         writel(HDMI_AUD_CONF1_I2S_MODE_STANDARD_MODE |
601                HDMI_AUD_CONF1_I2S_WIDTH_16BIT, &regs->aud_conf1);
602
603         writel(0x00, &regs->aud_conf2);
604 }
605
606 static void hdmi_audio_fifo_reset(struct rk3288_hdmi *regs)
607 {
608         writel((u8)~HDMI_MC_SWRSTZ_II2SSWRST_REQ, &regs->mc_swrstz);
609         writel(HDMI_AUD_CONF0_SW_AUDIO_FIFO_RST, &regs->aud_conf0);
610
611         writel(0x00, &regs->aud_int);
612         writel(0x00, &regs->aud_int1);
613 }
614
615 static void hdmi_init_interrupt(struct rk3288_hdmi *regs)
616 {
617         u8 ih_mute;
618
619         /*
620          * boot up defaults are:
621          * hdmi_ih_mute   = 0x03 (disabled)
622          * hdmi_ih_mute_* = 0x00 (enabled)
623          *
624          * disable top level interrupt bits in hdmi block
625          */
626         ih_mute = readl(&regs->ih_mute) |
627                   HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
628                   HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
629
630         writel(ih_mute, &regs->ih_mute);
631
632         /* enable i2c master done irq */
633         writel(~0x04, &regs->i2cm_int);
634
635         /* enable i2c client nack % arbitration error irq */
636         writel(~0x44, &regs->i2cm_ctlint);
637
638         /* enable phy i2cm done irq */
639         writel(HDMI_PHY_I2CM_INT_ADDR_DONE_POL, &regs->phy_i2cm_int_addr);
640
641         /* enable phy i2cm nack & arbitration error irq */
642         writel(HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
643                 HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
644                 &regs->phy_i2cm_ctlint_addr);
645
646         /* enable cable hot plug irq */
647         writel((u8)~HDMI_PHY_HPD, &regs->phy_mask0);
648
649         /* clear hotplug interrupts */
650         writel(HDMI_IH_PHY_STAT0_HPD, &regs->ih_phy_stat0);
651 }
652
653 static u8 hdmi_get_plug_in_status(struct rk3288_hdmi *regs)
654 {
655         u8 val = readl(&regs->phy_stat0) & HDMI_PHY_HPD;
656
657         return !!(val);
658 }
659
660 static int hdmi_wait_for_hpd(struct rk3288_hdmi *regs)
661 {
662         ulong start;
663
664         start = get_timer(0);
665         do {
666                 if (hdmi_get_plug_in_status(regs))
667                         return 0;
668                 udelay(100);
669         } while (get_timer(start) < 30000);
670
671         return -1;
672 }
673
674 static int hdmi_ddc_wait_i2c_done(struct rk3288_hdmi *regs, int msec)
675 {
676         u32 val;
677         ulong start;
678
679         start = get_timer(0);
680         do {
681                 val = readl(&regs->ih_i2cm_stat0);
682                 if (val & 0x2) {
683                         writel(val, &regs->ih_i2cm_stat0);
684                         return 0;
685                 }
686
687                 udelay(100);
688         } while (get_timer(start) < msec);
689
690         return 1;
691 }
692
693 static void hdmi_ddc_reset(struct rk3288_hdmi *regs)
694 {
695         clrbits_le32(&regs->i2cm_softrstz, HDMI_I2CM_SOFTRSTZ);
696 }
697
698 static int hdmi_read_edid(struct rk3288_hdmi *regs, int block, u8 *buff)
699 {
700         int shift = (block % 2) * 0x80;
701         int edid_read_err = 0;
702         u32 trytime = 5;
703         u32 n, j, val;
704
705         /* set ddc i2c clk which devided from ddc_clk to 100khz */
706         writel(0x7a, &regs->i2cm_ss_scl_hcnt_0_addr);
707         writel(0x8d, &regs->i2cm_ss_scl_lcnt_0_addr);
708
709         /*
710          * TODO(sjg@chromium.org): The above values don't work - these ones
711          * work better, but generate lots of errors in the data.
712          */
713         writel(0x0d, &regs->i2cm_ss_scl_hcnt_0_addr);
714         writel(0x0d, &regs->i2cm_ss_scl_lcnt_0_addr);
715         clrsetbits_le32(&regs->i2cm_div, HDMI_I2CM_DIV_FAST_STD_MODE,
716                         HDMI_I2CM_DIV_STD_MODE);
717
718         writel(HDMI_I2CM_SLAVE_DDC_ADDR, &regs->i2cm_slave);
719         writel(HDMI_I2CM_SEGADDR_DDC, &regs->i2cm_segaddr);
720         writel(block >> 1, &regs->i2cm_segptr);
721
722         while (trytime--) {
723                 edid_read_err = 0;
724
725                 for (n = 0; n < HDMI_EDID_BLOCK_SIZE / 8; n++) {
726                         writel(shift + 8 * n, &regs->i2c_address);
727
728                         if (block == 0)
729                                 clrsetbits_le32(&regs->i2cm_operation,
730                                                 HDMI_I2CM_OPT_RD8,
731                                                 HDMI_I2CM_OPT_RD8);
732                         else
733                                 clrsetbits_le32(&regs->i2cm_operation,
734                                                 HDMI_I2CM_OPT_RD8_EXT,
735                                                 HDMI_I2CM_OPT_RD8_EXT);
736
737                         if (hdmi_ddc_wait_i2c_done(regs, 10)) {
738                                 hdmi_ddc_reset(regs);
739                                 edid_read_err = 1;
740                                 break;
741                         }
742
743                         for (j = 0; j < 8; j++) {
744                                 val = readl(&regs->i2cm_buf0 + j);
745                                 buff[8 * n + j] = val;
746                         }
747                 }
748
749                 if (!edid_read_err)
750                         break;
751         }
752
753         return edid_read_err;
754 }
755
756 static u8 pre_buf[] = {
757         0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
758         0x04, 0x69, 0xfa, 0x23, 0xc8, 0x28, 0x01, 0x00,
759         0x10, 0x17, 0x01, 0x03, 0x80, 0x33, 0x1d, 0x78,
760         0x2a, 0xd9, 0x45, 0xa2, 0x55, 0x4d, 0xa0, 0x27,
761         0x12, 0x50, 0x54, 0xb7, 0xef, 0x00, 0x71, 0x4f,
762         0x81, 0x40, 0x81, 0x80, 0x95, 0x00, 0xb3, 0x00,
763         0xd1, 0xc0, 0x81, 0xc0, 0x81, 0x00, 0x02, 0x3a,
764         0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
765         0x45, 0x00, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
766         0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x34, 0x4c,
767         0x4d, 0x54, 0x46, 0x30, 0x37, 0x35, 0x39, 0x37,
768         0x36, 0x0a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
769         0x4b, 0x18, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20,
770         0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
771         0x00, 0x41, 0x53, 0x55, 0x53, 0x20, 0x56, 0x53,
772         0x32, 0x33, 0x38, 0x0a, 0x20, 0x20, 0x01, 0xb0,
773         0x02, 0x03, 0x22, 0x71, 0x4f, 0x01, 0x02, 0x03,
774         0x11, 0x12, 0x13, 0x04, 0x14, 0x05, 0x0e, 0x0f,
775         0x1d, 0x1e, 0x1f, 0x10, 0x23, 0x09, 0x17, 0x07,
776         0x83, 0x01, 0x00, 0x00, 0x65, 0x03, 0x0c, 0x00,
777         0x10, 0x00, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0,
778         0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xfd, 0x1e,
779         0x11, 0x00, 0x00, 0x18, 0x01, 0x1d, 0x00, 0x72,
780         0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
781         0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e, 0x01, 0x1d,
782         0x00, 0xbc, 0x52, 0xd0, 0x1e, 0x20, 0xb8, 0x28,
783         0x55, 0x40, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
784         0x8c, 0x0a, 0xd0, 0x90, 0x20, 0x40, 0x31, 0x20,
785         0x0c, 0x40, 0x55, 0x00, 0xfd, 0x1e, 0x11, 0x00,
786         0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
787         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
788         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9,
789 };
790
791 static int rk_hdmi_read_edid(struct udevice *dev, u8 *buf, int buf_size)
792 {
793         struct rk_hdmi_priv *priv = dev_get_priv(dev);
794         u32 edid_size = HDMI_EDID_BLOCK_SIZE;
795         int ret;
796
797         if (0) {
798                 edid_size = sizeof(pre_buf);
799                 memcpy(buf, pre_buf, edid_size);
800         } else {
801                 ret = hdmi_read_edid(priv->regs, 0, buf);
802                 if (ret) {
803                         debug("failed to read edid.\n");
804                         return -1;
805                 }
806
807                 if (buf[0x7e] != 0) {
808                         hdmi_read_edid(priv->regs, 1,
809                                        buf + HDMI_EDID_BLOCK_SIZE);
810                         edid_size += HDMI_EDID_BLOCK_SIZE;
811                 }
812         }
813
814         return edid_size;
815 }
816
817 static int rk_hdmi_enable(struct udevice *dev, int panel_bpp,
818                           const struct display_timing *edid)
819 {
820         struct rk_hdmi_priv *priv = dev_get_priv(dev);
821         struct rk3288_hdmi *regs = priv->regs;
822         int ret;
823
824         debug("hdmi, mode info : clock %d hdis %d vdis %d\n",
825               edid->pixelclock.typ, edid->hactive.typ, edid->vactive.typ);
826
827         hdmi_av_composer(regs, edid);
828
829         ret = hdmi_phy_init(regs, edid->pixelclock.typ);
830         if (ret)
831                 return ret;
832
833         hdmi_enable_video_path(regs);
834
835         hdmi_audio_fifo_reset(regs);
836         hdmi_audio_set_format(regs);
837         hdmi_audio_set_samplerate(regs, edid->pixelclock.typ);
838
839         hdmi_video_packetize(regs);
840         hdmi_video_csc(regs);
841         hdmi_video_sample(regs);
842
843         hdmi_clear_overflow(regs);
844
845         return 0;
846 }
847
848 static int rk_hdmi_ofdata_to_platdata(struct udevice *dev)
849 {
850         struct rk_hdmi_priv *priv = dev_get_priv(dev);
851
852         priv->regs = (struct rk3288_hdmi *)dev_get_addr(dev);
853         priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
854
855         return 0;
856 }
857
858 static int rk_hdmi_probe(struct udevice *dev)
859 {
860         struct display_plat *uc_plat = dev_get_uclass_platdata(dev);
861         struct rk_hdmi_priv *priv = dev_get_priv(dev);
862         struct udevice *reg;
863         struct clk clk;
864         int ret;
865         int vop_id = uc_plat->source_id;
866
867         ret = clk_get_by_index(dev, 0, &clk);
868         if (ret >= 0) {
869                 ret = clk_set_rate(&clk, 0);
870                 clk_free(&clk);
871         }
872         if (ret) {
873                 debug("%s: Failed to set EDP clock: ret=%d\n", __func__, ret);
874                 return ret;
875         }
876
877         /*
878          * Configure the maximum clock to permit whatever resolution the
879          * monitor wants
880          */
881         ret = clk_get_by_index(uc_plat->src_dev, 0, &clk);
882         if (ret >= 0) {
883                 ret = clk_set_rate(&clk, 384000000);
884                 clk_free(&clk);
885         }
886         if (ret < 0) {
887                 debug("%s: Failed to set clock in source device '%s': ret=%d\n",
888                       __func__, uc_plat->src_dev->name, ret);
889                 return ret;
890         }
891
892         ret = regulator_get_by_platname("vcc50_hdmi", &reg);
893         if (!ret)
894                 ret = regulator_set_enable(reg, true);
895         if (ret)
896                 debug("%s: Cannot set regulator vcc50_hdmi\n", __func__);
897
898         /* hdmi source select hdmi controller */
899         rk_setreg(&priv->grf->soc_con6, 1 << 15);
900
901         /* hdmi data from vop id */
902         rk_setreg(&priv->grf->soc_con6, (vop_id == 1) ? (1 << 4) : (1 << 4));
903
904         ret = hdmi_wait_for_hpd(priv->regs);
905         if (ret < 0) {
906                 debug("hdmi can not get hpd signal\n");
907                 return -1;
908         }
909
910         hdmi_init_interrupt(priv->regs);
911
912         return 0;
913 }
914
915 static const struct dm_display_ops rk_hdmi_ops = {
916         .read_edid = rk_hdmi_read_edid,
917         .enable = rk_hdmi_enable,
918 };
919
920 static const struct udevice_id rk_hdmi_ids[] = {
921         { .compatible = "rockchip,rk3288-dw-hdmi" },
922         { }
923 };
924
925 U_BOOT_DRIVER(hdmi_rockchip) = {
926         .name   = "hdmi_rockchip",
927         .id     = UCLASS_DISPLAY,
928         .of_match = rk_hdmi_ids,
929         .ops    = &rk_hdmi_ops,
930         .ofdata_to_platdata     = rk_hdmi_ofdata_to_platdata,
931         .probe  = rk_hdmi_probe,
932         .priv_auto_alloc_size    = sizeof(struct rk_hdmi_priv),
933 };