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 <log.h>
11 #include <asm/io.h>
12 #include <i2c.h>
13 #include <media_bus_format.h>
14 #include <linux/delay.h>
15 #include "dw_hdmi.h"
16 
17 struct tmds_n_cts {
18 	u32 tmds;
19 	u32 cts;
20 	u32 n;
21 };
22 
23 static const struct tmds_n_cts n_cts_table[] = {
24 	{
25 		.tmds = 25175000, .n = 6144, .cts = 25175,
26 	}, {
27 		.tmds = 25200000, .n = 6144, .cts = 25200,
28 	}, {
29 		.tmds = 27000000, .n = 6144, .cts = 27000,
30 	}, {
31 		.tmds = 27027000, .n = 6144, .cts = 27027,
32 	}, {
33 		.tmds = 40000000, .n = 6144, .cts = 40000,
34 	}, {
35 		.tmds = 54000000, .n = 6144, .cts = 54000,
36 	}, {
37 		.tmds = 54054000, .n = 6144, .cts = 54054,
38 	}, {
39 		.tmds = 65000000, .n = 6144, .cts = 65000,
40 	}, {
41 		.tmds = 74176000, .n = 11648, .cts = 140625,
42 	}, {
43 		.tmds = 74250000, .n = 6144, .cts = 74250,
44 	}, {
45 		.tmds = 83500000, .n = 6144, .cts = 83500,
46 	}, {
47 		.tmds = 106500000, .n = 6144, .cts = 106500,
48 	}, {
49 		.tmds = 108000000, .n = 6144, .cts = 108000,
50 	}, {
51 		.tmds = 148352000, .n = 5824, .cts = 140625,
52 	}, {
53 		.tmds = 148500000, .n = 6144, .cts = 148500,
54 	}, {
55 		.tmds = 297000000, .n = 5120, .cts = 247500,
56 	}
57 };
58 
59 static const u16 csc_coeff_default[3][4] = {
60 	{ 0x2000, 0x0000, 0x0000, 0x0000 },
61 	{ 0x0000, 0x2000, 0x0000, 0x0000 },
62 	{ 0x0000, 0x0000, 0x2000, 0x0000 }
63 };
64 
65 static const u16 csc_coeff_rgb_in_eitu601[3][4] = {
66 	{ 0x2591, 0x1322, 0x074b, 0x0000 },
67 	{ 0x6535, 0x2000, 0x7acc, 0x0200 },
68 	{ 0x6acd, 0x7534, 0x2000, 0x0200 }
69 };
70 
71 static const u16 csc_coeff_rgb_out_eitu601[3][4] = {
72 	{ 0x2000, 0x6926, 0x74fd, 0x010e },
73 	{ 0x2000, 0x2cdd, 0x0000, 0x7e9a },
74 	{ 0x2000, 0x0000, 0x38b4, 0x7e3b }
75 };
76 
dw_hdmi_write(struct dw_hdmi * hdmi,u8 val,int offset)77 static void dw_hdmi_write(struct dw_hdmi *hdmi, u8 val, int offset)
78 {
79 	switch (hdmi->reg_io_width) {
80 	case 1:
81 		writeb(val, hdmi->ioaddr + offset);
82 		break;
83 	case 4:
84 		writel(val, hdmi->ioaddr + (offset << 2));
85 		break;
86 	default:
87 		debug("reg_io_width has unsupported width!\n");
88 		break;
89 	}
90 }
91 
dw_hdmi_read(struct dw_hdmi * hdmi,int offset)92 static u8 dw_hdmi_read(struct dw_hdmi *hdmi, int offset)
93 {
94 	switch (hdmi->reg_io_width) {
95 	case 1:
96 		return readb(hdmi->ioaddr + offset);
97 	case 4:
98 		return readl(hdmi->ioaddr + (offset << 2));
99 	default:
100 		debug("reg_io_width has unsupported width!\n");
101 		break;
102 	}
103 
104 	return 0;
105 }
106 
107 static u8 (*hdmi_read)(struct dw_hdmi *hdmi, int offset) = dw_hdmi_read;
108 static void (*hdmi_write)(struct dw_hdmi *hdmi, u8 val, int offset) =
109 								 dw_hdmi_write;
110 
hdmi_mod(struct dw_hdmi * hdmi,unsigned reg,u8 mask,u8 data)111 static void hdmi_mod(struct dw_hdmi *hdmi, unsigned reg, u8 mask, u8 data)
112 {
113 	u8 val = hdmi_read(hdmi, reg) & ~mask;
114 
115 	val |= data & mask;
116 	hdmi_write(hdmi, val, reg);
117 }
118 
hdmi_set_clock_regenerator(struct dw_hdmi * hdmi,u32 n,u32 cts)119 static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi, u32 n, u32 cts)
120 {
121 	uint cts3;
122 	uint n3;
123 
124 	/* first set ncts_atomic_write (if present) */
125 	n3 = HDMI_AUD_N3_NCTS_ATOMIC_WRITE;
126 	hdmi_write(hdmi, n3, HDMI_AUD_N3);
127 
128 	/* set cts_manual (if present) */
129 	cts3 = HDMI_AUD_CTS3_CTS_MANUAL;
130 
131 	cts3 |= HDMI_AUD_CTS3_N_SHIFT_1 << HDMI_AUD_CTS3_N_SHIFT_OFFSET;
132 	cts3 |= (cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK;
133 
134 	/* write cts values; cts3 must be written first */
135 	hdmi_write(hdmi, cts3, HDMI_AUD_CTS3);
136 	hdmi_write(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
137 	hdmi_write(hdmi, cts & 0xff, HDMI_AUD_CTS1);
138 
139 	/* write n values; n1 must be written last */
140 	n3 |= (n >> 16) & HDMI_AUD_N3_AUDN19_16_MASK;
141 	hdmi_write(hdmi, n3, HDMI_AUD_N3);
142 	hdmi_write(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
143 	hdmi_write(hdmi, n & 0xff, HDMI_AUD_N3);
144 
145 	hdmi_write(hdmi, HDMI_AUD_INPUTCLKFS_128, HDMI_AUD_INPUTCLKFS);
146 }
147 
hdmi_lookup_n_cts(u32 pixel_clk)148 static int hdmi_lookup_n_cts(u32 pixel_clk)
149 {
150 	int i;
151 
152 	for (i = 0; i < ARRAY_SIZE(n_cts_table); i++)
153 		if (pixel_clk <= n_cts_table[i].tmds)
154 			break;
155 
156 	if (i >= ARRAY_SIZE(n_cts_table))
157 		return -1;
158 
159 	return i;
160 }
161 
hdmi_audio_set_samplerate(struct dw_hdmi * hdmi,u32 pixel_clk)162 static void hdmi_audio_set_samplerate(struct dw_hdmi *hdmi, u32 pixel_clk)
163 {
164 	u32 clk_n, clk_cts;
165 	int index;
166 
167 	index = hdmi_lookup_n_cts(pixel_clk);
168 	if (index == -1) {
169 		debug("audio not supported for pixel clk %d\n", pixel_clk);
170 		return;
171 	}
172 
173 	clk_n = n_cts_table[index].n;
174 	clk_cts = n_cts_table[index].cts;
175 	hdmi_set_clock_regenerator(hdmi, clk_n, clk_cts);
176 }
177 
178 /*
179  * this submodule is responsible for the video data synchronization.
180  * for example, for rgb 4:4:4 input, the data map is defined as
181  *			pin{47~40} <==> r[7:0]
182  *			pin{31~24} <==> g[7:0]
183  *			pin{15~8}  <==> b[7:0]
184  */
hdmi_video_sample(struct dw_hdmi * hdmi)185 static void hdmi_video_sample(struct dw_hdmi *hdmi)
186 {
187 	u32 color_format;
188 	uint val;
189 
190 	switch (hdmi->hdmi_data.enc_in_bus_format) {
191 	case MEDIA_BUS_FMT_RGB888_1X24:
192 		color_format = 0x01;
193 		break;
194 	case MEDIA_BUS_FMT_RGB101010_1X30:
195 		color_format = 0x03;
196 		break;
197 	case MEDIA_BUS_FMT_RGB121212_1X36:
198 		color_format = 0x05;
199 		break;
200 	case MEDIA_BUS_FMT_RGB161616_1X48:
201 		color_format = 0x07;
202 		break;
203 	case MEDIA_BUS_FMT_YUV8_1X24:
204 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
205 		color_format = 0x09;
206 		break;
207 	case MEDIA_BUS_FMT_YUV10_1X30:
208 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
209 		color_format = 0x0B;
210 		break;
211 	case MEDIA_BUS_FMT_YUV12_1X36:
212 	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
213 		color_format = 0x0D;
214 		break;
215 	case MEDIA_BUS_FMT_YUV16_1X48:
216 	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
217 		color_format = 0x0F;
218 		break;
219 	case MEDIA_BUS_FMT_UYVY8_1X16:
220 		color_format = 0x16;
221 		break;
222 	case MEDIA_BUS_FMT_UYVY10_1X20:
223 		color_format = 0x14;
224 		break;
225 	case MEDIA_BUS_FMT_UYVY12_1X24:
226 		color_format = 0x12;
227 		break;
228 	default:
229 		color_format = 0x01;
230 		break;
231 	}
232 
233 	val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
234 	      ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
235 	      HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
236 
237 	hdmi_write(hdmi, val, HDMI_TX_INVID0);
238 
239 	/* enable tx stuffing: when de is inactive, fix the output data to 0 */
240 	val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
241 	      HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
242 	      HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
243 	hdmi_write(hdmi, val, HDMI_TX_INSTUFFING);
244 	hdmi_write(hdmi, 0x0, HDMI_TX_GYDATA0);
245 	hdmi_write(hdmi, 0x0, HDMI_TX_GYDATA1);
246 	hdmi_write(hdmi, 0x0, HDMI_TX_RCRDATA0);
247 	hdmi_write(hdmi, 0x0, HDMI_TX_RCRDATA1);
248 	hdmi_write(hdmi, 0x0, HDMI_TX_BCBDATA0);
249 	hdmi_write(hdmi, 0x0, HDMI_TX_BCBDATA1);
250 }
251 
hdmi_video_packetize(struct dw_hdmi * hdmi)252 static void hdmi_video_packetize(struct dw_hdmi *hdmi)
253 {
254 	u32 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
255 	u32 remap_size = HDMI_VP_REMAP_YCC422_16BIT;
256 	u32 color_depth = 0;
257 	uint val, vp_conf;
258 
259 	/* set the packetizer registers */
260 	val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
261 		HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
262 		((0 << HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
263 		HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
264 	hdmi_write(hdmi, val, HDMI_VP_PR_CD);
265 
266 	hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PR_STUFFING_MASK,
267 		 HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE);
268 
269 	/* data from pixel repeater block */
270 	vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
271 		  HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
272 
273 	hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_PR_EN_MASK |
274 		 HDMI_VP_CONF_BYPASS_SELECT_MASK, vp_conf);
275 
276 	hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_IDEFAULT_PHASE_MASK,
277 		 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET);
278 
279 	hdmi_write(hdmi, remap_size, HDMI_VP_REMAP);
280 
281 	vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
282 		  HDMI_VP_CONF_PP_EN_DISABLE |
283 		  HDMI_VP_CONF_YCC422_EN_DISABLE;
284 
285 	hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_BYPASS_EN_MASK |
286 		 HDMI_VP_CONF_PP_EN_ENMASK | HDMI_VP_CONF_YCC422_EN_MASK,
287 		 vp_conf);
288 
289 	hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PP_STUFFING_MASK |
290 		 HDMI_VP_STUFF_YCC422_STUFFING_MASK,
291 		 HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
292 		 HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE);
293 
294 	hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
295 		 output_select);
296 }
297 
hdmi_phy_test_clear(struct dw_hdmi * hdmi,uint bit)298 static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, uint bit)
299 {
300 	hdmi_mod(hdmi, HDMI_PHY_TST0, HDMI_PHY_TST0_TSTCLR_MASK,
301 		 bit << HDMI_PHY_TST0_TSTCLR_OFFSET);
302 }
303 
hdmi_phy_wait_i2c_done(struct dw_hdmi * hdmi,u32 msec)304 static int hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, u32 msec)
305 {
306 	ulong start;
307 	u32 val;
308 
309 	start = get_timer(0);
310 	do {
311 		val = hdmi_read(hdmi, HDMI_IH_I2CMPHY_STAT0);
312 		if (val & 0x3) {
313 			hdmi_write(hdmi, val, HDMI_IH_I2CMPHY_STAT0);
314 			return 0;
315 		}
316 
317 		udelay(100);
318 	} while (get_timer(start) < msec);
319 
320 	return 1;
321 }
322 
hdmi_phy_i2c_write(struct dw_hdmi * hdmi,uint data,uint addr)323 static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, uint data, uint addr)
324 {
325 	hdmi_write(hdmi, 0xff, HDMI_IH_I2CMPHY_STAT0);
326 	hdmi_write(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
327 	hdmi_write(hdmi, (u8)(data >> 8), HDMI_PHY_I2CM_DATAO_1_ADDR);
328 	hdmi_write(hdmi, (u8)(data >> 0), HDMI_PHY_I2CM_DATAO_0_ADDR);
329 	hdmi_write(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
330 		   HDMI_PHY_I2CM_OPERATION_ADDR);
331 
332 	hdmi_phy_wait_i2c_done(hdmi, 1000);
333 }
334 
hdmi_phy_enable_power(struct dw_hdmi * hdmi,uint enable)335 static void hdmi_phy_enable_power(struct dw_hdmi *hdmi, uint enable)
336 {
337 	hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_PDZ_MASK,
338 		 enable << HDMI_PHY_CONF0_PDZ_OFFSET);
339 }
340 
hdmi_phy_enable_tmds(struct dw_hdmi * hdmi,uint enable)341 static void hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, uint enable)
342 {
343 	hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_ENTMDS_MASK,
344 		 enable << HDMI_PHY_CONF0_ENTMDS_OFFSET);
345 }
346 
hdmi_phy_enable_spare(struct dw_hdmi * hdmi,uint enable)347 static void hdmi_phy_enable_spare(struct dw_hdmi *hdmi, uint enable)
348 {
349 	hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SPARECTRL_MASK,
350 		 enable << HDMI_PHY_CONF0_SPARECTRL_OFFSET);
351 }
352 
hdmi_phy_gen2_pddq(struct dw_hdmi * hdmi,uint enable)353 static void hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, uint enable)
354 {
355 	hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_GEN2_PDDQ_MASK,
356 		 enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET);
357 }
358 
hdmi_phy_gen2_txpwron(struct dw_hdmi * hdmi,uint enable)359 static void hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, uint enable)
360 {
361 	hdmi_mod(hdmi, HDMI_PHY_CONF0,
362 		 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK,
363 		 enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET);
364 }
365 
hdmi_phy_sel_data_en_pol(struct dw_hdmi * hdmi,uint enable)366 static void hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, uint enable)
367 {
368 	hdmi_mod(hdmi, HDMI_PHY_CONF0,
369 		 HDMI_PHY_CONF0_SELDATAENPOL_MASK,
370 		 enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET);
371 }
372 
hdmi_phy_sel_interface_control(struct dw_hdmi * hdmi,uint enable)373 static void hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi,
374 					   uint enable)
375 {
376 	hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SELDIPIF_MASK,
377 		 enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET);
378 }
379 
hdmi_phy_configure(struct dw_hdmi * hdmi,u32 mpixelclock)380 static int hdmi_phy_configure(struct dw_hdmi *hdmi, u32 mpixelclock)
381 {
382 	ulong start;
383 	uint i, val;
384 
385 	if (!hdmi->mpll_cfg || !hdmi->phy_cfg)
386 		return -1;
387 
388 	/* gen2 tx power off */
389 	hdmi_phy_gen2_txpwron(hdmi, 0);
390 
391 	/* gen2 pddq */
392 	hdmi_phy_gen2_pddq(hdmi, 1);
393 
394 	/* phy reset */
395 	hdmi_write(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
396 	hdmi_write(hdmi, HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
397 	hdmi_write(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
398 
399 	hdmi_phy_test_clear(hdmi, 1);
400 	hdmi_write(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
401 		   HDMI_PHY_I2CM_SLAVE_ADDR);
402 	hdmi_phy_test_clear(hdmi, 0);
403 
404 	/* pll/mpll cfg - always match on final entry */
405 	for (i = 0; hdmi->mpll_cfg[i].mpixelclock != (~0ul); i++)
406 		if (mpixelclock <= hdmi->mpll_cfg[i].mpixelclock)
407 			break;
408 
409 	hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].cpce, PHY_OPMODE_PLLCFG);
410 	hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].gmp, PHY_PLLGMPCTRL);
411 	hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].curr, PHY_PLLCURRCTRL);
412 
413 	hdmi_phy_i2c_write(hdmi, 0x0000, PHY_PLLPHBYCTRL);
414 	hdmi_phy_i2c_write(hdmi, 0x0006, PHY_PLLCLKBISTPHASE);
415 
416 	for (i = 0; hdmi->phy_cfg[i].mpixelclock != (~0ul); i++)
417 		if (mpixelclock <= hdmi->phy_cfg[i].mpixelclock)
418 			break;
419 
420 	/*
421 	 * resistance term 133ohm cfg
422 	 * preemp cgf 0.00
423 	 * tx/ck lvl 10
424 	 */
425 	hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].term, PHY_TXTERM);
426 	hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].sym_ctr, PHY_CKSYMTXCTRL);
427 	hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].vlev_ctr, PHY_VLEVCTRL);
428 
429 	/* remove clk term */
430 	hdmi_phy_i2c_write(hdmi, 0x8000, PHY_CKCALCTRL);
431 
432 	hdmi_phy_enable_power(hdmi, 1);
433 
434 	/* toggle tmds enable */
435 	hdmi_phy_enable_tmds(hdmi, 0);
436 	hdmi_phy_enable_tmds(hdmi, 1);
437 
438 	/* gen2 tx power on */
439 	hdmi_phy_gen2_txpwron(hdmi, 1);
440 	hdmi_phy_gen2_pddq(hdmi, 0);
441 
442 	hdmi_phy_enable_spare(hdmi, 1);
443 
444 	/* wait for phy pll lock */
445 	start = get_timer(0);
446 	do {
447 		val = hdmi_read(hdmi, HDMI_PHY_STAT0);
448 		if (!(val & HDMI_PHY_TX_PHY_LOCK))
449 			return 0;
450 
451 		udelay(100);
452 	} while (get_timer(start) < 5);
453 
454 	return -1;
455 }
456 
hdmi_av_composer(struct dw_hdmi * hdmi,const struct display_timing * edid)457 static void hdmi_av_composer(struct dw_hdmi *hdmi,
458 			     const struct display_timing *edid)
459 {
460 	bool mdataenablepolarity = true;
461 	uint inv_val;
462 	uint hbl;
463 	uint vbl;
464 
465 	hbl = edid->hback_porch.typ + edid->hfront_porch.typ +
466 			edid->hsync_len.typ;
467 	vbl = edid->vback_porch.typ + edid->vfront_porch.typ +
468 			edid->vsync_len.typ;
469 
470 	/* set up hdmi_fc_invidconf */
471 	inv_val = HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE;
472 
473 	inv_val |= (edid->flags & DISPLAY_FLAGS_VSYNC_HIGH ?
474 		   HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
475 		   HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
476 
477 	inv_val |= (edid->flags & DISPLAY_FLAGS_HSYNC_HIGH ?
478 		   HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
479 		   HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
480 
481 	inv_val |= (mdataenablepolarity ?
482 		   HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
483 		   HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
484 
485 	inv_val |= (edid->hdmi_monitor ?
486 		   HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
487 		   HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE);
488 
489 	inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
490 
491 	inv_val |= HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
492 
493 	hdmi_write(hdmi, inv_val, HDMI_FC_INVIDCONF);
494 
495 	/* set up horizontal active pixel width */
496 	hdmi_write(hdmi, edid->hactive.typ >> 8, HDMI_FC_INHACTV1);
497 	hdmi_write(hdmi, edid->hactive.typ, HDMI_FC_INHACTV0);
498 
499 	/* set up vertical active lines */
500 	hdmi_write(hdmi, edid->vactive.typ >> 8, HDMI_FC_INVACTV1);
501 	hdmi_write(hdmi, edid->vactive.typ, HDMI_FC_INVACTV0);
502 
503 	/* set up horizontal blanking pixel region width */
504 	hdmi_write(hdmi, hbl >> 8, HDMI_FC_INHBLANK1);
505 	hdmi_write(hdmi, hbl, HDMI_FC_INHBLANK0);
506 
507 	/* set up vertical blanking pixel region width */
508 	hdmi_write(hdmi, vbl, HDMI_FC_INVBLANK);
509 
510 	/* set up hsync active edge delay width (in pixel clks) */
511 	hdmi_write(hdmi, edid->hfront_porch.typ >> 8, HDMI_FC_HSYNCINDELAY1);
512 	hdmi_write(hdmi, edid->hfront_porch.typ, HDMI_FC_HSYNCINDELAY0);
513 
514 	/* set up vsync active edge delay (in lines) */
515 	hdmi_write(hdmi, edid->vfront_porch.typ, HDMI_FC_VSYNCINDELAY);
516 
517 	/* set up hsync active pulse width (in pixel clks) */
518 	hdmi_write(hdmi, edid->hsync_len.typ >> 8, HDMI_FC_HSYNCINWIDTH1);
519 	hdmi_write(hdmi, edid->hsync_len.typ, HDMI_FC_HSYNCINWIDTH0);
520 
521 	/* set up vsync active edge delay (in lines) */
522 	hdmi_write(hdmi, edid->vsync_len.typ, HDMI_FC_VSYNCINWIDTH);
523 }
524 
hdmi_bus_fmt_is_rgb(unsigned int bus_format)525 static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
526 {
527 	switch (bus_format) {
528 	case MEDIA_BUS_FMT_RGB888_1X24:
529 	case MEDIA_BUS_FMT_RGB101010_1X30:
530 	case MEDIA_BUS_FMT_RGB121212_1X36:
531 	case MEDIA_BUS_FMT_RGB161616_1X48:
532 		return true;
533 
534 	default:
535 		return false;
536 	}
537 }
538 
hdmi_bus_fmt_is_yuv444(unsigned int bus_format)539 static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
540 {
541 	switch (bus_format) {
542 	case MEDIA_BUS_FMT_YUV8_1X24:
543 	case MEDIA_BUS_FMT_YUV10_1X30:
544 	case MEDIA_BUS_FMT_YUV12_1X36:
545 	case MEDIA_BUS_FMT_YUV16_1X48:
546 		return true;
547 
548 	default:
549 		return false;
550 	}
551 }
552 
hdmi_bus_fmt_is_yuv422(unsigned int bus_format)553 static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
554 {
555 	switch (bus_format) {
556 	case MEDIA_BUS_FMT_UYVY8_1X16:
557 	case MEDIA_BUS_FMT_UYVY10_1X20:
558 	case MEDIA_BUS_FMT_UYVY12_1X24:
559 		return true;
560 
561 	default:
562 		return false;
563 	}
564 }
565 
is_color_space_interpolation(struct dw_hdmi * hdmi)566 static int is_color_space_interpolation(struct dw_hdmi *hdmi)
567 {
568 	if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format))
569 		return 0;
570 
571 	if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) ||
572 	    hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
573 		return 1;
574 
575 	return 0;
576 }
577 
is_color_space_decimation(struct dw_hdmi * hdmi)578 static int is_color_space_decimation(struct dw_hdmi *hdmi)
579 {
580 	if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
581 		return 0;
582 
583 	if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) ||
584 	    hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format))
585 		return 1;
586 
587 	return 0;
588 }
589 
hdmi_bus_fmt_color_depth(unsigned int bus_format)590 static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
591 {
592 	switch (bus_format) {
593 	case MEDIA_BUS_FMT_RGB888_1X24:
594 	case MEDIA_BUS_FMT_YUV8_1X24:
595 	case MEDIA_BUS_FMT_UYVY8_1X16:
596 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
597 		return 8;
598 
599 	case MEDIA_BUS_FMT_RGB101010_1X30:
600 	case MEDIA_BUS_FMT_YUV10_1X30:
601 	case MEDIA_BUS_FMT_UYVY10_1X20:
602 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
603 		return 10;
604 
605 	case MEDIA_BUS_FMT_RGB121212_1X36:
606 	case MEDIA_BUS_FMT_YUV12_1X36:
607 	case MEDIA_BUS_FMT_UYVY12_1X24:
608 	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
609 		return 12;
610 
611 	case MEDIA_BUS_FMT_RGB161616_1X48:
612 	case MEDIA_BUS_FMT_YUV16_1X48:
613 	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
614 		return 16;
615 
616 	default:
617 		return 0;
618 	}
619 }
620 
is_color_space_conversion(struct dw_hdmi * hdmi)621 static int is_color_space_conversion(struct dw_hdmi *hdmi)
622 {
623 	return hdmi->hdmi_data.enc_in_bus_format !=
624 	       hdmi->hdmi_data.enc_out_bus_format;
625 }
626 
dw_hdmi_update_csc_coeffs(struct dw_hdmi * hdmi)627 static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
628 {
629 	const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
630 	unsigned int i;
631 	u32 csc_scale = 1;
632 
633 	if (is_color_space_conversion(hdmi)) {
634 		if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
635 			csc_coeff = &csc_coeff_rgb_out_eitu601;
636 		} else if (hdmi_bus_fmt_is_rgb(
637 					hdmi->hdmi_data.enc_in_bus_format)) {
638 			csc_coeff = &csc_coeff_rgb_in_eitu601;
639 			csc_scale = 0;
640 		}
641 	}
642 
643 	/* The CSC registers are sequential, alternating MSB then LSB */
644 	for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) {
645 		u16 coeff_a = (*csc_coeff)[0][i];
646 		u16 coeff_b = (*csc_coeff)[1][i];
647 		u16 coeff_c = (*csc_coeff)[2][i];
648 
649 		hdmi_write(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2);
650 		hdmi_write(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2);
651 		hdmi_write(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2);
652 		hdmi_write(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
653 		hdmi_write(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2);
654 		hdmi_write(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
655 	}
656 
657 	hdmi_mod(hdmi, HDMI_CSC_SCALE, HDMI_CSC_SCALE_CSCSCALE_MASK, csc_scale);
658 }
659 
hdmi_video_csc(struct dw_hdmi * hdmi)660 static void hdmi_video_csc(struct dw_hdmi *hdmi)
661 {
662 	int color_depth = 0;
663 	int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
664 	int decimation = 0;
665 
666 	/* YCC422 interpolation to 444 mode */
667 	if (is_color_space_interpolation(hdmi))
668 		interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1;
669 	else if (is_color_space_decimation(hdmi))
670 		decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
671 
672 	switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) {
673 	case 8:
674 		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
675 		break;
676 	case 10:
677 		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
678 		break;
679 	case 12:
680 		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
681 		break;
682 	case 16:
683 		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
684 		break;
685 
686 	default:
687 		return;
688 	}
689 
690 	/* Configure the CSC registers */
691 	hdmi_write(hdmi, interpolation | decimation, HDMI_CSC_CFG);
692 
693 	hdmi_mod(hdmi, HDMI_CSC_SCALE, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
694 		 color_depth);
695 
696 	dw_hdmi_update_csc_coeffs(hdmi);
697 }
698 
699 /* hdmi initialization step b.4 */
hdmi_enable_video_path(struct dw_hdmi * hdmi,bool audio)700 static void hdmi_enable_video_path(struct dw_hdmi *hdmi, bool audio)
701 {
702 	uint clkdis;
703 
704 	/* control period minimum duration */
705 	hdmi_write(hdmi, 12, HDMI_FC_CTRLDUR);
706 	hdmi_write(hdmi, 32, HDMI_FC_EXCTRLDUR);
707 	hdmi_write(hdmi, 1, HDMI_FC_EXCTRLSPAC);
708 
709 	/* set to fill tmds data channels */
710 	hdmi_write(hdmi, 0x0b, HDMI_FC_CH0PREAM);
711 	hdmi_write(hdmi, 0x16, HDMI_FC_CH1PREAM);
712 	hdmi_write(hdmi, 0x21, HDMI_FC_CH2PREAM);
713 
714 	hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
715 		   HDMI_MC_FLOWCTRL);
716 
717 	/* enable pixel clock and tmds data path */
718 	clkdis = 0x7f;
719 	clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
720 	hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
721 
722 	clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
723 	hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
724 
725 	/* Enable csc path */
726 	if (is_color_space_conversion(hdmi)) {
727 		clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
728 		hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
729 	}
730 
731 	/* Enable color space conversion if needed */
732 	if (is_color_space_conversion(hdmi))
733 		hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
734 			   HDMI_MC_FLOWCTRL);
735 	else
736 		hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
737 			   HDMI_MC_FLOWCTRL);
738 
739 	if (audio) {
740 		clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
741 		hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
742 	}
743 }
744 
745 /* workaround to clear the overflow condition */
hdmi_clear_overflow(struct dw_hdmi * hdmi)746 static void hdmi_clear_overflow(struct dw_hdmi *hdmi)
747 {
748 	uint val, count;
749 
750 	/* tmds software reset */
751 	hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
752 
753 	val = hdmi_read(hdmi, HDMI_FC_INVIDCONF);
754 
755 	for (count = 0; count < 4; count++)
756 		hdmi_write(hdmi, val, HDMI_FC_INVIDCONF);
757 }
758 
hdmi_audio_set_format(struct dw_hdmi * hdmi)759 static void hdmi_audio_set_format(struct dw_hdmi *hdmi)
760 {
761 	hdmi_write(hdmi, HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_IN_EN_0,
762 		   HDMI_AUD_CONF0);
763 
764 
765 	hdmi_write(hdmi, HDMI_AUD_CONF1_I2S_MODE_STANDARD_MODE |
766 		   HDMI_AUD_CONF1_I2S_WIDTH_16BIT, HDMI_AUD_CONF1);
767 
768 	hdmi_write(hdmi, 0x00, HDMI_AUD_CONF2);
769 }
770 
hdmi_audio_fifo_reset(struct dw_hdmi * hdmi)771 static void hdmi_audio_fifo_reset(struct dw_hdmi *hdmi)
772 {
773 	hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_II2SSWRST_REQ, HDMI_MC_SWRSTZ);
774 	hdmi_write(hdmi, HDMI_AUD_CONF0_SW_AUDIO_FIFO_RST, HDMI_AUD_CONF0);
775 
776 	hdmi_write(hdmi, 0x00, HDMI_AUD_INT);
777 	hdmi_write(hdmi, 0x00, HDMI_AUD_INT1);
778 }
779 
hdmi_get_plug_in_status(struct dw_hdmi * hdmi)780 static int hdmi_get_plug_in_status(struct dw_hdmi *hdmi)
781 {
782 	uint val = hdmi_read(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD;
783 
784 	return !!val;
785 }
786 
hdmi_ddc_wait_i2c_done(struct dw_hdmi * hdmi,int msec)787 static int hdmi_ddc_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
788 {
789 	u32 val;
790 	ulong start;
791 
792 	start = get_timer(0);
793 	do {
794 		val = hdmi_read(hdmi, HDMI_IH_I2CM_STAT0);
795 		if (val & 0x2) {
796 			hdmi_write(hdmi, val, HDMI_IH_I2CM_STAT0);
797 			return 0;
798 		}
799 
800 		udelay(100);
801 	} while (get_timer(start) < msec);
802 
803 	return 1;
804 }
805 
hdmi_ddc_reset(struct dw_hdmi * hdmi)806 static void hdmi_ddc_reset(struct dw_hdmi *hdmi)
807 {
808 	hdmi_mod(hdmi, HDMI_I2CM_SOFTRSTZ, HDMI_I2CM_SOFTRSTZ_MASK, 0);
809 }
810 
hdmi_read_edid(struct dw_hdmi * hdmi,int block,u8 * buff)811 static int hdmi_read_edid(struct dw_hdmi *hdmi, int block, u8 *buff)
812 {
813 	int shift = (block % 2) * 0x80;
814 	int edid_read_err = 0;
815 	u32 trytime = 5;
816 	u32 n;
817 
818 	if (CONFIG_IS_ENABLED(DM_I2C) && hdmi->ddc_bus) {
819 		struct udevice *chip;
820 
821 		edid_read_err = i2c_get_chip(hdmi->ddc_bus,
822 					     HDMI_I2CM_SLAVE_DDC_ADDR,
823 					     1, &chip);
824 		if (edid_read_err)
825 			return edid_read_err;
826 
827 		return dm_i2c_read(chip, shift, buff, HDMI_EDID_BLOCK_SIZE);
828 	}
829 
830 	/* set ddc i2c clk which devided from ddc_clk to 100khz */
831 	hdmi_write(hdmi, hdmi->i2c_clk_high, HDMI_I2CM_SS_SCL_HCNT_0_ADDR);
832 	hdmi_write(hdmi, hdmi->i2c_clk_low, HDMI_I2CM_SS_SCL_LCNT_0_ADDR);
833 	hdmi_mod(hdmi, HDMI_I2CM_DIV, HDMI_I2CM_DIV_FAST_STD_MODE,
834 		 HDMI_I2CM_DIV_STD_MODE);
835 
836 	hdmi_write(hdmi, HDMI_I2CM_SLAVE_DDC_ADDR, HDMI_I2CM_SLAVE);
837 	hdmi_write(hdmi, HDMI_I2CM_SEGADDR_DDC, HDMI_I2CM_SEGADDR);
838 	hdmi_write(hdmi, block >> 1, HDMI_I2CM_SEGPTR);
839 
840 	while (trytime--) {
841 		edid_read_err = 0;
842 
843 		for (n = 0; n < HDMI_EDID_BLOCK_SIZE; n++) {
844 			hdmi_write(hdmi, shift + n, HDMI_I2CM_ADDRESS);
845 
846 			if (block == 0)
847 				hdmi_write(hdmi, HDMI_I2CM_OP_RD8,
848 					   HDMI_I2CM_OPERATION);
849 			else
850 				hdmi_write(hdmi, HDMI_I2CM_OP_RD8_EXT,
851 					   HDMI_I2CM_OPERATION);
852 
853 			if (hdmi_ddc_wait_i2c_done(hdmi, 10)) {
854 				hdmi_ddc_reset(hdmi);
855 				edid_read_err = 1;
856 				break;
857 			}
858 
859 			buff[n] = hdmi_read(hdmi, HDMI_I2CM_DATAI);
860 		}
861 
862 		if (!edid_read_err)
863 			break;
864 	}
865 
866 	return edid_read_err;
867 }
868 
869 static const u8 pre_buf[] = {
870 	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
871 	0x04, 0x69, 0xfa, 0x23, 0xc8, 0x28, 0x01, 0x00,
872 	0x10, 0x17, 0x01, 0x03, 0x80, 0x33, 0x1d, 0x78,
873 	0x2a, 0xd9, 0x45, 0xa2, 0x55, 0x4d, 0xa0, 0x27,
874 	0x12, 0x50, 0x54, 0xb7, 0xef, 0x00, 0x71, 0x4f,
875 	0x81, 0x40, 0x81, 0x80, 0x95, 0x00, 0xb3, 0x00,
876 	0xd1, 0xc0, 0x81, 0xc0, 0x81, 0x00, 0x02, 0x3a,
877 	0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
878 	0x45, 0x00, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
879 	0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x34, 0x4c,
880 	0x4d, 0x54, 0x46, 0x30, 0x37, 0x35, 0x39, 0x37,
881 	0x36, 0x0a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
882 	0x4b, 0x18, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20,
883 	0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
884 	0x00, 0x41, 0x53, 0x55, 0x53, 0x20, 0x56, 0x53,
885 	0x32, 0x33, 0x38, 0x0a, 0x20, 0x20, 0x01, 0xb0,
886 	0x02, 0x03, 0x22, 0x71, 0x4f, 0x01, 0x02, 0x03,
887 	0x11, 0x12, 0x13, 0x04, 0x14, 0x05, 0x0e, 0x0f,
888 	0x1d, 0x1e, 0x1f, 0x10, 0x23, 0x09, 0x17, 0x07,
889 	0x83, 0x01, 0x00, 0x00, 0x65, 0x03, 0x0c, 0x00,
890 	0x10, 0x00, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0,
891 	0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xfd, 0x1e,
892 	0x11, 0x00, 0x00, 0x18, 0x01, 0x1d, 0x00, 0x72,
893 	0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
894 	0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e, 0x01, 0x1d,
895 	0x00, 0xbc, 0x52, 0xd0, 0x1e, 0x20, 0xb8, 0x28,
896 	0x55, 0x40, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
897 	0x8c, 0x0a, 0xd0, 0x90, 0x20, 0x40, 0x31, 0x20,
898 	0x0c, 0x40, 0x55, 0x00, 0xfd, 0x1e, 0x11, 0x00,
899 	0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
900 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
901 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9,
902 };
903 
dw_hdmi_phy_cfg(struct dw_hdmi * hdmi,uint mpixelclock)904 int dw_hdmi_phy_cfg(struct dw_hdmi *hdmi, uint mpixelclock)
905 {
906 	int i, ret;
907 
908 	/* hdmi phy spec says to do the phy initialization sequence twice */
909 	for (i = 0; i < 2; i++) {
910 		hdmi_phy_sel_data_en_pol(hdmi, 1);
911 		hdmi_phy_sel_interface_control(hdmi, 0);
912 		hdmi_phy_enable_tmds(hdmi, 0);
913 		hdmi_phy_enable_power(hdmi, 0);
914 
915 		ret = hdmi_phy_configure(hdmi, mpixelclock);
916 		if (ret) {
917 			debug("hdmi phy config failure %d\n", ret);
918 			return ret;
919 		}
920 	}
921 
922 	return 0;
923 }
924 
dw_hdmi_phy_wait_for_hpd(struct dw_hdmi * hdmi)925 int dw_hdmi_phy_wait_for_hpd(struct dw_hdmi *hdmi)
926 {
927 	ulong start;
928 
929 	start = get_timer(0);
930 	do {
931 		if (hdmi_get_plug_in_status(hdmi))
932 			return 0;
933 		udelay(100);
934 	} while (get_timer(start) < 300);
935 
936 	return -1;
937 }
938 
dw_hdmi_phy_init(struct dw_hdmi * hdmi)939 void dw_hdmi_phy_init(struct dw_hdmi *hdmi)
940 {
941 	/* enable phy i2cm done irq */
942 	hdmi_write(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
943 		   HDMI_PHY_I2CM_INT_ADDR);
944 
945 	/* enable phy i2cm nack & arbitration error irq */
946 	hdmi_write(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
947 		   HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
948 		   HDMI_PHY_I2CM_CTLINT_ADDR);
949 
950 	/* enable cable hot plug irq */
951 	hdmi_write(hdmi, (u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
952 
953 	/* clear hotplug interrupts */
954 	hdmi_write(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
955 }
956 
dw_hdmi_read_edid(struct dw_hdmi * hdmi,u8 * buf,int buf_size)957 int dw_hdmi_read_edid(struct dw_hdmi *hdmi, u8 *buf, int buf_size)
958 {
959 	u32 edid_size = HDMI_EDID_BLOCK_SIZE;
960 	int ret;
961 
962 	if (0) {
963 		edid_size = sizeof(pre_buf);
964 		memcpy(buf, pre_buf, edid_size);
965 	} else {
966 		ret = hdmi_read_edid(hdmi, 0, buf);
967 		if (ret) {
968 			debug("failed to read edid.\n");
969 			return -1;
970 		}
971 
972 		if (buf[0x7e] != 0) {
973 			hdmi_read_edid(hdmi, 1, buf + HDMI_EDID_BLOCK_SIZE);
974 			edid_size += HDMI_EDID_BLOCK_SIZE;
975 		}
976 	}
977 
978 	return edid_size;
979 }
980 
dw_hdmi_enable(struct dw_hdmi * hdmi,const struct display_timing * edid)981 int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
982 {
983 	int ret;
984 
985 	debug("%s, mode info : clock %d hdis %d vdis %d\n",
986 	      edid->hdmi_monitor ? "hdmi" : "dvi",
987 	      edid->pixelclock.typ, edid->hactive.typ, edid->vactive.typ);
988 
989 	hdmi_av_composer(hdmi, edid);
990 
991 	ret = hdmi->phy_set(hdmi, edid->pixelclock.typ);
992 	if (ret)
993 		return ret;
994 
995 	hdmi_enable_video_path(hdmi, edid->hdmi_monitor);
996 
997 	if (edid->hdmi_monitor) {
998 		hdmi_audio_fifo_reset(hdmi);
999 		hdmi_audio_set_format(hdmi);
1000 		hdmi_audio_set_samplerate(hdmi, edid->pixelclock.typ);
1001 	}
1002 
1003 	hdmi_video_packetize(hdmi);
1004 	hdmi_video_csc(hdmi);
1005 	hdmi_video_sample(hdmi);
1006 
1007 	hdmi_clear_overflow(hdmi);
1008 
1009 	return 0;
1010 }
1011 
dw_hdmi_init(struct dw_hdmi * hdmi)1012 void dw_hdmi_init(struct dw_hdmi *hdmi)
1013 {
1014 	uint ih_mute;
1015 
1016 	/*
1017 	 * boot up defaults are:
1018 	 * hdmi_ih_mute   = 0x03 (disabled)
1019 	 * hdmi_ih_mute_* = 0x00 (enabled)
1020 	 *
1021 	 * disable top level interrupt bits in hdmi block
1022 	 */
1023 	ih_mute = /*hdmi_read(hdmi, HDMI_IH_MUTE) |*/
1024 		  HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
1025 		  HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
1026 
1027 	if (hdmi->write_reg)
1028 		hdmi_write = hdmi->write_reg;
1029 
1030 	if (hdmi->read_reg)
1031 		hdmi_read = hdmi->read_reg;
1032 
1033 	hdmi_write(hdmi, ih_mute, HDMI_IH_MUTE);
1034 
1035 	/* enable i2c master done irq */
1036 	hdmi_write(hdmi, ~0x04, HDMI_I2CM_INT);
1037 
1038 	/* enable i2c client nack % arbitration error irq */
1039 	hdmi_write(hdmi, ~0x44, HDMI_I2CM_CTLINT);
1040 }
1041