xref: /openbmc/u-boot/drivers/video/dw_hdmi.c (revision 9d466f2f)
1 /*
2  * Copyright (c) 2015 Google, Inc
3  * Copyright 2014 Rockchip Inc.
4  * Copyright 2017 Jernej Skrabec <jernej.skrabec@siol.net>
5  *
6  * SPDX-License-Identifier:	GPL-2.0+
7  */
8 
9 #include <common.h>
10 #include <fdtdec.h>
11 #include <asm/io.h>
12 #include "dw_hdmi.h"
13 
14 struct tmds_n_cts {
15 	u32 tmds;
16 	u32 cts;
17 	u32 n;
18 };
19 
20 static const struct tmds_n_cts n_cts_table[] = {
21 	{
22 		.tmds = 25175000, .n = 6144, .cts = 25175,
23 	}, {
24 		.tmds = 25200000, .n = 6144, .cts = 25200,
25 	}, {
26 		.tmds = 27000000, .n = 6144, .cts = 27000,
27 	}, {
28 		.tmds = 27027000, .n = 6144, .cts = 27027,
29 	}, {
30 		.tmds = 40000000, .n = 6144, .cts = 40000,
31 	}, {
32 		.tmds = 54000000, .n = 6144, .cts = 54000,
33 	}, {
34 		.tmds = 54054000, .n = 6144, .cts = 54054,
35 	}, {
36 		.tmds = 65000000, .n = 6144, .cts = 65000,
37 	}, {
38 		.tmds = 74176000, .n = 11648, .cts = 140625,
39 	}, {
40 		.tmds = 74250000, .n = 6144, .cts = 74250,
41 	}, {
42 		.tmds = 83500000, .n = 6144, .cts = 83500,
43 	}, {
44 		.tmds = 106500000, .n = 6144, .cts = 106500,
45 	}, {
46 		.tmds = 108000000, .n = 6144, .cts = 108000,
47 	}, {
48 		.tmds = 148352000, .n = 5824, .cts = 140625,
49 	}, {
50 		.tmds = 148500000, .n = 6144, .cts = 148500,
51 	}, {
52 		.tmds = 297000000, .n = 5120, .cts = 247500,
53 	}
54 };
55 
56 static void hdmi_write(struct dw_hdmi *hdmi, u8 val, int offset)
57 {
58 	switch (hdmi->reg_io_width) {
59 	case 1:
60 		writeb(val, hdmi->ioaddr + offset);
61 		break;
62 	case 4:
63 		writel(val, hdmi->ioaddr + (offset << 2));
64 		break;
65 	default:
66 		debug("reg_io_width has unsupported width!\n");
67 		break;
68 	}
69 }
70 
71 static u8 hdmi_read(struct dw_hdmi *hdmi, int offset)
72 {
73 	switch (hdmi->reg_io_width) {
74 	case 1:
75 		return readb(hdmi->ioaddr + offset);
76 	case 4:
77 		return readl(hdmi->ioaddr + (offset << 2));
78 	default:
79 		debug("reg_io_width has unsupported width!\n");
80 		break;
81 	}
82 
83 	return 0;
84 }
85 
86 static void hdmi_mod(struct dw_hdmi *hdmi, unsigned reg, u8 mask, u8 data)
87 {
88 	u8 val = hdmi_read(hdmi, reg) & ~mask;
89 
90 	val |= data & mask;
91 	hdmi_write(hdmi, val, reg);
92 }
93 
94 static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi, u32 n, u32 cts)
95 {
96 	uint cts3;
97 	uint n3;
98 
99 	/* first set ncts_atomic_write (if present) */
100 	n3 = HDMI_AUD_N3_NCTS_ATOMIC_WRITE;
101 	hdmi_write(hdmi, n3, HDMI_AUD_N3);
102 
103 	/* set cts_manual (if present) */
104 	cts3 = HDMI_AUD_CTS3_CTS_MANUAL;
105 
106 	cts3 |= HDMI_AUD_CTS3_N_SHIFT_1 << HDMI_AUD_CTS3_N_SHIFT_OFFSET;
107 	cts3 |= (cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK;
108 
109 	/* write cts values; cts3 must be written first */
110 	hdmi_write(hdmi, cts3, HDMI_AUD_CTS3);
111 	hdmi_write(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
112 	hdmi_write(hdmi, cts & 0xff, HDMI_AUD_CTS1);
113 
114 	/* write n values; n1 must be written last */
115 	n3 |= (n >> 16) & HDMI_AUD_N3_AUDN19_16_MASK;
116 	hdmi_write(hdmi, n3, HDMI_AUD_N3);
117 	hdmi_write(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
118 	hdmi_write(hdmi, n & 0xff, HDMI_AUD_N3);
119 
120 	hdmi_write(hdmi, HDMI_AUD_INPUTCLKFS_128, HDMI_AUD_INPUTCLKFS);
121 }
122 
123 static int hdmi_lookup_n_cts(u32 pixel_clk)
124 {
125 	int i;
126 
127 	for (i = 0; i < ARRAY_SIZE(n_cts_table); i++)
128 		if (pixel_clk <= n_cts_table[i].tmds)
129 			break;
130 
131 	if (i >= ARRAY_SIZE(n_cts_table))
132 		return -1;
133 
134 	return i;
135 }
136 
137 static void hdmi_audio_set_samplerate(struct dw_hdmi *hdmi, u32 pixel_clk)
138 {
139 	u32 clk_n, clk_cts;
140 	int index;
141 
142 	index = hdmi_lookup_n_cts(pixel_clk);
143 	if (index == -1) {
144 		debug("audio not supported for pixel clk %d\n", pixel_clk);
145 		return;
146 	}
147 
148 	clk_n = n_cts_table[index].n;
149 	clk_cts = n_cts_table[index].cts;
150 	hdmi_set_clock_regenerator(hdmi, clk_n, clk_cts);
151 }
152 
153 /*
154  * this submodule is responsible for the video data synchronization.
155  * for example, for rgb 4:4:4 input, the data map is defined as
156  *			pin{47~40} <==> r[7:0]
157  *			pin{31~24} <==> g[7:0]
158  *			pin{15~8}  <==> b[7:0]
159  */
160 static void hdmi_video_sample(struct dw_hdmi *hdmi)
161 {
162 	u32 color_format = 0x01;
163 	uint val;
164 
165 	val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
166 	      ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
167 	      HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
168 
169 	hdmi_write(hdmi, val, HDMI_TX_INVID0);
170 
171 	/* enable tx stuffing: when de is inactive, fix the output data to 0 */
172 	val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
173 	      HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
174 	      HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
175 	hdmi_write(hdmi, val, HDMI_TX_INSTUFFING);
176 	hdmi_write(hdmi, 0x0, HDMI_TX_GYDATA0);
177 	hdmi_write(hdmi, 0x0, HDMI_TX_GYDATA1);
178 	hdmi_write(hdmi, 0x0, HDMI_TX_RCRDATA0);
179 	hdmi_write(hdmi, 0x0, HDMI_TX_RCRDATA1);
180 	hdmi_write(hdmi, 0x0, HDMI_TX_BCBDATA0);
181 	hdmi_write(hdmi, 0x0, HDMI_TX_BCBDATA1);
182 }
183 
184 static void hdmi_video_packetize(struct dw_hdmi *hdmi)
185 {
186 	u32 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
187 	u32 remap_size = HDMI_VP_REMAP_YCC422_16BIT;
188 	u32 color_depth = 0;
189 	uint val, vp_conf;
190 
191 	/* set the packetizer registers */
192 	val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
193 		HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
194 		((0 << HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
195 		HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
196 	hdmi_write(hdmi, val, HDMI_VP_PR_CD);
197 
198 	hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PR_STUFFING_MASK,
199 		 HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE);
200 
201 	/* data from pixel repeater block */
202 	vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
203 		  HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
204 
205 	hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_PR_EN_MASK |
206 		 HDMI_VP_CONF_BYPASS_SELECT_MASK, vp_conf);
207 
208 	hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_IDEFAULT_PHASE_MASK,
209 		 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET);
210 
211 	hdmi_write(hdmi, remap_size, HDMI_VP_REMAP);
212 
213 	vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
214 		  HDMI_VP_CONF_PP_EN_DISABLE |
215 		  HDMI_VP_CONF_YCC422_EN_DISABLE;
216 
217 	hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_BYPASS_EN_MASK |
218 		 HDMI_VP_CONF_PP_EN_ENMASK | HDMI_VP_CONF_YCC422_EN_MASK,
219 		 vp_conf);
220 
221 	hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PP_STUFFING_MASK |
222 		 HDMI_VP_STUFF_YCC422_STUFFING_MASK,
223 		 HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
224 		 HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE);
225 
226 	hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
227 		 output_select);
228 }
229 
230 static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, uint bit)
231 {
232 	hdmi_mod(hdmi, HDMI_PHY_TST0, HDMI_PHY_TST0_TSTCLR_MASK,
233 		 bit << HDMI_PHY_TST0_TSTCLR_OFFSET);
234 }
235 
236 static int hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, u32 msec)
237 {
238 	ulong start;
239 	u32 val;
240 
241 	start = get_timer(0);
242 	do {
243 		val = hdmi_read(hdmi, HDMI_IH_I2CMPHY_STAT0);
244 		if (val & 0x3) {
245 			hdmi_write(hdmi, val, HDMI_IH_I2CMPHY_STAT0);
246 			return 0;
247 		}
248 
249 		udelay(100);
250 	} while (get_timer(start) < msec);
251 
252 	return 1;
253 }
254 
255 static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, uint data, uint addr)
256 {
257 	hdmi_write(hdmi, 0xff, HDMI_IH_I2CMPHY_STAT0);
258 	hdmi_write(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
259 	hdmi_write(hdmi, (u8)(data >> 8), HDMI_PHY_I2CM_DATAO_1_ADDR);
260 	hdmi_write(hdmi, (u8)(data >> 0), HDMI_PHY_I2CM_DATAO_0_ADDR);
261 	hdmi_write(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
262 		   HDMI_PHY_I2CM_OPERATION_ADDR);
263 
264 	hdmi_phy_wait_i2c_done(hdmi, 1000);
265 }
266 
267 static void hdmi_phy_enable_power(struct dw_hdmi *hdmi, uint enable)
268 {
269 	hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_PDZ_MASK,
270 		 enable << HDMI_PHY_CONF0_PDZ_OFFSET);
271 }
272 
273 static void hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, uint enable)
274 {
275 	hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_ENTMDS_MASK,
276 		 enable << HDMI_PHY_CONF0_ENTMDS_OFFSET);
277 }
278 
279 static void hdmi_phy_enable_spare(struct dw_hdmi *hdmi, uint enable)
280 {
281 	hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SPARECTRL_MASK,
282 		 enable << HDMI_PHY_CONF0_SPARECTRL_OFFSET);
283 }
284 
285 static void hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, uint enable)
286 {
287 	hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_GEN2_PDDQ_MASK,
288 		 enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET);
289 }
290 
291 static void hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, uint enable)
292 {
293 	hdmi_mod(hdmi, HDMI_PHY_CONF0,
294 		 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK,
295 		 enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET);
296 }
297 
298 static void hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, uint enable)
299 {
300 	hdmi_mod(hdmi, HDMI_PHY_CONF0,
301 		 HDMI_PHY_CONF0_SELDATAENPOL_MASK,
302 		 enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET);
303 }
304 
305 static void hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi,
306 					   uint enable)
307 {
308 	hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SELDIPIF_MASK,
309 		 enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET);
310 }
311 
312 static int hdmi_phy_configure(struct dw_hdmi *hdmi, u32 mpixelclock)
313 {
314 	ulong start;
315 	uint i, val;
316 
317 	if (!hdmi->mpll_cfg || !hdmi->phy_cfg)
318 		return -1;
319 
320 	/* gen2 tx power off */
321 	hdmi_phy_gen2_txpwron(hdmi, 0);
322 
323 	/* gen2 pddq */
324 	hdmi_phy_gen2_pddq(hdmi, 1);
325 
326 	/* phy reset */
327 	hdmi_write(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
328 	hdmi_write(hdmi, HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
329 	hdmi_write(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
330 
331 	hdmi_phy_test_clear(hdmi, 1);
332 	hdmi_write(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
333 		   HDMI_PHY_I2CM_SLAVE_ADDR);
334 	hdmi_phy_test_clear(hdmi, 0);
335 
336 	/* pll/mpll cfg - always match on final entry */
337 	for (i = 0; hdmi->mpll_cfg[i].mpixelclock != (~0ul); i++)
338 		if (mpixelclock <= hdmi->mpll_cfg[i].mpixelclock)
339 			break;
340 
341 	hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].cpce, PHY_OPMODE_PLLCFG);
342 	hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].gmp, PHY_PLLGMPCTRL);
343 	hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].curr, PHY_PLLCURRCTRL);
344 
345 	hdmi_phy_i2c_write(hdmi, 0x0000, PHY_PLLPHBYCTRL);
346 	hdmi_phy_i2c_write(hdmi, 0x0006, PHY_PLLCLKBISTPHASE);
347 
348 	for (i = 0; hdmi->phy_cfg[i].mpixelclock != (~0ul); i++)
349 		if (mpixelclock <= hdmi->phy_cfg[i].mpixelclock)
350 			break;
351 
352 	/*
353 	 * resistance term 133ohm cfg
354 	 * preemp cgf 0.00
355 	 * tx/ck lvl 10
356 	 */
357 	hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].term, PHY_TXTERM);
358 	hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].sym_ctr, PHY_CKSYMTXCTRL);
359 	hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].vlev_ctr, PHY_VLEVCTRL);
360 
361 	/* remove clk term */
362 	hdmi_phy_i2c_write(hdmi, 0x8000, PHY_CKCALCTRL);
363 
364 	hdmi_phy_enable_power(hdmi, 1);
365 
366 	/* toggle tmds enable */
367 	hdmi_phy_enable_tmds(hdmi, 0);
368 	hdmi_phy_enable_tmds(hdmi, 1);
369 
370 	/* gen2 tx power on */
371 	hdmi_phy_gen2_txpwron(hdmi, 1);
372 	hdmi_phy_gen2_pddq(hdmi, 0);
373 
374 	hdmi_phy_enable_spare(hdmi, 1);
375 
376 	/* wait for phy pll lock */
377 	start = get_timer(0);
378 	do {
379 		val = hdmi_read(hdmi, HDMI_PHY_STAT0);
380 		if (!(val & HDMI_PHY_TX_PHY_LOCK))
381 			return 0;
382 
383 		udelay(100);
384 	} while (get_timer(start) < 5);
385 
386 	return -1;
387 }
388 
389 static void hdmi_av_composer(struct dw_hdmi *hdmi,
390 			     const struct display_timing *edid)
391 {
392 	bool mdataenablepolarity = true;
393 	uint inv_val;
394 	uint hbl;
395 	uint vbl;
396 
397 	hbl = edid->hback_porch.typ + edid->hfront_porch.typ +
398 			edid->hsync_len.typ;
399 	vbl = edid->vback_porch.typ + edid->vfront_porch.typ +
400 			edid->vsync_len.typ;
401 
402 	/* set up hdmi_fc_invidconf */
403 	inv_val = HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE;
404 
405 	inv_val |= (edid->flags & DISPLAY_FLAGS_HSYNC_HIGH ?
406 		   HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
407 		   HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
408 
409 	inv_val |= (edid->flags & DISPLAY_FLAGS_VSYNC_HIGH ?
410 		   HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
411 		   HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
412 
413 	inv_val |= (mdataenablepolarity ?
414 		   HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
415 		   HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
416 
417 	inv_val |= (edid->hdmi_monitor ?
418 		   HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
419 		   HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE);
420 
421 	inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
422 
423 	inv_val |= HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
424 
425 	hdmi_write(hdmi, inv_val, HDMI_FC_INVIDCONF);
426 
427 	/* set up horizontal active pixel width */
428 	hdmi_write(hdmi, edid->hactive.typ >> 8, HDMI_FC_INHACTV1);
429 	hdmi_write(hdmi, edid->hactive.typ, HDMI_FC_INHACTV0);
430 
431 	/* set up vertical active lines */
432 	hdmi_write(hdmi, edid->vactive.typ >> 8, HDMI_FC_INVACTV1);
433 	hdmi_write(hdmi, edid->vactive.typ, HDMI_FC_INVACTV0);
434 
435 	/* set up horizontal blanking pixel region width */
436 	hdmi_write(hdmi, hbl >> 8, HDMI_FC_INHBLANK1);
437 	hdmi_write(hdmi, hbl, HDMI_FC_INHBLANK0);
438 
439 	/* set up vertical blanking pixel region width */
440 	hdmi_write(hdmi, vbl, HDMI_FC_INVBLANK);
441 
442 	/* set up hsync active edge delay width (in pixel clks) */
443 	hdmi_write(hdmi, edid->hfront_porch.typ >> 8, HDMI_FC_HSYNCINDELAY1);
444 	hdmi_write(hdmi, edid->hfront_porch.typ, HDMI_FC_HSYNCINDELAY0);
445 
446 	/* set up vsync active edge delay (in lines) */
447 	hdmi_write(hdmi, edid->vfront_porch.typ, HDMI_FC_VSYNCINDELAY);
448 
449 	/* set up hsync active pulse width (in pixel clks) */
450 	hdmi_write(hdmi, edid->hsync_len.typ >> 8, HDMI_FC_HSYNCINWIDTH1);
451 	hdmi_write(hdmi, edid->hsync_len.typ, HDMI_FC_HSYNCINWIDTH0);
452 
453 	/* set up vsync active edge delay (in lines) */
454 	hdmi_write(hdmi, edid->vsync_len.typ, HDMI_FC_VSYNCINWIDTH);
455 }
456 
457 /* hdmi initialization step b.4 */
458 static void hdmi_enable_video_path(struct dw_hdmi *hdmi, bool audio)
459 {
460 	uint clkdis;
461 
462 	/* control period minimum duration */
463 	hdmi_write(hdmi, 12, HDMI_FC_CTRLDUR);
464 	hdmi_write(hdmi, 32, HDMI_FC_EXCTRLDUR);
465 	hdmi_write(hdmi, 1, HDMI_FC_EXCTRLSPAC);
466 
467 	/* set to fill tmds data channels */
468 	hdmi_write(hdmi, 0x0b, HDMI_FC_CH0PREAM);
469 	hdmi_write(hdmi, 0x16, HDMI_FC_CH1PREAM);
470 	hdmi_write(hdmi, 0x21, HDMI_FC_CH2PREAM);
471 
472 	hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
473 		   HDMI_MC_FLOWCTRL);
474 
475 	/* enable pixel clock and tmds data path */
476 	clkdis = 0x7f;
477 	clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
478 	hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
479 
480 	clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
481 	hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
482 
483 	if (audio) {
484 		clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
485 		hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
486 	}
487 }
488 
489 /* workaround to clear the overflow condition */
490 static void hdmi_clear_overflow(struct dw_hdmi *hdmi)
491 {
492 	uint val, count;
493 
494 	/* tmds software reset */
495 	hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
496 
497 	val = hdmi_read(hdmi, HDMI_FC_INVIDCONF);
498 
499 	for (count = 0; count < 4; count++)
500 		hdmi_write(hdmi, val, HDMI_FC_INVIDCONF);
501 }
502 
503 static void hdmi_audio_set_format(struct dw_hdmi *hdmi)
504 {
505 	hdmi_write(hdmi, HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_IN_EN_0,
506 		   HDMI_AUD_CONF0);
507 
508 
509 	hdmi_write(hdmi, HDMI_AUD_CONF1_I2S_MODE_STANDARD_MODE |
510 		   HDMI_AUD_CONF1_I2S_WIDTH_16BIT, HDMI_AUD_CONF1);
511 
512 	hdmi_write(hdmi, 0x00, HDMI_AUD_CONF2);
513 }
514 
515 static void hdmi_audio_fifo_reset(struct dw_hdmi *hdmi)
516 {
517 	hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_II2SSWRST_REQ, HDMI_MC_SWRSTZ);
518 	hdmi_write(hdmi, HDMI_AUD_CONF0_SW_AUDIO_FIFO_RST, HDMI_AUD_CONF0);
519 
520 	hdmi_write(hdmi, 0x00, HDMI_AUD_INT);
521 	hdmi_write(hdmi, 0x00, HDMI_AUD_INT1);
522 }
523 
524 static int hdmi_get_plug_in_status(struct dw_hdmi *hdmi)
525 {
526 	uint val = hdmi_read(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD;
527 
528 	return !!val;
529 }
530 
531 static int hdmi_ddc_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
532 {
533 	u32 val;
534 	ulong start;
535 
536 	start = get_timer(0);
537 	do {
538 		val = hdmi_read(hdmi, HDMI_IH_I2CM_STAT0);
539 		if (val & 0x2) {
540 			hdmi_write(hdmi, val, HDMI_IH_I2CM_STAT0);
541 			return 0;
542 		}
543 
544 		udelay(100);
545 	} while (get_timer(start) < msec);
546 
547 	return 1;
548 }
549 
550 static void hdmi_ddc_reset(struct dw_hdmi *hdmi)
551 {
552 	hdmi_mod(hdmi, HDMI_I2CM_SOFTRSTZ, HDMI_I2CM_SOFTRSTZ_MASK, 0);
553 }
554 
555 static int hdmi_read_edid(struct dw_hdmi *hdmi, int block, u8 *buff)
556 {
557 	int shift = (block % 2) * 0x80;
558 	int edid_read_err = 0;
559 	u32 trytime = 5;
560 	u32 n;
561 
562 	/* set ddc i2c clk which devided from ddc_clk to 100khz */
563 	hdmi_write(hdmi, hdmi->i2c_clk_high, HDMI_I2CM_SS_SCL_HCNT_0_ADDR);
564 	hdmi_write(hdmi, hdmi->i2c_clk_low, HDMI_I2CM_SS_SCL_LCNT_0_ADDR);
565 	hdmi_mod(hdmi, HDMI_I2CM_DIV, HDMI_I2CM_DIV_FAST_STD_MODE,
566 		 HDMI_I2CM_DIV_STD_MODE);
567 
568 	hdmi_write(hdmi, HDMI_I2CM_SLAVE_DDC_ADDR, HDMI_I2CM_SLAVE);
569 	hdmi_write(hdmi, HDMI_I2CM_SEGADDR_DDC, HDMI_I2CM_SEGADDR);
570 	hdmi_write(hdmi, block >> 1, HDMI_I2CM_SEGPTR);
571 
572 	while (trytime--) {
573 		edid_read_err = 0;
574 
575 		for (n = 0; n < HDMI_EDID_BLOCK_SIZE; n++) {
576 			hdmi_write(hdmi, shift + n, HDMI_I2CM_ADDRESS);
577 
578 			if (block == 0)
579 				hdmi_write(hdmi, HDMI_I2CM_OP_RD8,
580 					   HDMI_I2CM_OPERATION);
581 			else
582 				hdmi_write(hdmi, HDMI_I2CM_OP_RD8_EXT,
583 					   HDMI_I2CM_OPERATION);
584 
585 			if (hdmi_ddc_wait_i2c_done(hdmi, 10)) {
586 				hdmi_ddc_reset(hdmi);
587 				edid_read_err = 1;
588 				break;
589 			}
590 
591 			buff[n] = hdmi_read(hdmi, HDMI_I2CM_DATAI);
592 		}
593 
594 		if (!edid_read_err)
595 			break;
596 	}
597 
598 	return edid_read_err;
599 }
600 
601 static const u8 pre_buf[] = {
602 	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
603 	0x04, 0x69, 0xfa, 0x23, 0xc8, 0x28, 0x01, 0x00,
604 	0x10, 0x17, 0x01, 0x03, 0x80, 0x33, 0x1d, 0x78,
605 	0x2a, 0xd9, 0x45, 0xa2, 0x55, 0x4d, 0xa0, 0x27,
606 	0x12, 0x50, 0x54, 0xb7, 0xef, 0x00, 0x71, 0x4f,
607 	0x81, 0x40, 0x81, 0x80, 0x95, 0x00, 0xb3, 0x00,
608 	0xd1, 0xc0, 0x81, 0xc0, 0x81, 0x00, 0x02, 0x3a,
609 	0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
610 	0x45, 0x00, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
611 	0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x34, 0x4c,
612 	0x4d, 0x54, 0x46, 0x30, 0x37, 0x35, 0x39, 0x37,
613 	0x36, 0x0a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
614 	0x4b, 0x18, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20,
615 	0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
616 	0x00, 0x41, 0x53, 0x55, 0x53, 0x20, 0x56, 0x53,
617 	0x32, 0x33, 0x38, 0x0a, 0x20, 0x20, 0x01, 0xb0,
618 	0x02, 0x03, 0x22, 0x71, 0x4f, 0x01, 0x02, 0x03,
619 	0x11, 0x12, 0x13, 0x04, 0x14, 0x05, 0x0e, 0x0f,
620 	0x1d, 0x1e, 0x1f, 0x10, 0x23, 0x09, 0x17, 0x07,
621 	0x83, 0x01, 0x00, 0x00, 0x65, 0x03, 0x0c, 0x00,
622 	0x10, 0x00, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0,
623 	0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xfd, 0x1e,
624 	0x11, 0x00, 0x00, 0x18, 0x01, 0x1d, 0x00, 0x72,
625 	0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
626 	0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e, 0x01, 0x1d,
627 	0x00, 0xbc, 0x52, 0xd0, 0x1e, 0x20, 0xb8, 0x28,
628 	0x55, 0x40, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
629 	0x8c, 0x0a, 0xd0, 0x90, 0x20, 0x40, 0x31, 0x20,
630 	0x0c, 0x40, 0x55, 0x00, 0xfd, 0x1e, 0x11, 0x00,
631 	0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9,
634 };
635 
636 int dw_hdmi_phy_cfg(struct dw_hdmi *hdmi, uint mpixelclock)
637 {
638 	int i, ret;
639 
640 	/* hdmi phy spec says to do the phy initialization sequence twice */
641 	for (i = 0; i < 2; i++) {
642 		hdmi_phy_sel_data_en_pol(hdmi, 1);
643 		hdmi_phy_sel_interface_control(hdmi, 0);
644 		hdmi_phy_enable_tmds(hdmi, 0);
645 		hdmi_phy_enable_power(hdmi, 0);
646 
647 		ret = hdmi_phy_configure(hdmi, mpixelclock);
648 		if (ret) {
649 			debug("hdmi phy config failure %d\n", ret);
650 			return ret;
651 		}
652 	}
653 
654 	return 0;
655 }
656 
657 int dw_hdmi_phy_wait_for_hpd(struct dw_hdmi *hdmi)
658 {
659 	ulong start;
660 
661 	start = get_timer(0);
662 	do {
663 		if (hdmi_get_plug_in_status(hdmi))
664 			return 0;
665 		udelay(100);
666 	} while (get_timer(start) < 300);
667 
668 	return -1;
669 }
670 
671 void dw_hdmi_phy_init(struct dw_hdmi *hdmi)
672 {
673 	/* enable phy i2cm done irq */
674 	hdmi_write(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
675 		   HDMI_PHY_I2CM_INT_ADDR);
676 
677 	/* enable phy i2cm nack & arbitration error irq */
678 	hdmi_write(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
679 		   HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
680 		   HDMI_PHY_I2CM_CTLINT_ADDR);
681 
682 	/* enable cable hot plug irq */
683 	hdmi_write(hdmi, (u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
684 
685 	/* clear hotplug interrupts */
686 	hdmi_write(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
687 }
688 
689 int dw_hdmi_read_edid(struct dw_hdmi *hdmi, u8 *buf, int buf_size)
690 {
691 	u32 edid_size = HDMI_EDID_BLOCK_SIZE;
692 	int ret;
693 
694 	if (0) {
695 		edid_size = sizeof(pre_buf);
696 		memcpy(buf, pre_buf, edid_size);
697 	} else {
698 		ret = hdmi_read_edid(hdmi, 0, buf);
699 		if (ret) {
700 			debug("failed to read edid.\n");
701 			return -1;
702 		}
703 
704 		if (buf[0x7e] != 0) {
705 			hdmi_read_edid(hdmi, 1, buf + HDMI_EDID_BLOCK_SIZE);
706 			edid_size += HDMI_EDID_BLOCK_SIZE;
707 		}
708 	}
709 
710 	return edid_size;
711 }
712 
713 int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
714 {
715 	int ret;
716 
717 	debug("%s, mode info : clock %d hdis %d vdis %d\n",
718 	      edid->hdmi_monitor ? "hdmi" : "dvi",
719 	      edid->pixelclock.typ, edid->hactive.typ, edid->vactive.typ);
720 
721 	hdmi_av_composer(hdmi, edid);
722 
723 	ret = hdmi->phy_set(hdmi, edid->pixelclock.typ);
724 	if (ret)
725 		return ret;
726 
727 	hdmi_enable_video_path(hdmi, edid->hdmi_monitor);
728 
729 	if (edid->hdmi_monitor) {
730 		hdmi_audio_fifo_reset(hdmi);
731 		hdmi_audio_set_format(hdmi);
732 		hdmi_audio_set_samplerate(hdmi, edid->pixelclock.typ);
733 	}
734 
735 	hdmi_video_packetize(hdmi);
736 	hdmi_video_sample(hdmi);
737 
738 	hdmi_clear_overflow(hdmi);
739 
740 	return 0;
741 }
742 
743 void dw_hdmi_init(struct dw_hdmi *hdmi)
744 {
745 	uint ih_mute;
746 
747 	/*
748 	 * boot up defaults are:
749 	 * hdmi_ih_mute   = 0x03 (disabled)
750 	 * hdmi_ih_mute_* = 0x00 (enabled)
751 	 *
752 	 * disable top level interrupt bits in hdmi block
753 	 */
754 	ih_mute = /*hdmi_read(hdmi, HDMI_IH_MUTE) |*/
755 		  HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
756 		  HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
757 
758 	hdmi_write(hdmi, ih_mute, HDMI_IH_MUTE);
759 
760 	/* enable i2c master done irq */
761 	hdmi_write(hdmi, ~0x04, HDMI_I2CM_INT);
762 
763 	/* enable i2c client nack % arbitration error irq */
764 	hdmi_write(hdmi, ~0x44, HDMI_I2CM_CTLINT);
765 }
766