]> git.sur5r.net Git - u-boot/blob - drivers/video/dw_hdmi.c
dm: core: Update of_read_fmap_entry() for livetree
[u-boot] / drivers / video / dw_hdmi.c
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 }