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