Merge branch 'master' of git://git.denx.de/u-boot-socfpga
[platform/kernel/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 <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
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
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
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
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
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
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  */
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 */
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 */
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
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
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
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
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
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
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
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
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
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
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
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
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 }