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