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