2 * Copyright (c) 2015 Google, Inc
3 * Copyright 2014 Rockchip Inc.
5 * SPDX-License-Identifier: GPL-2.0+
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>
29 struct rk3288_hdmi *regs;
30 struct rk3288_grf *grf;
33 static const struct tmds_n_cts n_cts_table[] = {
35 .tmds = 25175, .n = 6144, .cts = 25175,
37 .tmds = 25200, .n = 6144, .cts = 25200,
39 .tmds = 27000, .n = 6144, .cts = 27000,
41 .tmds = 27027, .n = 6144, .cts = 27027,
43 .tmds = 40000, .n = 6144, .cts = 40000,
45 .tmds = 54000, .n = 6144, .cts = 54000,
47 .tmds = 54054, .n = 6144, .cts = 54054,
49 .tmds = 65000, .n = 6144, .cts = 65000,
51 .tmds = 74176, .n = 11648, .cts = 140625,
53 .tmds = 74250, .n = 6144, .cts = 74250,
55 .tmds = 83500, .n = 6144, .cts = 83500,
57 .tmds = 106500, .n = 6144, .cts = 106500,
59 .tmds = 108000, .n = 6144, .cts = 108000,
61 .tmds = 148352, .n = 5824, .cts = 140625,
63 .tmds = 148500, .n = 6144, .cts = 148500,
65 .tmds = 297000, .n = 5120, .cts = 247500,
69 struct hdmi_mpll_config {
71 /* Mode of Operation and PLL Dividers Control Register */
73 /* PLL Gmp Control Register */
75 /* PLL Current COntrol Register */
79 struct hdmi_phy_config {
81 u32 sym_ctr; /* clock symbol and transmitter control */
82 u32 term; /* transmission termination value */
83 u32 vlev_ctr; /* voltage level control */
86 static const struct hdmi_phy_config rockchip_phy_config[] = {
89 .sym_ctr = 0x8009, .term = 0x0004, .vlev_ctr = 0x0272,
91 .mpixelclock = 148500,
92 .sym_ctr = 0x802b, .term = 0x0004, .vlev_ctr = 0x028d,
94 .mpixelclock = 297000,
95 .sym_ctr = 0x8039, .term = 0x0005, .vlev_ctr = 0x028d,
98 .sym_ctr = 0x0000, .term = 0x0000, .vlev_ctr = 0x0000,
102 static const struct hdmi_mpll_config rockchip_mpll_cfg[] = {
104 .mpixelclock = 40000,
105 .cpce = 0x00b3, .gmp = 0x0000, .curr = 0x0018,
107 .mpixelclock = 65000,
108 .cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028,
110 .mpixelclock = 66000,
111 .cpce = 0x013e, .gmp = 0x0003, .curr = 0x0038,
113 .mpixelclock = 83500,
114 .cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028,
116 .mpixelclock = 146250,
117 .cpce = 0x0051, .gmp = 0x0002, .curr = 0x0038,
119 .mpixelclock = 148500,
120 .cpce = 0x0051, .gmp = 0x0003, .curr = 0x0000,
123 .cpce = 0x0051, .gmp = 0x0003, .curr = 0x0000,
127 static const u32 csc_coeff_default[3][4] = {
128 { 0x2000, 0x0000, 0x0000, 0x0000 },
129 { 0x0000, 0x2000, 0x0000, 0x0000 },
130 { 0x0000, 0x0000, 0x2000, 0x0000 }
133 static void hdmi_set_clock_regenerator(struct rk3288_hdmi *regs, u32 n, u32 cts)
138 /* first set ncts_atomic_write (if present) */
139 n3 = HDMI_AUD_N3_NCTS_ATOMIC_WRITE;
140 writel(n3, ®s->aud_n3);
142 /* set cts_manual (if present) */
143 cts3 = HDMI_AUD_CTS3_CTS_MANUAL;
145 cts3 |= HDMI_AUD_CTS3_N_SHIFT_1 << HDMI_AUD_CTS3_N_SHIFT_OFFSET;
146 cts3 |= (cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK;
148 /* write cts values; cts3 must be written first */
149 writel(cts3, ®s->aud_cts3);
150 writel((cts >> 8) & 0xff, ®s->aud_cts2);
151 writel(cts & 0xff, ®s->aud_cts1);
153 /* write n values; n1 must be written last */
154 n3 |= (n >> 16) & HDMI_AUD_N3_AUDN19_16_MASK;
155 writel(n3, ®s->aud_n3);
156 writel((n >> 8) & 0xff, ®s->aud_n2);
157 writel(n & 0xff, ®s->aud_n1);
159 writel(HDMI_AUD_INPUTCLKFS_128, ®s->aud_inputclkfs);
162 static int hdmi_lookup_n_cts(u32 pixel_clk)
166 for (i = 0; i < ARRAY_SIZE(n_cts_table); i++)
167 if (pixel_clk <= n_cts_table[i].tmds)
170 if (i >= ARRAY_SIZE(n_cts_table))
176 static void hdmi_audio_set_samplerate(struct rk3288_hdmi *regs, u32 pixel_clk)
181 index = hdmi_lookup_n_cts(pixel_clk);
183 debug("audio not supported for pixel clk %d\n", pixel_clk);
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);
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]
199 static void hdmi_video_sample(struct rk3288_hdmi *regs)
201 u32 color_format = 0x01;
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);
208 writel(val, ®s->tx_invid0);
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, ®s->tx_instuffing);
215 writel(0x0, ®s->tx_gydata0);
216 writel(0x0, ®s->tx_gydata1);
217 writel(0x0, ®s->tx_rcrdata0);
218 writel(0x0, ®s->tx_rcrdata1);
219 writel(0x0, ®s->tx_bcbdata0);
220 writel(0x0, ®s->tx_bcbdata1);
223 static void hdmi_update_csc_coeffs(struct rk3288_hdmi *regs)
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, ®s->csc_coef[i][j].msb);
233 writel(coeff && 0xff, ®s->csc_coef[i][j].lsb);
237 clrsetbits_le32(®s->csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK,
241 static void hdmi_video_csc(struct rk3288_hdmi *regs)
243 u32 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
244 u32 interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
246 /* configure the csc registers */
247 writel(interpolation, ®s->csc_cfg);
248 clrsetbits_le32(®s->csc_scale,
249 HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK, color_depth);
251 hdmi_update_csc_coeffs(regs);
254 static void hdmi_video_packetize(struct rk3288_hdmi *regs)
256 u32 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
257 u32 remap_size = HDMI_VP_REMAP_YCC422_16BIT;
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, ®s->vp_pr_cd);
268 clrsetbits_le32(®s->vp_stuff, HDMI_VP_STUFF_PR_STUFFING_MASK,
269 HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE);
271 /* data from pixel repeater block */
272 vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
273 HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
275 clrsetbits_le32(®s->vp_conf, HDMI_VP_CONF_PR_EN_MASK |
276 HDMI_VP_CONF_BYPASS_SELECT_MASK, vp_conf);
278 clrsetbits_le32(®s->vp_stuff, HDMI_VP_STUFF_IDEFAULT_PHASE_MASK,
279 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET);
281 writel(remap_size, ®s->vp_remap);
283 vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
284 HDMI_VP_CONF_PP_EN_DISABLE |
285 HDMI_VP_CONF_YCC422_EN_DISABLE;
287 clrsetbits_le32(®s->vp_conf, HDMI_VP_CONF_BYPASS_EN_MASK |
288 HDMI_VP_CONF_PP_EN_ENMASK | HDMI_VP_CONF_YCC422_EN_MASK,
291 clrsetbits_le32(®s->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);
296 clrsetbits_le32(®s->vp_conf, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
300 static inline void hdmi_phy_test_clear(struct rk3288_hdmi *regs, uint bit)
302 clrsetbits_le32(®s->phy_tst0, HDMI_PHY_TST0_TSTCLR_MASK,
303 bit << HDMI_PHY_TST0_TSTCLR_OFFSET);
306 static int hdmi_phy_wait_i2c_done(struct rk3288_hdmi *regs, u32 msec)
311 start = get_timer(0);
313 val = readl(®s->ih_i2cmphy_stat0);
315 writel(val, ®s->ih_i2cmphy_stat0);
320 } while (get_timer(start) < msec);
325 static void hdmi_phy_i2c_write(struct rk3288_hdmi *regs, uint data, uint addr)
327 writel(0xff, ®s->ih_i2cmphy_stat0);
328 writel(addr, ®s->phy_i2cm_address_addr);
329 writel((u8)(data >> 8), ®s->phy_i2cm_datao_1_addr);
330 writel((u8)(data >> 0), ®s->phy_i2cm_datao_0_addr);
331 writel(HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
332 ®s->phy_i2cm_operation_addr);
334 hdmi_phy_wait_i2c_done(regs, 1000);
337 static void hdmi_phy_enable_power(struct rk3288_hdmi *regs, uint enable)
339 clrsetbits_le32(®s->phy_conf0, HDMI_PHY_CONF0_PDZ_MASK,
340 enable << HDMI_PHY_CONF0_PDZ_OFFSET);
343 static void hdmi_phy_enable_tmds(struct rk3288_hdmi *regs, uint enable)
345 clrsetbits_le32(®s->phy_conf0, HDMI_PHY_CONF0_ENTMDS_MASK,
346 enable << HDMI_PHY_CONF0_ENTMDS_OFFSET);
349 static void hdmi_phy_enable_spare(struct rk3288_hdmi *regs, uint enable)
351 clrsetbits_le32(®s->phy_conf0, HDMI_PHY_CONF0_SPARECTRL_MASK,
352 enable << HDMI_PHY_CONF0_SPARECTRL_OFFSET);
355 static void hdmi_phy_gen2_pddq(struct rk3288_hdmi *regs, uint enable)
357 clrsetbits_le32(®s->phy_conf0, HDMI_PHY_CONF0_GEN2_PDDQ_MASK,
358 enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET);
361 static void hdmi_phy_gen2_txpwron(struct rk3288_hdmi *regs, uint enable)
363 clrsetbits_le32(®s->phy_conf0,
364 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK,
365 enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET);
368 static void hdmi_phy_sel_data_en_pol(struct rk3288_hdmi *regs, uint enable)
370 clrsetbits_le32(®s->phy_conf0,
371 HDMI_PHY_CONF0_SELDATAENPOL_MASK,
372 enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET);
375 static void hdmi_phy_sel_interface_control(struct rk3288_hdmi *regs,
378 clrsetbits_le32(®s->phy_conf0, HDMI_PHY_CONF0_SELDIPIF_MASK,
379 enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET);
382 static int hdmi_phy_configure(struct rk3288_hdmi *regs, u32 mpixelclock)
387 writel(HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
390 /* gen2 tx power off */
391 hdmi_phy_gen2_txpwron(regs, 0);
394 hdmi_phy_gen2_pddq(regs, 1);
397 writel(HDMI_MC_PHYRSTZ_DEASSERT, ®s->mc_phyrstz);
398 writel(HDMI_MC_PHYRSTZ_ASSERT, ®s->mc_phyrstz);
399 writel(HDMI_MC_HEACPHY_RST_ASSERT, ®s->mc_heacphy_rst);
401 hdmi_phy_test_clear(regs, 1);
402 writel(HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2, ®s->phy_i2cm_slave_addr);
403 hdmi_phy_test_clear(regs, 0);
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)
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);
414 hdmi_phy_i2c_write(regs, 0x0000, PHY_PLLPHBYCTRL);
415 hdmi_phy_i2c_write(regs, 0x0006, PHY_PLLCLKBISTPHASE);
417 for (i = 0; rockchip_phy_config[i].mpixelclock != (~0ul); i++)
418 if (mpixelclock <= rockchip_phy_config[i].mpixelclock)
422 * resistance term 133ohm cfg
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,
429 hdmi_phy_i2c_write(regs, rockchip_phy_config[i].vlev_ctr, PHY_VLEVCTRL);
431 /* remove clk term */
432 hdmi_phy_i2c_write(regs, 0x8000, PHY_CKCALCTRL);
434 hdmi_phy_enable_power(regs, 1);
436 /* toggle tmds enable */
437 hdmi_phy_enable_tmds(regs, 0);
438 hdmi_phy_enable_tmds(regs, 1);
440 /* gen2 tx power on */
441 hdmi_phy_gen2_txpwron(regs, 1);
442 hdmi_phy_gen2_pddq(regs, 0);
444 hdmi_phy_enable_spare(regs, 1);
446 /* wait for phy pll lock */
447 start = get_timer(0);
449 val = readl(®s->phy_stat0);
450 if (!(val & HDMI_PHY_TX_PHY_LOCK))
454 } while (get_timer(start) < 5);
459 static int hdmi_phy_init(struct rk3288_hdmi *regs, uint mpixelclock)
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);
471 ret = hdmi_phy_configure(regs, mpixelclock);
473 debug("hdmi phy config failure %d\n", ret);
481 static void hdmi_av_composer(struct rk3288_hdmi *regs,
482 const struct display_timing *edid)
484 bool mdataenablepolarity = true;
489 hbl = edid->hback_porch.typ + edid->hfront_porch.typ +
491 vbl = edid->vback_porch.typ + edid->vfront_porch.typ +
494 /* set up hdmi_fc_invidconf */
495 inv_val = HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE;
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);
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);
505 inv_val |= (mdataenablepolarity ?
506 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
507 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
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);
515 inv_val |= HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE;
517 inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
519 inv_val |= HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
521 writel(inv_val, ®s->fc_invidconf);
523 /* set up horizontal active pixel width */
524 writel(edid->hactive.typ >> 8, ®s->fc_inhactv1);
525 writel(edid->hactive.typ, ®s->fc_inhactv0);
527 /* set up vertical active lines */
528 writel(edid->vactive.typ >> 8, ®s->fc_invactv1);
529 writel(edid->vactive.typ, ®s->fc_invactv0);
531 /* set up horizontal blanking pixel region width */
532 writel(hbl >> 8, ®s->fc_inhblank1);
533 writel(hbl, ®s->fc_inhblank0);
535 /* set up vertical blanking pixel region width */
536 writel(vbl, ®s->fc_invblank);
538 /* set up hsync active edge delay width (in pixel clks) */
539 writel(edid->hfront_porch.typ >> 8, ®s->fc_hsyncindelay1);
540 writel(edid->hfront_porch.typ, ®s->fc_hsyncindelay0);
542 /* set up vsync active edge delay (in lines) */
543 writel(edid->vfront_porch.typ, ®s->fc_vsyncindelay);
545 /* set up hsync active pulse width (in pixel clks) */
546 writel(edid->hsync_len.typ >> 8, ®s->fc_hsyncinwidth1);
547 writel(edid->hsync_len.typ, ®s->fc_hsyncinwidth0);
549 /* set up vsync active edge delay (in lines) */
550 writel(edid->vsync_len.typ, ®s->fc_vsyncinwidth);
553 /* hdmi initialization step b.4 */
554 static void hdmi_enable_video_path(struct rk3288_hdmi *regs)
558 /* control period minimum duration */
559 writel(12, ®s->fc_ctrldur);
560 writel(32, ®s->fc_exctrldur);
561 writel(1, ®s->fc_exctrlspac);
563 /* set to fill tmds data channels */
564 writel(0x0b, ®s->fc_ch0pream);
565 writel(0x16, ®s->fc_ch1pream);
566 writel(0x21, ®s->fc_ch2pream);
568 /* enable pixel clock and tmds data path */
570 clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
571 writel(clkdis, ®s->mc_clkdis);
573 clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
574 writel(clkdis, ®s->mc_clkdis);
576 clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
577 writel(clkdis, ®s->mc_clkdis);
580 /* workaround to clear the overflow condition */
581 static void hdmi_clear_overflow(struct rk3288_hdmi *regs)
585 /* tmds software reset */
586 writel((u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, ®s->mc_swrstz);
588 val = readl(®s->fc_invidconf);
590 for (count = 0; count < 4; count++)
591 writel(val, ®s->fc_invidconf);
594 static void hdmi_audio_set_format(struct rk3288_hdmi *regs)
596 writel(HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_IN_EN_0,
600 writel(HDMI_AUD_CONF1_I2S_MODE_STANDARD_MODE |
601 HDMI_AUD_CONF1_I2S_WIDTH_16BIT, ®s->aud_conf1);
603 writel(0x00, ®s->aud_conf2);
606 static void hdmi_audio_fifo_reset(struct rk3288_hdmi *regs)
608 writel((u8)~HDMI_MC_SWRSTZ_II2SSWRST_REQ, ®s->mc_swrstz);
609 writel(HDMI_AUD_CONF0_SW_AUDIO_FIFO_RST, ®s->aud_conf0);
611 writel(0x00, ®s->aud_int);
612 writel(0x00, ®s->aud_int1);
615 static void hdmi_init_interrupt(struct rk3288_hdmi *regs)
620 * boot up defaults are:
621 * hdmi_ih_mute = 0x03 (disabled)
622 * hdmi_ih_mute_* = 0x00 (enabled)
624 * disable top level interrupt bits in hdmi block
626 ih_mute = readl(®s->ih_mute) |
627 HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
628 HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
630 writel(ih_mute, ®s->ih_mute);
632 /* enable i2c master done irq */
633 writel(~0x04, ®s->i2cm_int);
635 /* enable i2c client nack % arbitration error irq */
636 writel(~0x44, ®s->i2cm_ctlint);
638 /* enable phy i2cm done irq */
639 writel(HDMI_PHY_I2CM_INT_ADDR_DONE_POL, ®s->phy_i2cm_int_addr);
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 ®s->phy_i2cm_ctlint_addr);
646 /* enable cable hot plug irq */
647 writel((u8)~HDMI_PHY_HPD, ®s->phy_mask0);
649 /* clear hotplug interrupts */
650 writel(HDMI_IH_PHY_STAT0_HPD, ®s->ih_phy_stat0);
653 static int hdmi_get_plug_in_status(struct rk3288_hdmi *regs)
655 uint val = readl(®s->phy_stat0) & HDMI_PHY_HPD;
660 static int hdmi_wait_for_hpd(struct rk3288_hdmi *regs)
664 start = get_timer(0);
666 if (hdmi_get_plug_in_status(regs))
669 } while (get_timer(start) < 300);
674 static int hdmi_ddc_wait_i2c_done(struct rk3288_hdmi *regs, int msec)
679 start = get_timer(0);
681 val = readl(®s->ih_i2cm_stat0);
683 writel(val, ®s->ih_i2cm_stat0);
688 } while (get_timer(start) < msec);
693 static void hdmi_ddc_reset(struct rk3288_hdmi *regs)
695 clrbits_le32(®s->i2cm_softrstz, HDMI_I2CM_SOFTRSTZ);
698 static int hdmi_read_edid(struct rk3288_hdmi *regs, int block, u8 *buff)
700 int shift = (block % 2) * 0x80;
701 int edid_read_err = 0;
705 /* set ddc i2c clk which devided from ddc_clk to 100khz */
706 writel(0x7a, ®s->i2cm_ss_scl_hcnt_0_addr);
707 writel(0x8d, ®s->i2cm_ss_scl_lcnt_0_addr);
710 * TODO(sjg@chromium.org): The above values don't work - these ones
711 * work better, but generate lots of errors in the data.
713 writel(0x0d, ®s->i2cm_ss_scl_hcnt_0_addr);
714 writel(0x0d, ®s->i2cm_ss_scl_lcnt_0_addr);
715 clrsetbits_le32(®s->i2cm_div, HDMI_I2CM_DIV_FAST_STD_MODE,
716 HDMI_I2CM_DIV_STD_MODE);
718 writel(HDMI_I2CM_SLAVE_DDC_ADDR, ®s->i2cm_slave);
719 writel(HDMI_I2CM_SEGADDR_DDC, ®s->i2cm_segaddr);
720 writel(block >> 1, ®s->i2cm_segptr);
725 for (n = 0; n < HDMI_EDID_BLOCK_SIZE / 8; n++) {
726 writel(shift + 8 * n, ®s->i2c_address);
729 clrsetbits_le32(®s->i2cm_operation,
733 clrsetbits_le32(®s->i2cm_operation,
734 HDMI_I2CM_OPT_RD8_EXT,
735 HDMI_I2CM_OPT_RD8_EXT);
737 if (hdmi_ddc_wait_i2c_done(regs, 10)) {
738 hdmi_ddc_reset(regs);
743 for (j = 0; j < 8; j++) {
744 val = readl(®s->i2cm_buf0 + j);
745 buff[8 * n + j] = val;
753 return edid_read_err;
756 static const 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,
791 static int rk_hdmi_read_edid(struct udevice *dev, u8 *buf, int buf_size)
793 struct rk_hdmi_priv *priv = dev_get_priv(dev);
794 u32 edid_size = HDMI_EDID_BLOCK_SIZE;
798 edid_size = sizeof(pre_buf);
799 memcpy(buf, pre_buf, edid_size);
801 ret = hdmi_read_edid(priv->regs, 0, buf);
803 debug("failed to read edid.\n");
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;
817 static int rk_hdmi_enable(struct udevice *dev, int panel_bpp,
818 const struct display_timing *edid)
820 struct rk_hdmi_priv *priv = dev_get_priv(dev);
821 struct rk3288_hdmi *regs = priv->regs;
824 debug("hdmi, mode info : clock %d hdis %d vdis %d\n",
825 edid->pixelclock.typ, edid->hactive.typ, edid->vactive.typ);
827 hdmi_av_composer(regs, edid);
829 ret = hdmi_phy_init(regs, edid->pixelclock.typ);
833 hdmi_enable_video_path(regs);
835 hdmi_audio_fifo_reset(regs);
836 hdmi_audio_set_format(regs);
837 hdmi_audio_set_samplerate(regs, edid->pixelclock.typ);
839 hdmi_video_packetize(regs);
840 hdmi_video_csc(regs);
841 hdmi_video_sample(regs);
843 hdmi_clear_overflow(regs);
848 static int rk_hdmi_ofdata_to_platdata(struct udevice *dev)
850 struct rk_hdmi_priv *priv = dev_get_priv(dev);
852 priv->regs = (struct rk3288_hdmi *)dev_get_addr(dev);
853 priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
858 static int rk_hdmi_probe(struct udevice *dev)
860 struct display_plat *uc_plat = dev_get_uclass_platdata(dev);
861 struct rk_hdmi_priv *priv = dev_get_priv(dev);
865 int vop_id = uc_plat->source_id;
867 ret = clk_get_by_index(dev, 0, &clk);
869 ret = clk_set_rate(&clk, 0);
873 debug("%s: Failed to set EDP clock: ret=%d\n", __func__, ret);
878 * Configure the maximum clock to permit whatever resolution the
881 ret = clk_get_by_index(uc_plat->src_dev, 0, &clk);
883 ret = clk_set_rate(&clk, 384000000);
887 debug("%s: Failed to set clock in source device '%s': ret=%d\n",
888 __func__, uc_plat->src_dev->name, ret);
892 ret = regulator_get_by_platname("vcc50_hdmi", ®);
894 ret = regulator_set_enable(reg, true);
896 debug("%s: Cannot set regulator vcc50_hdmi\n", __func__);
898 /* hdmi source select hdmi controller */
899 rk_setreg(&priv->grf->soc_con6, 1 << 15);
901 /* hdmi data from vop id */
902 rk_clrsetreg(&priv->grf->soc_con6, 1 << 4,
903 (vop_id == 1) ? (1 << 4) : 0);
905 ret = hdmi_wait_for_hpd(priv->regs);
907 debug("hdmi can not get hpd signal\n");
911 hdmi_init_interrupt(priv->regs);
916 static const struct dm_display_ops rk_hdmi_ops = {
917 .read_edid = rk_hdmi_read_edid,
918 .enable = rk_hdmi_enable,
921 static const struct udevice_id rk_hdmi_ids[] = {
922 { .compatible = "rockchip,rk3288-dw-hdmi" },
926 U_BOOT_DRIVER(hdmi_rockchip) = {
927 .name = "hdmi_rockchip",
928 .id = UCLASS_DISPLAY,
929 .of_match = rk_hdmi_ids,
931 .ofdata_to_platdata = rk_hdmi_ofdata_to_platdata,
932 .probe = rk_hdmi_probe,
933 .priv_auto_alloc_size = sizeof(struct rk_hdmi_priv),