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 = 74250000,
89 		.sym_ctr = 0x8009, .term = 0x0004, .vlev_ctr = 0x0272,
90 	}, {
91 		.mpixelclock = 148500000,
92 		.sym_ctr = 0x802b, .term = 0x0004, .vlev_ctr = 0x028d,
93 	}, {
94 		.mpixelclock = 297000000,
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 = 40000000,
105 		.cpce = 0x00b3, .gmp = 0x0000, .curr = 0x0018,
106 	}, {
107 		.mpixelclock = 65000000,
108 		.cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028,
109 	}, {
110 		.mpixelclock = 66000000,
111 		.cpce = 0x013e, .gmp = 0x0003, .curr = 0x0038,
112 	}, {
113 		.mpixelclock = 835000000,
114 		.cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028,
115 	}, {
116 		.mpixelclock = 146250000,
117 		.cpce = 0x0051, .gmp = 0x0002, .curr = 0x0038,
118 	}, {
119 		.mpixelclock = 148500000,
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 	uint cts3;
136 	uint 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 	uint 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 	uint 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, uint 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 	uint 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 	bool mdataenablepolarity = true;
485 	uint 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 	uint 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 	uint 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 	uint 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 int hdmi_get_plug_in_status(struct rk3288_hdmi *regs)
654 {
655 	uint 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) < 300);
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 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,
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 hdmi 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_clrsetreg(&priv->grf->soc_con6, 1 << 4,
903 		     (vop_id == 1) ? (1 << 4) : 0);
904 
905 	ret = hdmi_wait_for_hpd(priv->regs);
906 	if (ret < 0) {
907 		debug("hdmi can not get hpd signal\n");
908 		return -1;
909 	}
910 
911 	hdmi_init_interrupt(priv->regs);
912 
913 	return 0;
914 }
915 
916 static const struct dm_display_ops rk_hdmi_ops = {
917 	.read_edid = rk_hdmi_read_edid,
918 	.enable = rk_hdmi_enable,
919 };
920 
921 static const struct udevice_id rk_hdmi_ids[] = {
922 	{ .compatible = "rockchip,rk3288-dw-hdmi" },
923 	{ }
924 };
925 
926 U_BOOT_DRIVER(hdmi_rockchip) = {
927 	.name	= "hdmi_rockchip",
928 	.id	= UCLASS_DISPLAY,
929 	.of_match = rk_hdmi_ids,
930 	.ops	= &rk_hdmi_ops,
931 	.ofdata_to_platdata	= rk_hdmi_ofdata_to_platdata,
932 	.probe	= rk_hdmi_probe,
933 	.priv_auto_alloc_size	 = sizeof(struct rk_hdmi_priv),
934 };
935