blob: 5fcb61ac2a3eddd6affc40c1db07bed6f49d467a [file] [log] [blame]
Simon Glass0139ae62016-01-21 19:45:03 -07001/*
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
22struct tmds_n_cts {
23 u32 tmds;
24 u32 cts;
25 u32 n;
26};
27
28struct rk_hdmi_priv {
29 struct rk3288_hdmi *regs;
30 struct rk3288_grf *grf;
31};
32
33static 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
69struct 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
79struct 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
86static 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
102static 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
127static const u32 csc_coeff_default[3][4] = {
128 { 0x2000, 0x0000, 0x0000, 0x0000 },
129 { 0x0000, 0x2000, 0x0000, 0x0000 },
130 { 0x0000, 0x0000, 0x2000, 0x0000 }
131};
132
133static 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
162static 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
176static 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 */
199static 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
223static 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
241static 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
254static 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
300static 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
306static 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
325static 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
337static 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
343static 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
349static 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
355static 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
361static 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
368static 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
375static 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
382static 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
459static 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
481static 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 */
554static 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 */
581static 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
594static 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
606static 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
615static 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
653static 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
660static 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
674static 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
693static void hdmi_ddc_reset(struct rk3288_hdmi *regs)
694{
695 clrbits_le32(&regs->i2cm_softrstz, HDMI_I2CM_SOFTRSTZ);
696}
697
698static 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
756static 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
791static 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
817static 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
848static 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
858static 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, *clk;
863 int periph;
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 periph = ret;
870 ret = clk_set_periph_rate(clk, periph, 0);
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 periph = ret;
884 ret = clk_set_periph_rate(clk, periph, 384000000);
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
915static const struct dm_display_ops rk_hdmi_ops = {
916 .read_edid = rk_hdmi_read_edid,
917 .enable = rk_hdmi_enable,
918};
919
920static const struct udevice_id rk_hdmi_ids[] = {
921 { .compatible = "rockchip,rk3288-dw-hdmi" },
922 { }
923};
924
925U_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};