1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2015 Google, Inc
4 * Copyright 2014 Rockchip Inc.
12 #include <media_bus_format.h>
14 #include <linux/delay.h>
15 #include <linux/errno.h>
24 static const struct tmds_n_cts n_cts_table[] = {
26 .tmds = 25175000, .n = 6144, .cts = 25175,
28 .tmds = 25200000, .n = 6144, .cts = 25200,
30 .tmds = 27000000, .n = 6144, .cts = 27000,
32 .tmds = 27027000, .n = 6144, .cts = 27027,
34 .tmds = 40000000, .n = 6144, .cts = 40000,
36 .tmds = 54000000, .n = 6144, .cts = 54000,
38 .tmds = 54054000, .n = 6144, .cts = 54054,
40 .tmds = 65000000, .n = 6144, .cts = 65000,
42 .tmds = 74176000, .n = 11648, .cts = 140625,
44 .tmds = 74250000, .n = 6144, .cts = 74250,
46 .tmds = 83500000, .n = 6144, .cts = 83500,
48 .tmds = 106500000, .n = 6144, .cts = 106500,
50 .tmds = 108000000, .n = 6144, .cts = 108000,
52 .tmds = 148352000, .n = 5824, .cts = 140625,
54 .tmds = 148500000, .n = 6144, .cts = 148500,
56 .tmds = 297000000, .n = 5120, .cts = 247500,
60 static const u16 csc_coeff_default[3][4] = {
61 { 0x2000, 0x0000, 0x0000, 0x0000 },
62 { 0x0000, 0x2000, 0x0000, 0x0000 },
63 { 0x0000, 0x0000, 0x2000, 0x0000 }
66 static const u16 csc_coeff_rgb_in_eitu601[3][4] = {
67 { 0x2591, 0x1322, 0x074b, 0x0000 },
68 { 0x6535, 0x2000, 0x7acc, 0x0200 },
69 { 0x6acd, 0x7534, 0x2000, 0x0200 }
72 static const u16 csc_coeff_rgb_out_eitu601[3][4] = {
73 { 0x2000, 0x6926, 0x74fd, 0x010e },
74 { 0x2000, 0x2cdd, 0x0000, 0x7e9a },
75 { 0x2000, 0x0000, 0x38b4, 0x7e3b }
78 static void dw_hdmi_write(struct dw_hdmi *hdmi, u8 val, int offset)
80 switch (hdmi->reg_io_width) {
82 writeb(val, (void *)(hdmi->ioaddr + offset));
85 writel(val, (void *)(hdmi->ioaddr + (offset << 2)));
88 debug("reg_io_width has unsupported width!\n");
93 static u8 dw_hdmi_read(struct dw_hdmi *hdmi, int offset)
95 switch (hdmi->reg_io_width) {
97 return readb((void *)(hdmi->ioaddr + offset));
99 return readl((void *)(hdmi->ioaddr + (offset << 2)));
101 debug("reg_io_width has unsupported width!\n");
108 static u8 (*hdmi_read)(struct dw_hdmi *hdmi, int offset) = dw_hdmi_read;
109 static void (*hdmi_write)(struct dw_hdmi *hdmi, u8 val, int offset) =
112 static void hdmi_mod(struct dw_hdmi *hdmi, unsigned reg, u8 mask, u8 data)
114 u8 val = hdmi_read(hdmi, reg) & ~mask;
117 hdmi_write(hdmi, val, reg);
120 static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi, u32 n, u32 cts)
125 /* first set ncts_atomic_write (if present) */
126 n3 = HDMI_AUD_N3_NCTS_ATOMIC_WRITE;
127 hdmi_write(hdmi, n3, HDMI_AUD_N3);
129 /* set cts_manual (if present) */
130 cts3 = HDMI_AUD_CTS3_CTS_MANUAL;
132 cts3 |= HDMI_AUD_CTS3_N_SHIFT_1 << HDMI_AUD_CTS3_N_SHIFT_OFFSET;
133 cts3 |= (cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK;
135 /* write cts values; cts3 must be written first */
136 hdmi_write(hdmi, cts3, HDMI_AUD_CTS3);
137 hdmi_write(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
138 hdmi_write(hdmi, cts & 0xff, HDMI_AUD_CTS1);
140 /* write n values; n1 must be written last */
141 n3 |= (n >> 16) & HDMI_AUD_N3_AUDN19_16_MASK;
142 hdmi_write(hdmi, n3, HDMI_AUD_N3);
143 hdmi_write(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
144 hdmi_write(hdmi, n & 0xff, HDMI_AUD_N3);
146 hdmi_write(hdmi, HDMI_AUD_INPUTCLKFS_128, HDMI_AUD_INPUTCLKFS);
149 static int hdmi_lookup_n_cts(u32 pixel_clk)
153 for (i = 0; i < ARRAY_SIZE(n_cts_table); i++)
154 if (pixel_clk <= n_cts_table[i].tmds)
157 if (i >= ARRAY_SIZE(n_cts_table))
163 static void hdmi_audio_set_samplerate(struct dw_hdmi *hdmi, u32 pixel_clk)
168 index = hdmi_lookup_n_cts(pixel_clk);
170 debug("audio not supported for pixel clk %d\n", pixel_clk);
174 clk_n = n_cts_table[index].n;
175 clk_cts = n_cts_table[index].cts;
176 hdmi_set_clock_regenerator(hdmi, clk_n, clk_cts);
180 * this submodule is responsible for the video data synchronization.
181 * for example, for rgb 4:4:4 input, the data map is defined as
182 * pin{47~40} <==> r[7:0]
183 * pin{31~24} <==> g[7:0]
184 * pin{15~8} <==> b[7:0]
186 static void hdmi_video_sample(struct dw_hdmi *hdmi)
191 switch (hdmi->hdmi_data.enc_in_bus_format) {
192 case MEDIA_BUS_FMT_RGB888_1X24:
195 case MEDIA_BUS_FMT_RGB101010_1X30:
198 case MEDIA_BUS_FMT_RGB121212_1X36:
201 case MEDIA_BUS_FMT_RGB161616_1X48:
204 case MEDIA_BUS_FMT_YUV8_1X24:
205 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
208 case MEDIA_BUS_FMT_YUV10_1X30:
209 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
212 case MEDIA_BUS_FMT_YUV12_1X36:
213 case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
216 case MEDIA_BUS_FMT_YUV16_1X48:
217 case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
220 case MEDIA_BUS_FMT_UYVY8_1X16:
223 case MEDIA_BUS_FMT_UYVY10_1X20:
226 case MEDIA_BUS_FMT_UYVY12_1X24:
234 val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
235 ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
236 HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
238 hdmi_write(hdmi, val, HDMI_TX_INVID0);
240 /* enable tx stuffing: when de is inactive, fix the output data to 0 */
241 val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
242 HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
243 HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
244 hdmi_write(hdmi, val, HDMI_TX_INSTUFFING);
245 hdmi_write(hdmi, 0x0, HDMI_TX_GYDATA0);
246 hdmi_write(hdmi, 0x0, HDMI_TX_GYDATA1);
247 hdmi_write(hdmi, 0x0, HDMI_TX_RCRDATA0);
248 hdmi_write(hdmi, 0x0, HDMI_TX_RCRDATA1);
249 hdmi_write(hdmi, 0x0, HDMI_TX_BCBDATA0);
250 hdmi_write(hdmi, 0x0, HDMI_TX_BCBDATA1);
253 static void hdmi_video_packetize(struct dw_hdmi *hdmi)
255 u32 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
256 u32 remap_size = HDMI_VP_REMAP_YCC422_16BIT;
260 /* set the packetizer registers */
261 val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
262 HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
263 ((0 << HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
264 HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
265 hdmi_write(hdmi, val, HDMI_VP_PR_CD);
267 hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PR_STUFFING_MASK,
268 HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE);
270 /* data from pixel repeater block */
271 vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
272 HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
274 hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_PR_EN_MASK |
275 HDMI_VP_CONF_BYPASS_SELECT_MASK, vp_conf);
277 hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_IDEFAULT_PHASE_MASK,
278 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET);
280 hdmi_write(hdmi, remap_size, HDMI_VP_REMAP);
282 vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
283 HDMI_VP_CONF_PP_EN_DISABLE |
284 HDMI_VP_CONF_YCC422_EN_DISABLE;
286 hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_BYPASS_EN_MASK |
287 HDMI_VP_CONF_PP_EN_ENMASK | HDMI_VP_CONF_YCC422_EN_MASK,
290 hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PP_STUFFING_MASK |
291 HDMI_VP_STUFF_YCC422_STUFFING_MASK,
292 HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
293 HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE);
295 hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
299 static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, uint bit)
301 hdmi_mod(hdmi, HDMI_PHY_TST0, HDMI_PHY_TST0_TSTCLR_MASK,
302 bit << HDMI_PHY_TST0_TSTCLR_OFFSET);
305 static int hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, u32 msec)
310 start = get_timer(0);
312 val = hdmi_read(hdmi, HDMI_IH_I2CMPHY_STAT0);
314 hdmi_write(hdmi, val, HDMI_IH_I2CMPHY_STAT0);
319 } while (get_timer(start) < msec);
324 static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, uint data, uint addr)
326 hdmi_write(hdmi, 0xff, HDMI_IH_I2CMPHY_STAT0);
327 hdmi_write(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
328 hdmi_write(hdmi, (u8)(data >> 8), HDMI_PHY_I2CM_DATAO_1_ADDR);
329 hdmi_write(hdmi, (u8)(data >> 0), HDMI_PHY_I2CM_DATAO_0_ADDR);
330 hdmi_write(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
331 HDMI_PHY_I2CM_OPERATION_ADDR);
333 hdmi_phy_wait_i2c_done(hdmi, 1000);
336 static void hdmi_phy_enable_power(struct dw_hdmi *hdmi, uint enable)
338 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_PDZ_MASK,
339 enable << HDMI_PHY_CONF0_PDZ_OFFSET);
342 static void hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, uint enable)
344 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_ENTMDS_MASK,
345 enable << HDMI_PHY_CONF0_ENTMDS_OFFSET);
348 static void hdmi_phy_enable_spare(struct dw_hdmi *hdmi, uint enable)
350 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SPARECTRL_MASK,
351 enable << HDMI_PHY_CONF0_SPARECTRL_OFFSET);
354 static void hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, uint enable)
356 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_GEN2_PDDQ_MASK,
357 enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET);
360 static void hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, uint enable)
362 hdmi_mod(hdmi, HDMI_PHY_CONF0,
363 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK,
364 enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET);
367 static void hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, uint enable)
369 hdmi_mod(hdmi, HDMI_PHY_CONF0,
370 HDMI_PHY_CONF0_SELDATAENPOL_MASK,
371 enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET);
374 static void hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi,
377 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SELDIPIF_MASK,
378 enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET);
381 static int hdmi_phy_configure(struct dw_hdmi *hdmi, u32 mpixelclock)
386 if (!hdmi->mpll_cfg || !hdmi->phy_cfg)
389 /* gen2 tx power off */
390 hdmi_phy_gen2_txpwron(hdmi, 0);
393 hdmi_phy_gen2_pddq(hdmi, 1);
396 hdmi_write(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
397 hdmi_write(hdmi, HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
398 hdmi_write(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
400 hdmi_phy_test_clear(hdmi, 1);
401 hdmi_write(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
402 HDMI_PHY_I2CM_SLAVE_ADDR);
403 hdmi_phy_test_clear(hdmi, 0);
405 /* pll/mpll cfg - always match on final entry */
406 for (i = 0; hdmi->mpll_cfg[i].mpixelclock != (~0ul); i++)
407 if (mpixelclock <= hdmi->mpll_cfg[i].mpixelclock)
410 hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].cpce, PHY_OPMODE_PLLCFG);
411 hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].gmp, PHY_PLLGMPCTRL);
412 hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].curr, PHY_PLLCURRCTRL);
414 hdmi_phy_i2c_write(hdmi, 0x0000, PHY_PLLPHBYCTRL);
415 hdmi_phy_i2c_write(hdmi, 0x0006, PHY_PLLCLKBISTPHASE);
417 for (i = 0; hdmi->phy_cfg[i].mpixelclock != (~0ul); i++)
418 if (mpixelclock <= hdmi->phy_cfg[i].mpixelclock)
422 * resistance term 133ohm cfg
426 hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].term, PHY_TXTERM);
427 hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].sym_ctr, PHY_CKSYMTXCTRL);
428 hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].vlev_ctr, PHY_VLEVCTRL);
430 /* remove clk term */
431 hdmi_phy_i2c_write(hdmi, 0x8000, PHY_CKCALCTRL);
433 hdmi_phy_enable_power(hdmi, 1);
435 /* toggle tmds enable */
436 hdmi_phy_enable_tmds(hdmi, 0);
437 hdmi_phy_enable_tmds(hdmi, 1);
439 /* gen2 tx power on */
440 hdmi_phy_gen2_txpwron(hdmi, 1);
441 hdmi_phy_gen2_pddq(hdmi, 0);
443 hdmi_phy_enable_spare(hdmi, 1);
445 /* wait for phy pll lock */
446 start = get_timer(0);
448 val = hdmi_read(hdmi, HDMI_PHY_STAT0);
449 if (!(val & HDMI_PHY_TX_PHY_LOCK))
453 } while (get_timer(start) < 5);
458 static void hdmi_av_composer(struct dw_hdmi *hdmi,
459 const struct display_timing *edid)
461 bool mdataenablepolarity = true;
466 hbl = edid->hback_porch.typ + edid->hfront_porch.typ +
468 vbl = edid->vback_porch.typ + edid->vfront_porch.typ +
471 /* set up hdmi_fc_invidconf */
472 inv_val = HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE;
474 inv_val |= (edid->flags & DISPLAY_FLAGS_VSYNC_HIGH ?
475 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
476 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
478 inv_val |= (edid->flags & DISPLAY_FLAGS_HSYNC_HIGH ?
479 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
480 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
482 inv_val |= (mdataenablepolarity ?
483 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
484 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
486 inv_val |= (edid->hdmi_monitor ?
487 HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
488 HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE);
490 inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
492 inv_val |= HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
494 hdmi_write(hdmi, inv_val, HDMI_FC_INVIDCONF);
496 /* set up horizontal active pixel width */
497 hdmi_write(hdmi, edid->hactive.typ >> 8, HDMI_FC_INHACTV1);
498 hdmi_write(hdmi, edid->hactive.typ, HDMI_FC_INHACTV0);
500 /* set up vertical active lines */
501 hdmi_write(hdmi, edid->vactive.typ >> 8, HDMI_FC_INVACTV1);
502 hdmi_write(hdmi, edid->vactive.typ, HDMI_FC_INVACTV0);
504 /* set up horizontal blanking pixel region width */
505 hdmi_write(hdmi, hbl >> 8, HDMI_FC_INHBLANK1);
506 hdmi_write(hdmi, hbl, HDMI_FC_INHBLANK0);
508 /* set up vertical blanking pixel region width */
509 hdmi_write(hdmi, vbl, HDMI_FC_INVBLANK);
511 /* set up hsync active edge delay width (in pixel clks) */
512 hdmi_write(hdmi, edid->hfront_porch.typ >> 8, HDMI_FC_HSYNCINDELAY1);
513 hdmi_write(hdmi, edid->hfront_porch.typ, HDMI_FC_HSYNCINDELAY0);
515 /* set up vsync active edge delay (in lines) */
516 hdmi_write(hdmi, edid->vfront_porch.typ, HDMI_FC_VSYNCINDELAY);
518 /* set up hsync active pulse width (in pixel clks) */
519 hdmi_write(hdmi, edid->hsync_len.typ >> 8, HDMI_FC_HSYNCINWIDTH1);
520 hdmi_write(hdmi, edid->hsync_len.typ, HDMI_FC_HSYNCINWIDTH0);
522 /* set up vsync active edge delay (in lines) */
523 hdmi_write(hdmi, edid->vsync_len.typ, HDMI_FC_VSYNCINWIDTH);
526 static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
528 switch (bus_format) {
529 case MEDIA_BUS_FMT_RGB888_1X24:
530 case MEDIA_BUS_FMT_RGB101010_1X30:
531 case MEDIA_BUS_FMT_RGB121212_1X36:
532 case MEDIA_BUS_FMT_RGB161616_1X48:
540 static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
542 switch (bus_format) {
543 case MEDIA_BUS_FMT_YUV8_1X24:
544 case MEDIA_BUS_FMT_YUV10_1X30:
545 case MEDIA_BUS_FMT_YUV12_1X36:
546 case MEDIA_BUS_FMT_YUV16_1X48:
554 static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
556 switch (bus_format) {
557 case MEDIA_BUS_FMT_UYVY8_1X16:
558 case MEDIA_BUS_FMT_UYVY10_1X20:
559 case MEDIA_BUS_FMT_UYVY12_1X24:
567 static int is_color_space_interpolation(struct dw_hdmi *hdmi)
569 if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format))
572 if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) ||
573 hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
579 static int is_color_space_decimation(struct dw_hdmi *hdmi)
581 if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
584 if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) ||
585 hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format))
591 static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
593 switch (bus_format) {
594 case MEDIA_BUS_FMT_RGB888_1X24:
595 case MEDIA_BUS_FMT_YUV8_1X24:
596 case MEDIA_BUS_FMT_UYVY8_1X16:
597 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
600 case MEDIA_BUS_FMT_RGB101010_1X30:
601 case MEDIA_BUS_FMT_YUV10_1X30:
602 case MEDIA_BUS_FMT_UYVY10_1X20:
603 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
606 case MEDIA_BUS_FMT_RGB121212_1X36:
607 case MEDIA_BUS_FMT_YUV12_1X36:
608 case MEDIA_BUS_FMT_UYVY12_1X24:
609 case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
612 case MEDIA_BUS_FMT_RGB161616_1X48:
613 case MEDIA_BUS_FMT_YUV16_1X48:
614 case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
622 static int is_color_space_conversion(struct dw_hdmi *hdmi)
624 return hdmi->hdmi_data.enc_in_bus_format !=
625 hdmi->hdmi_data.enc_out_bus_format;
628 static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
630 const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
634 if (is_color_space_conversion(hdmi)) {
635 if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
636 csc_coeff = &csc_coeff_rgb_out_eitu601;
637 } else if (hdmi_bus_fmt_is_rgb(
638 hdmi->hdmi_data.enc_in_bus_format)) {
639 csc_coeff = &csc_coeff_rgb_in_eitu601;
644 /* The CSC registers are sequential, alternating MSB then LSB */
645 for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) {
646 u16 coeff_a = (*csc_coeff)[0][i];
647 u16 coeff_b = (*csc_coeff)[1][i];
648 u16 coeff_c = (*csc_coeff)[2][i];
650 hdmi_write(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2);
651 hdmi_write(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2);
652 hdmi_write(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2);
653 hdmi_write(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
654 hdmi_write(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2);
655 hdmi_write(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
658 hdmi_mod(hdmi, HDMI_CSC_SCALE, HDMI_CSC_SCALE_CSCSCALE_MASK, csc_scale);
661 static void hdmi_video_csc(struct dw_hdmi *hdmi)
664 int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
667 /* YCC422 interpolation to 444 mode */
668 if (is_color_space_interpolation(hdmi))
669 interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1;
670 else if (is_color_space_decimation(hdmi))
671 decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
673 switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) {
675 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
678 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
681 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
684 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
691 /* Configure the CSC registers */
692 hdmi_write(hdmi, interpolation | decimation, HDMI_CSC_CFG);
694 hdmi_mod(hdmi, HDMI_CSC_SCALE, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
697 dw_hdmi_update_csc_coeffs(hdmi);
700 /* hdmi initialization step b.4 */
701 static void hdmi_enable_video_path(struct dw_hdmi *hdmi, bool audio)
705 /* control period minimum duration */
706 hdmi_write(hdmi, 12, HDMI_FC_CTRLDUR);
707 hdmi_write(hdmi, 32, HDMI_FC_EXCTRLDUR);
708 hdmi_write(hdmi, 1, HDMI_FC_EXCTRLSPAC);
710 /* set to fill tmds data channels */
711 hdmi_write(hdmi, 0x0b, HDMI_FC_CH0PREAM);
712 hdmi_write(hdmi, 0x16, HDMI_FC_CH1PREAM);
713 hdmi_write(hdmi, 0x21, HDMI_FC_CH2PREAM);
715 hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
718 /* enable pixel clock and tmds data path */
720 clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
721 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
723 clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
724 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
726 /* Enable csc path */
727 if (is_color_space_conversion(hdmi)) {
728 clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
729 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
732 /* Enable color space conversion if needed */
733 if (is_color_space_conversion(hdmi))
734 hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
737 hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
741 clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
742 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
746 /* workaround to clear the overflow condition */
747 static void hdmi_clear_overflow(struct dw_hdmi *hdmi)
751 /* tmds software reset */
752 hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
754 val = hdmi_read(hdmi, HDMI_FC_INVIDCONF);
756 for (count = 0; count < 4; count++)
757 hdmi_write(hdmi, val, HDMI_FC_INVIDCONF);
760 static void hdmi_audio_set_format(struct dw_hdmi *hdmi)
762 hdmi_write(hdmi, HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_IN_EN_0,
765 hdmi_write(hdmi, HDMI_AUD_CONF1_I2S_MODE_STANDARD_MODE |
766 HDMI_AUD_CONF1_I2S_WIDTH_16BIT, HDMI_AUD_CONF1);
768 hdmi_write(hdmi, 0x00, HDMI_AUD_CONF2);
771 static void hdmi_audio_fifo_reset(struct dw_hdmi *hdmi)
773 hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_II2SSWRST_REQ, HDMI_MC_SWRSTZ);
774 hdmi_write(hdmi, HDMI_AUD_CONF0_SW_AUDIO_FIFO_RST, HDMI_AUD_CONF0);
776 hdmi_write(hdmi, 0x00, HDMI_AUD_INT);
777 hdmi_write(hdmi, 0x00, HDMI_AUD_INT1);
780 static int hdmi_get_plug_in_status(struct dw_hdmi *hdmi)
782 uint val = hdmi_read(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD;
787 static int hdmi_ddc_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
792 start = get_timer(0);
794 val = hdmi_read(hdmi, HDMI_IH_I2CM_STAT0);
796 hdmi_write(hdmi, val, HDMI_IH_I2CM_STAT0);
801 } while (get_timer(start) < msec);
806 static void hdmi_ddc_reset(struct dw_hdmi *hdmi)
808 hdmi_mod(hdmi, HDMI_I2CM_SOFTRSTZ, HDMI_I2CM_SOFTRSTZ_MASK, 0);
811 static int hdmi_read_edid(struct dw_hdmi *hdmi, int block, u8 *buff)
813 int shift = (block % 2) * 0x80;
814 int edid_read_err = 0;
818 if (CONFIG_IS_ENABLED(DM_I2C) && hdmi->ddc_bus) {
819 struct udevice *chip;
821 edid_read_err = i2c_get_chip(hdmi->ddc_bus,
822 HDMI_I2CM_SLAVE_DDC_ADDR,
825 return edid_read_err;
827 return dm_i2c_read(chip, shift, buff, HDMI_EDID_BLOCK_SIZE);
830 /* set ddc i2c clk which devided from ddc_clk to 100khz */
831 hdmi_write(hdmi, hdmi->i2c_clk_high, HDMI_I2CM_SS_SCL_HCNT_0_ADDR);
832 hdmi_write(hdmi, hdmi->i2c_clk_low, HDMI_I2CM_SS_SCL_LCNT_0_ADDR);
833 hdmi_mod(hdmi, HDMI_I2CM_DIV, HDMI_I2CM_DIV_FAST_STD_MODE,
834 HDMI_I2CM_DIV_STD_MODE);
836 hdmi_write(hdmi, HDMI_I2CM_SLAVE_DDC_ADDR, HDMI_I2CM_SLAVE);
837 hdmi_write(hdmi, HDMI_I2CM_SEGADDR_DDC, HDMI_I2CM_SEGADDR);
838 hdmi_write(hdmi, block >> 1, HDMI_I2CM_SEGPTR);
843 for (n = 0; n < HDMI_EDID_BLOCK_SIZE; n++) {
844 hdmi_write(hdmi, shift + n, HDMI_I2CM_ADDRESS);
847 hdmi_write(hdmi, HDMI_I2CM_OP_RD8,
848 HDMI_I2CM_OPERATION);
850 hdmi_write(hdmi, HDMI_I2CM_OP_RD8_EXT,
851 HDMI_I2CM_OPERATION);
853 if (hdmi_ddc_wait_i2c_done(hdmi, 10)) {
854 hdmi_ddc_reset(hdmi);
859 buff[n] = hdmi_read(hdmi, HDMI_I2CM_DATAI);
866 return edid_read_err;
869 static const u8 pre_buf[] = {
870 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
871 0x04, 0x69, 0xfa, 0x23, 0xc8, 0x28, 0x01, 0x00,
872 0x10, 0x17, 0x01, 0x03, 0x80, 0x33, 0x1d, 0x78,
873 0x2a, 0xd9, 0x45, 0xa2, 0x55, 0x4d, 0xa0, 0x27,
874 0x12, 0x50, 0x54, 0xb7, 0xef, 0x00, 0x71, 0x4f,
875 0x81, 0x40, 0x81, 0x80, 0x95, 0x00, 0xb3, 0x00,
876 0xd1, 0xc0, 0x81, 0xc0, 0x81, 0x00, 0x02, 0x3a,
877 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
878 0x45, 0x00, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
879 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x34, 0x4c,
880 0x4d, 0x54, 0x46, 0x30, 0x37, 0x35, 0x39, 0x37,
881 0x36, 0x0a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
882 0x4b, 0x18, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20,
883 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
884 0x00, 0x41, 0x53, 0x55, 0x53, 0x20, 0x56, 0x53,
885 0x32, 0x33, 0x38, 0x0a, 0x20, 0x20, 0x01, 0xb0,
886 0x02, 0x03, 0x22, 0x71, 0x4f, 0x01, 0x02, 0x03,
887 0x11, 0x12, 0x13, 0x04, 0x14, 0x05, 0x0e, 0x0f,
888 0x1d, 0x1e, 0x1f, 0x10, 0x23, 0x09, 0x17, 0x07,
889 0x83, 0x01, 0x00, 0x00, 0x65, 0x03, 0x0c, 0x00,
890 0x10, 0x00, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0,
891 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xfd, 0x1e,
892 0x11, 0x00, 0x00, 0x18, 0x01, 0x1d, 0x00, 0x72,
893 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
894 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e, 0x01, 0x1d,
895 0x00, 0xbc, 0x52, 0xd0, 0x1e, 0x20, 0xb8, 0x28,
896 0x55, 0x40, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
897 0x8c, 0x0a, 0xd0, 0x90, 0x20, 0x40, 0x31, 0x20,
898 0x0c, 0x40, 0x55, 0x00, 0xfd, 0x1e, 0x11, 0x00,
899 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
900 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
901 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9,
904 int dw_hdmi_phy_cfg(struct dw_hdmi *hdmi, uint mpixelclock)
908 /* hdmi phy spec says to do the phy initialization sequence twice */
909 for (i = 0; i < 2; i++) {
910 hdmi_phy_sel_data_en_pol(hdmi, 1);
911 hdmi_phy_sel_interface_control(hdmi, 0);
912 hdmi_phy_enable_tmds(hdmi, 0);
913 hdmi_phy_enable_power(hdmi, 0);
915 ret = hdmi_phy_configure(hdmi, mpixelclock);
917 debug("hdmi phy config failure %d\n", ret);
925 int dw_hdmi_phy_wait_for_hpd(struct dw_hdmi *hdmi)
929 start = get_timer(0);
931 if (hdmi_get_plug_in_status(hdmi))
934 } while (get_timer(start) < 300);
939 int dw_hdmi_detect_hpd(struct dw_hdmi *hdmi)
943 ret = dw_hdmi_phy_wait_for_hpd(hdmi);
945 debug("hdmi can not get hpd signal\n");
949 if (hdmi->ops && hdmi->ops->read_hpd)
950 hdmi->ops->read_hpd(hdmi, true);
955 void dw_hdmi_phy_init(struct dw_hdmi *hdmi)
957 /* enable phy i2cm done irq */
958 hdmi_write(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
959 HDMI_PHY_I2CM_INT_ADDR);
961 /* enable phy i2cm nack & arbitration error irq */
962 hdmi_write(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
963 HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
964 HDMI_PHY_I2CM_CTLINT_ADDR);
966 /* enable cable hot plug irq */
967 hdmi_write(hdmi, (u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
969 /* clear hotplug interrupts */
970 hdmi_write(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
973 int dw_hdmi_read_edid(struct dw_hdmi *hdmi, u8 *buf, int buf_size)
975 u32 edid_size = HDMI_EDID_BLOCK_SIZE;
979 edid_size = sizeof(pre_buf);
980 memcpy(buf, pre_buf, edid_size);
982 ret = hdmi_read_edid(hdmi, 0, buf);
984 debug("failed to read edid.\n");
988 if (buf[0x7e] != 0) {
989 hdmi_read_edid(hdmi, 1, buf + HDMI_EDID_BLOCK_SIZE);
990 edid_size += HDMI_EDID_BLOCK_SIZE;
997 int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
1001 debug("%s, mode info : clock %d hdis %d vdis %d\n",
1002 edid->hdmi_monitor ? "hdmi" : "dvi",
1003 edid->pixelclock.typ, edid->hactive.typ, edid->vactive.typ);
1005 hdmi_av_composer(hdmi, edid);
1007 ret = hdmi->ops->phy_set(hdmi, edid->pixelclock.typ);
1011 hdmi_enable_video_path(hdmi, edid->hdmi_monitor);
1013 if (edid->hdmi_monitor) {
1014 hdmi_audio_fifo_reset(hdmi);
1015 hdmi_audio_set_format(hdmi);
1016 hdmi_audio_set_samplerate(hdmi, edid->pixelclock.typ);
1019 hdmi_video_packetize(hdmi);
1020 hdmi_video_csc(hdmi);
1021 hdmi_video_sample(hdmi);
1023 hdmi_clear_overflow(hdmi);
1028 static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
1029 .phy_set = dw_hdmi_phy_cfg,
1032 void dw_hdmi_init(struct dw_hdmi *hdmi)
1036 /* hook Synopsys PHYs ops */
1038 hdmi->ops = &dw_hdmi_synopsys_phy_ops;
1041 * boot up defaults are:
1042 * hdmi_ih_mute = 0x03 (disabled)
1043 * hdmi_ih_mute_* = 0x00 (enabled)
1045 * disable top level interrupt bits in hdmi block
1047 ih_mute = /*hdmi_read(hdmi, HDMI_IH_MUTE) |*/
1048 HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
1049 HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
1051 if (hdmi->write_reg)
1052 hdmi_write = hdmi->write_reg;
1055 hdmi_read = hdmi->read_reg;
1057 hdmi_write(hdmi, ih_mute, HDMI_IH_MUTE);
1059 /* enable i2c master done irq */
1060 hdmi_write(hdmi, ~0x04, HDMI_I2CM_INT);
1062 /* enable i2c client nack % arbitration error irq */
1063 hdmi_write(hdmi, ~0x44, HDMI_I2CM_CTLINT);
1065 if (hdmi->ops && hdmi->ops->setup_hpd)
1066 hdmi->ops->setup_hpd(hdmi);