xref: /openbmc/u-boot/drivers/video/dw_hdmi.c (revision 6c9a1003)
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 	/*
418 	 * TODO(sjg@chromium.org>: Need to check for HDMI / DVI
419 	 * inv_val |= (edid->hdmi_monitor_detected ?
420 	 *	   HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
421 	 *	   HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE);
422 	 */
423 	inv_val |= HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE;
424 
425 	inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
426 
427 	inv_val |= HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
428 
429 	hdmi_write(hdmi, inv_val, HDMI_FC_INVIDCONF);
430 
431 	/* set up horizontal active pixel width */
432 	hdmi_write(hdmi, edid->hactive.typ >> 8, HDMI_FC_INHACTV1);
433 	hdmi_write(hdmi, edid->hactive.typ, HDMI_FC_INHACTV0);
434 
435 	/* set up vertical active lines */
436 	hdmi_write(hdmi, edid->vactive.typ >> 8, HDMI_FC_INVACTV1);
437 	hdmi_write(hdmi, edid->vactive.typ, HDMI_FC_INVACTV0);
438 
439 	/* set up horizontal blanking pixel region width */
440 	hdmi_write(hdmi, hbl >> 8, HDMI_FC_INHBLANK1);
441 	hdmi_write(hdmi, hbl, HDMI_FC_INHBLANK0);
442 
443 	/* set up vertical blanking pixel region width */
444 	hdmi_write(hdmi, vbl, HDMI_FC_INVBLANK);
445 
446 	/* set up hsync active edge delay width (in pixel clks) */
447 	hdmi_write(hdmi, edid->hfront_porch.typ >> 8, HDMI_FC_HSYNCINDELAY1);
448 	hdmi_write(hdmi, edid->hfront_porch.typ, HDMI_FC_HSYNCINDELAY0);
449 
450 	/* set up vsync active edge delay (in lines) */
451 	hdmi_write(hdmi, edid->vfront_porch.typ, HDMI_FC_VSYNCINDELAY);
452 
453 	/* set up hsync active pulse width (in pixel clks) */
454 	hdmi_write(hdmi, edid->hsync_len.typ >> 8, HDMI_FC_HSYNCINWIDTH1);
455 	hdmi_write(hdmi, edid->hsync_len.typ, HDMI_FC_HSYNCINWIDTH0);
456 
457 	/* set up vsync active edge delay (in lines) */
458 	hdmi_write(hdmi, edid->vsync_len.typ, HDMI_FC_VSYNCINWIDTH);
459 }
460 
461 /* hdmi initialization step b.4 */
462 static void hdmi_enable_video_path(struct dw_hdmi *hdmi)
463 {
464 	uint clkdis;
465 
466 	/* control period minimum duration */
467 	hdmi_write(hdmi, 12, HDMI_FC_CTRLDUR);
468 	hdmi_write(hdmi, 32, HDMI_FC_EXCTRLDUR);
469 	hdmi_write(hdmi, 1, HDMI_FC_EXCTRLSPAC);
470 
471 	/* set to fill tmds data channels */
472 	hdmi_write(hdmi, 0x0b, HDMI_FC_CH0PREAM);
473 	hdmi_write(hdmi, 0x16, HDMI_FC_CH1PREAM);
474 	hdmi_write(hdmi, 0x21, HDMI_FC_CH2PREAM);
475 
476 	hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
477 		   HDMI_MC_FLOWCTRL);
478 
479 	/* enable pixel clock and tmds data path */
480 	clkdis = 0x7f;
481 	clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
482 	hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
483 
484 	clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
485 	hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
486 
487 	clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
488 	hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
489 }
490 
491 /* workaround to clear the overflow condition */
492 static void hdmi_clear_overflow(struct dw_hdmi *hdmi)
493 {
494 	uint val, count;
495 
496 	/* tmds software reset */
497 	hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
498 
499 	val = hdmi_read(hdmi, HDMI_FC_INVIDCONF);
500 
501 	for (count = 0; count < 4; count++)
502 		hdmi_write(hdmi, val, HDMI_FC_INVIDCONF);
503 }
504 
505 static void hdmi_audio_set_format(struct dw_hdmi *hdmi)
506 {
507 	hdmi_write(hdmi, HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_IN_EN_0,
508 		   HDMI_AUD_CONF0);
509 
510 
511 	hdmi_write(hdmi, HDMI_AUD_CONF1_I2S_MODE_STANDARD_MODE |
512 		   HDMI_AUD_CONF1_I2S_WIDTH_16BIT, HDMI_AUD_CONF1);
513 
514 	hdmi_write(hdmi, 0x00, HDMI_AUD_CONF2);
515 }
516 
517 static void hdmi_audio_fifo_reset(struct dw_hdmi *hdmi)
518 {
519 	hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_II2SSWRST_REQ, HDMI_MC_SWRSTZ);
520 	hdmi_write(hdmi, HDMI_AUD_CONF0_SW_AUDIO_FIFO_RST, HDMI_AUD_CONF0);
521 
522 	hdmi_write(hdmi, 0x00, HDMI_AUD_INT);
523 	hdmi_write(hdmi, 0x00, HDMI_AUD_INT1);
524 }
525 
526 static int hdmi_get_plug_in_status(struct dw_hdmi *hdmi)
527 {
528 	uint val = hdmi_read(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD;
529 
530 	return !!val;
531 }
532 
533 static int hdmi_ddc_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
534 {
535 	u32 val;
536 	ulong start;
537 
538 	start = get_timer(0);
539 	do {
540 		val = hdmi_read(hdmi, HDMI_IH_I2CM_STAT0);
541 		if (val & 0x2) {
542 			hdmi_write(hdmi, val, HDMI_IH_I2CM_STAT0);
543 			return 0;
544 		}
545 
546 		udelay(100);
547 	} while (get_timer(start) < msec);
548 
549 	return 1;
550 }
551 
552 static void hdmi_ddc_reset(struct dw_hdmi *hdmi)
553 {
554 	hdmi_mod(hdmi, HDMI_I2CM_SOFTRSTZ, HDMI_I2CM_SOFTRSTZ_MASK, 0);
555 }
556 
557 static int hdmi_read_edid(struct dw_hdmi *hdmi, int block, u8 *buff)
558 {
559 	int shift = (block % 2) * 0x80;
560 	int edid_read_err = 0;
561 	u32 trytime = 5;
562 	u32 n;
563 
564 	/* set ddc i2c clk which devided from ddc_clk to 100khz */
565 	hdmi_write(hdmi, hdmi->i2c_clk_high, HDMI_I2CM_SS_SCL_HCNT_0_ADDR);
566 	hdmi_write(hdmi, hdmi->i2c_clk_low, HDMI_I2CM_SS_SCL_LCNT_0_ADDR);
567 	hdmi_mod(hdmi, HDMI_I2CM_DIV, HDMI_I2CM_DIV_FAST_STD_MODE,
568 		 HDMI_I2CM_DIV_STD_MODE);
569 
570 	hdmi_write(hdmi, HDMI_I2CM_SLAVE_DDC_ADDR, HDMI_I2CM_SLAVE);
571 	hdmi_write(hdmi, HDMI_I2CM_SEGADDR_DDC, HDMI_I2CM_SEGADDR);
572 	hdmi_write(hdmi, block >> 1, HDMI_I2CM_SEGPTR);
573 
574 	while (trytime--) {
575 		edid_read_err = 0;
576 
577 		for (n = 0; n < HDMI_EDID_BLOCK_SIZE; n++) {
578 			hdmi_write(hdmi, shift + n, HDMI_I2CM_ADDRESS);
579 
580 			if (block == 0)
581 				hdmi_write(hdmi, HDMI_I2CM_OP_RD8,
582 					   HDMI_I2CM_OPERATION);
583 			else
584 				hdmi_write(hdmi, HDMI_I2CM_OP_RD8_EXT,
585 					   HDMI_I2CM_OPERATION);
586 
587 			if (hdmi_ddc_wait_i2c_done(hdmi, 10)) {
588 				hdmi_ddc_reset(hdmi);
589 				edid_read_err = 1;
590 				break;
591 			}
592 
593 			buff[n] = hdmi_read(hdmi, HDMI_I2CM_DATAI);
594 		}
595 
596 		if (!edid_read_err)
597 			break;
598 	}
599 
600 	return edid_read_err;
601 }
602 
603 static const u8 pre_buf[] = {
604 	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
605 	0x04, 0x69, 0xfa, 0x23, 0xc8, 0x28, 0x01, 0x00,
606 	0x10, 0x17, 0x01, 0x03, 0x80, 0x33, 0x1d, 0x78,
607 	0x2a, 0xd9, 0x45, 0xa2, 0x55, 0x4d, 0xa0, 0x27,
608 	0x12, 0x50, 0x54, 0xb7, 0xef, 0x00, 0x71, 0x4f,
609 	0x81, 0x40, 0x81, 0x80, 0x95, 0x00, 0xb3, 0x00,
610 	0xd1, 0xc0, 0x81, 0xc0, 0x81, 0x00, 0x02, 0x3a,
611 	0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
612 	0x45, 0x00, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
613 	0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x34, 0x4c,
614 	0x4d, 0x54, 0x46, 0x30, 0x37, 0x35, 0x39, 0x37,
615 	0x36, 0x0a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
616 	0x4b, 0x18, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20,
617 	0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
618 	0x00, 0x41, 0x53, 0x55, 0x53, 0x20, 0x56, 0x53,
619 	0x32, 0x33, 0x38, 0x0a, 0x20, 0x20, 0x01, 0xb0,
620 	0x02, 0x03, 0x22, 0x71, 0x4f, 0x01, 0x02, 0x03,
621 	0x11, 0x12, 0x13, 0x04, 0x14, 0x05, 0x0e, 0x0f,
622 	0x1d, 0x1e, 0x1f, 0x10, 0x23, 0x09, 0x17, 0x07,
623 	0x83, 0x01, 0x00, 0x00, 0x65, 0x03, 0x0c, 0x00,
624 	0x10, 0x00, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0,
625 	0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xfd, 0x1e,
626 	0x11, 0x00, 0x00, 0x18, 0x01, 0x1d, 0x00, 0x72,
627 	0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
628 	0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e, 0x01, 0x1d,
629 	0x00, 0xbc, 0x52, 0xd0, 0x1e, 0x20, 0xb8, 0x28,
630 	0x55, 0x40, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
631 	0x8c, 0x0a, 0xd0, 0x90, 0x20, 0x40, 0x31, 0x20,
632 	0x0c, 0x40, 0x55, 0x00, 0xfd, 0x1e, 0x11, 0x00,
633 	0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9,
636 };
637 
638 int dw_hdmi_phy_cfg(struct dw_hdmi *hdmi, uint mpixelclock)
639 {
640 	int i, ret;
641 
642 	/* hdmi phy spec says to do the phy initialization sequence twice */
643 	for (i = 0; i < 2; i++) {
644 		hdmi_phy_sel_data_en_pol(hdmi, 1);
645 		hdmi_phy_sel_interface_control(hdmi, 0);
646 		hdmi_phy_enable_tmds(hdmi, 0);
647 		hdmi_phy_enable_power(hdmi, 0);
648 
649 		ret = hdmi_phy_configure(hdmi, mpixelclock);
650 		if (ret) {
651 			debug("hdmi phy config failure %d\n", ret);
652 			return ret;
653 		}
654 	}
655 
656 	return 0;
657 }
658 
659 int dw_hdmi_phy_wait_for_hpd(struct dw_hdmi *hdmi)
660 {
661 	ulong start;
662 
663 	start = get_timer(0);
664 	do {
665 		if (hdmi_get_plug_in_status(hdmi))
666 			return 0;
667 		udelay(100);
668 	} while (get_timer(start) < 300);
669 
670 	return -1;
671 }
672 
673 void dw_hdmi_phy_init(struct dw_hdmi *hdmi)
674 {
675 	/* enable phy i2cm done irq */
676 	hdmi_write(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
677 		   HDMI_PHY_I2CM_INT_ADDR);
678 
679 	/* enable phy i2cm nack & arbitration error irq */
680 	hdmi_write(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
681 		   HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
682 		   HDMI_PHY_I2CM_CTLINT_ADDR);
683 
684 	/* enable cable hot plug irq */
685 	hdmi_write(hdmi, (u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
686 
687 	/* clear hotplug interrupts */
688 	hdmi_write(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
689 }
690 
691 int dw_hdmi_read_edid(struct dw_hdmi *hdmi, u8 *buf, int buf_size)
692 {
693 	u32 edid_size = HDMI_EDID_BLOCK_SIZE;
694 	int ret;
695 
696 	if (0) {
697 		edid_size = sizeof(pre_buf);
698 		memcpy(buf, pre_buf, edid_size);
699 	} else {
700 		ret = hdmi_read_edid(hdmi, 0, buf);
701 		if (ret) {
702 			debug("failed to read edid.\n");
703 			return -1;
704 		}
705 
706 		if (buf[0x7e] != 0) {
707 			hdmi_read_edid(hdmi, 1, buf + HDMI_EDID_BLOCK_SIZE);
708 			edid_size += HDMI_EDID_BLOCK_SIZE;
709 		}
710 	}
711 
712 	return edid_size;
713 }
714 
715 int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
716 {
717 	int ret;
718 
719 	debug("hdmi, mode info : clock %d hdis %d vdis %d\n",
720 	      edid->pixelclock.typ, edid->hactive.typ, edid->vactive.typ);
721 
722 	hdmi_av_composer(hdmi, edid);
723 
724 	ret = hdmi->phy_set(hdmi, edid->pixelclock.typ);
725 	if (ret)
726 		return ret;
727 
728 	hdmi_enable_video_path(hdmi);
729 
730 	hdmi_audio_fifo_reset(hdmi);
731 	hdmi_audio_set_format(hdmi);
732 	hdmi_audio_set_samplerate(hdmi, edid->pixelclock.typ);
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