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