1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2015 Google, Inc
4 * Copyright 2014 Rockchip Inc.
5 * Copyright 2017 Jernej Skrabec <jernej.skrabec@siol.net>
13 #include <media_bus_format.h>
14 #include <linux/delay.h>
23 static const struct tmds_n_cts n_cts_table[] = {
25 .tmds = 25175000, .n = 6144, .cts = 25175,
27 .tmds = 25200000, .n = 6144, .cts = 25200,
29 .tmds = 27000000, .n = 6144, .cts = 27000,
31 .tmds = 27027000, .n = 6144, .cts = 27027,
33 .tmds = 40000000, .n = 6144, .cts = 40000,
35 .tmds = 54000000, .n = 6144, .cts = 54000,
37 .tmds = 54054000, .n = 6144, .cts = 54054,
39 .tmds = 65000000, .n = 6144, .cts = 65000,
41 .tmds = 74176000, .n = 11648, .cts = 140625,
43 .tmds = 74250000, .n = 6144, .cts = 74250,
45 .tmds = 83500000, .n = 6144, .cts = 83500,
47 .tmds = 106500000, .n = 6144, .cts = 106500,
49 .tmds = 108000000, .n = 6144, .cts = 108000,
51 .tmds = 148352000, .n = 5824, .cts = 140625,
53 .tmds = 148500000, .n = 6144, .cts = 148500,
55 .tmds = 297000000, .n = 5120, .cts = 247500,
59 static const u16 csc_coeff_default[3][4] = {
60 { 0x2000, 0x0000, 0x0000, 0x0000 },
61 { 0x0000, 0x2000, 0x0000, 0x0000 },
62 { 0x0000, 0x0000, 0x2000, 0x0000 }
65 static const u16 csc_coeff_rgb_in_eitu601[3][4] = {
66 { 0x2591, 0x1322, 0x074b, 0x0000 },
67 { 0x6535, 0x2000, 0x7acc, 0x0200 },
68 { 0x6acd, 0x7534, 0x2000, 0x0200 }
71 static const u16 csc_coeff_rgb_out_eitu601[3][4] = {
72 { 0x2000, 0x6926, 0x74fd, 0x010e },
73 { 0x2000, 0x2cdd, 0x0000, 0x7e9a },
74 { 0x2000, 0x0000, 0x38b4, 0x7e3b }
77 static void dw_hdmi_write(struct dw_hdmi *hdmi, u8 val, int offset)
79 switch (hdmi->reg_io_width) {
81 writeb(val, hdmi->ioaddr + offset);
84 writel(val, hdmi->ioaddr + (offset << 2));
87 debug("reg_io_width has unsupported width!\n");
92 static u8 dw_hdmi_read(struct dw_hdmi *hdmi, int offset)
94 switch (hdmi->reg_io_width) {
96 return readb(hdmi->ioaddr + offset);
98 return readl(hdmi->ioaddr + (offset << 2));
100 debug("reg_io_width has unsupported width!\n");
107 static u8 (*hdmi_read)(struct dw_hdmi *hdmi, int offset) = dw_hdmi_read;
108 static void (*hdmi_write)(struct dw_hdmi *hdmi, u8 val, int offset) =
111 static void hdmi_mod(struct dw_hdmi *hdmi, unsigned reg, u8 mask, u8 data)
113 u8 val = hdmi_read(hdmi, reg) & ~mask;
116 hdmi_write(hdmi, val, reg);
119 static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi, u32 n, u32 cts)
124 /* first set ncts_atomic_write (if present) */
125 n3 = HDMI_AUD_N3_NCTS_ATOMIC_WRITE;
126 hdmi_write(hdmi, n3, HDMI_AUD_N3);
128 /* set cts_manual (if present) */
129 cts3 = HDMI_AUD_CTS3_CTS_MANUAL;
131 cts3 |= HDMI_AUD_CTS3_N_SHIFT_1 << HDMI_AUD_CTS3_N_SHIFT_OFFSET;
132 cts3 |= (cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK;
134 /* write cts values; cts3 must be written first */
135 hdmi_write(hdmi, cts3, HDMI_AUD_CTS3);
136 hdmi_write(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
137 hdmi_write(hdmi, cts & 0xff, HDMI_AUD_CTS1);
139 /* write n values; n1 must be written last */
140 n3 |= (n >> 16) & HDMI_AUD_N3_AUDN19_16_MASK;
141 hdmi_write(hdmi, n3, HDMI_AUD_N3);
142 hdmi_write(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
143 hdmi_write(hdmi, n & 0xff, HDMI_AUD_N3);
145 hdmi_write(hdmi, HDMI_AUD_INPUTCLKFS_128, HDMI_AUD_INPUTCLKFS);
148 static int hdmi_lookup_n_cts(u32 pixel_clk)
152 for (i = 0; i < ARRAY_SIZE(n_cts_table); i++)
153 if (pixel_clk <= n_cts_table[i].tmds)
156 if (i >= ARRAY_SIZE(n_cts_table))
162 static void hdmi_audio_set_samplerate(struct dw_hdmi *hdmi, u32 pixel_clk)
167 index = hdmi_lookup_n_cts(pixel_clk);
169 debug("audio not supported for pixel clk %d\n", pixel_clk);
173 clk_n = n_cts_table[index].n;
174 clk_cts = n_cts_table[index].cts;
175 hdmi_set_clock_regenerator(hdmi, clk_n, clk_cts);
179 * this submodule is responsible for the video data synchronization.
180 * for example, for rgb 4:4:4 input, the data map is defined as
181 * pin{47~40} <==> r[7:0]
182 * pin{31~24} <==> g[7:0]
183 * pin{15~8} <==> b[7:0]
185 static void hdmi_video_sample(struct dw_hdmi *hdmi)
190 switch (hdmi->hdmi_data.enc_in_bus_format) {
191 case MEDIA_BUS_FMT_RGB888_1X24:
194 case MEDIA_BUS_FMT_RGB101010_1X30:
197 case MEDIA_BUS_FMT_RGB121212_1X36:
200 case MEDIA_BUS_FMT_RGB161616_1X48:
203 case MEDIA_BUS_FMT_YUV8_1X24:
204 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
207 case MEDIA_BUS_FMT_YUV10_1X30:
208 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
211 case MEDIA_BUS_FMT_YUV12_1X36:
212 case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
215 case MEDIA_BUS_FMT_YUV16_1X48:
216 case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
219 case MEDIA_BUS_FMT_UYVY8_1X16:
222 case MEDIA_BUS_FMT_UYVY10_1X20:
225 case MEDIA_BUS_FMT_UYVY12_1X24:
233 val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
234 ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
235 HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
237 hdmi_write(hdmi, val, HDMI_TX_INVID0);
239 /* enable tx stuffing: when de is inactive, fix the output data to 0 */
240 val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
241 HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
242 HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
243 hdmi_write(hdmi, val, HDMI_TX_INSTUFFING);
244 hdmi_write(hdmi, 0x0, HDMI_TX_GYDATA0);
245 hdmi_write(hdmi, 0x0, HDMI_TX_GYDATA1);
246 hdmi_write(hdmi, 0x0, HDMI_TX_RCRDATA0);
247 hdmi_write(hdmi, 0x0, HDMI_TX_RCRDATA1);
248 hdmi_write(hdmi, 0x0, HDMI_TX_BCBDATA0);
249 hdmi_write(hdmi, 0x0, HDMI_TX_BCBDATA1);
252 static void hdmi_video_packetize(struct dw_hdmi *hdmi)
254 u32 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
255 u32 remap_size = HDMI_VP_REMAP_YCC422_16BIT;
259 /* set the packetizer registers */
260 val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
261 HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
262 ((0 << HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
263 HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
264 hdmi_write(hdmi, val, HDMI_VP_PR_CD);
266 hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PR_STUFFING_MASK,
267 HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE);
269 /* data from pixel repeater block */
270 vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
271 HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
273 hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_PR_EN_MASK |
274 HDMI_VP_CONF_BYPASS_SELECT_MASK, vp_conf);
276 hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_IDEFAULT_PHASE_MASK,
277 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET);
279 hdmi_write(hdmi, remap_size, HDMI_VP_REMAP);
281 vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
282 HDMI_VP_CONF_PP_EN_DISABLE |
283 HDMI_VP_CONF_YCC422_EN_DISABLE;
285 hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_BYPASS_EN_MASK |
286 HDMI_VP_CONF_PP_EN_ENMASK | HDMI_VP_CONF_YCC422_EN_MASK,
289 hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PP_STUFFING_MASK |
290 HDMI_VP_STUFF_YCC422_STUFFING_MASK,
291 HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
292 HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE);
294 hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
298 static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, uint bit)
300 hdmi_mod(hdmi, HDMI_PHY_TST0, HDMI_PHY_TST0_TSTCLR_MASK,
301 bit << HDMI_PHY_TST0_TSTCLR_OFFSET);
304 static int hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, u32 msec)
309 start = get_timer(0);
311 val = hdmi_read(hdmi, HDMI_IH_I2CMPHY_STAT0);
313 hdmi_write(hdmi, val, HDMI_IH_I2CMPHY_STAT0);
318 } while (get_timer(start) < msec);
323 static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, uint data, uint addr)
325 hdmi_write(hdmi, 0xff, HDMI_IH_I2CMPHY_STAT0);
326 hdmi_write(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
327 hdmi_write(hdmi, (u8)(data >> 8), HDMI_PHY_I2CM_DATAO_1_ADDR);
328 hdmi_write(hdmi, (u8)(data >> 0), HDMI_PHY_I2CM_DATAO_0_ADDR);
329 hdmi_write(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
330 HDMI_PHY_I2CM_OPERATION_ADDR);
332 hdmi_phy_wait_i2c_done(hdmi, 1000);
335 static void hdmi_phy_enable_power(struct dw_hdmi *hdmi, uint enable)
337 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_PDZ_MASK,
338 enable << HDMI_PHY_CONF0_PDZ_OFFSET);
341 static void hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, uint enable)
343 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_ENTMDS_MASK,
344 enable << HDMI_PHY_CONF0_ENTMDS_OFFSET);
347 static void hdmi_phy_enable_spare(struct dw_hdmi *hdmi, uint enable)
349 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SPARECTRL_MASK,
350 enable << HDMI_PHY_CONF0_SPARECTRL_OFFSET);
353 static void hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, uint enable)
355 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_GEN2_PDDQ_MASK,
356 enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET);
359 static void hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, uint enable)
361 hdmi_mod(hdmi, HDMI_PHY_CONF0,
362 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK,
363 enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET);
366 static void hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, uint enable)
368 hdmi_mod(hdmi, HDMI_PHY_CONF0,
369 HDMI_PHY_CONF0_SELDATAENPOL_MASK,
370 enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET);
373 static void hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi,
376 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SELDIPIF_MASK,
377 enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET);
380 static int hdmi_phy_configure(struct dw_hdmi *hdmi, u32 mpixelclock)
385 if (!hdmi->mpll_cfg || !hdmi->phy_cfg)
388 /* gen2 tx power off */
389 hdmi_phy_gen2_txpwron(hdmi, 0);
392 hdmi_phy_gen2_pddq(hdmi, 1);
395 hdmi_write(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
396 hdmi_write(hdmi, HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
397 hdmi_write(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
399 hdmi_phy_test_clear(hdmi, 1);
400 hdmi_write(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
401 HDMI_PHY_I2CM_SLAVE_ADDR);
402 hdmi_phy_test_clear(hdmi, 0);
404 /* pll/mpll cfg - always match on final entry */
405 for (i = 0; hdmi->mpll_cfg[i].mpixelclock != (~0ul); i++)
406 if (mpixelclock <= hdmi->mpll_cfg[i].mpixelclock)
409 hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].cpce, PHY_OPMODE_PLLCFG);
410 hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].gmp, PHY_PLLGMPCTRL);
411 hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].curr, PHY_PLLCURRCTRL);
413 hdmi_phy_i2c_write(hdmi, 0x0000, PHY_PLLPHBYCTRL);
414 hdmi_phy_i2c_write(hdmi, 0x0006, PHY_PLLCLKBISTPHASE);
416 for (i = 0; hdmi->phy_cfg[i].mpixelclock != (~0ul); i++)
417 if (mpixelclock <= hdmi->phy_cfg[i].mpixelclock)
421 * resistance term 133ohm cfg
425 hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].term, PHY_TXTERM);
426 hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].sym_ctr, PHY_CKSYMTXCTRL);
427 hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].vlev_ctr, PHY_VLEVCTRL);
429 /* remove clk term */
430 hdmi_phy_i2c_write(hdmi, 0x8000, PHY_CKCALCTRL);
432 hdmi_phy_enable_power(hdmi, 1);
434 /* toggle tmds enable */
435 hdmi_phy_enable_tmds(hdmi, 0);
436 hdmi_phy_enable_tmds(hdmi, 1);
438 /* gen2 tx power on */
439 hdmi_phy_gen2_txpwron(hdmi, 1);
440 hdmi_phy_gen2_pddq(hdmi, 0);
442 hdmi_phy_enable_spare(hdmi, 1);
444 /* wait for phy pll lock */
445 start = get_timer(0);
447 val = hdmi_read(hdmi, HDMI_PHY_STAT0);
448 if (!(val & HDMI_PHY_TX_PHY_LOCK))
452 } while (get_timer(start) < 5);
457 static void hdmi_av_composer(struct dw_hdmi *hdmi,
458 const struct display_timing *edid)
460 bool mdataenablepolarity = true;
465 hbl = edid->hback_porch.typ + edid->hfront_porch.typ +
467 vbl = edid->vback_porch.typ + edid->vfront_porch.typ +
470 /* set up hdmi_fc_invidconf */
471 inv_val = HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE;
473 inv_val |= (edid->flags & DISPLAY_FLAGS_VSYNC_HIGH ?
474 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
475 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
477 inv_val |= (edid->flags & DISPLAY_FLAGS_HSYNC_HIGH ?
478 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
479 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
481 inv_val |= (mdataenablepolarity ?
482 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
483 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
485 inv_val |= (edid->hdmi_monitor ?
486 HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
487 HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE);
489 inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
491 inv_val |= HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
493 hdmi_write(hdmi, inv_val, HDMI_FC_INVIDCONF);
495 /* set up horizontal active pixel width */
496 hdmi_write(hdmi, edid->hactive.typ >> 8, HDMI_FC_INHACTV1);
497 hdmi_write(hdmi, edid->hactive.typ, HDMI_FC_INHACTV0);
499 /* set up vertical active lines */
500 hdmi_write(hdmi, edid->vactive.typ >> 8, HDMI_FC_INVACTV1);
501 hdmi_write(hdmi, edid->vactive.typ, HDMI_FC_INVACTV0);
503 /* set up horizontal blanking pixel region width */
504 hdmi_write(hdmi, hbl >> 8, HDMI_FC_INHBLANK1);
505 hdmi_write(hdmi, hbl, HDMI_FC_INHBLANK0);
507 /* set up vertical blanking pixel region width */
508 hdmi_write(hdmi, vbl, HDMI_FC_INVBLANK);
510 /* set up hsync active edge delay width (in pixel clks) */
511 hdmi_write(hdmi, edid->hfront_porch.typ >> 8, HDMI_FC_HSYNCINDELAY1);
512 hdmi_write(hdmi, edid->hfront_porch.typ, HDMI_FC_HSYNCINDELAY0);
514 /* set up vsync active edge delay (in lines) */
515 hdmi_write(hdmi, edid->vfront_porch.typ, HDMI_FC_VSYNCINDELAY);
517 /* set up hsync active pulse width (in pixel clks) */
518 hdmi_write(hdmi, edid->hsync_len.typ >> 8, HDMI_FC_HSYNCINWIDTH1);
519 hdmi_write(hdmi, edid->hsync_len.typ, HDMI_FC_HSYNCINWIDTH0);
521 /* set up vsync active edge delay (in lines) */
522 hdmi_write(hdmi, edid->vsync_len.typ, HDMI_FC_VSYNCINWIDTH);
525 static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
527 switch (bus_format) {
528 case MEDIA_BUS_FMT_RGB888_1X24:
529 case MEDIA_BUS_FMT_RGB101010_1X30:
530 case MEDIA_BUS_FMT_RGB121212_1X36:
531 case MEDIA_BUS_FMT_RGB161616_1X48:
539 static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
541 switch (bus_format) {
542 case MEDIA_BUS_FMT_YUV8_1X24:
543 case MEDIA_BUS_FMT_YUV10_1X30:
544 case MEDIA_BUS_FMT_YUV12_1X36:
545 case MEDIA_BUS_FMT_YUV16_1X48:
553 static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
555 switch (bus_format) {
556 case MEDIA_BUS_FMT_UYVY8_1X16:
557 case MEDIA_BUS_FMT_UYVY10_1X20:
558 case MEDIA_BUS_FMT_UYVY12_1X24:
566 static int is_color_space_interpolation(struct dw_hdmi *hdmi)
568 if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format))
571 if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) ||
572 hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
578 static int is_color_space_decimation(struct dw_hdmi *hdmi)
580 if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
583 if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) ||
584 hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format))
590 static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
592 switch (bus_format) {
593 case MEDIA_BUS_FMT_RGB888_1X24:
594 case MEDIA_BUS_FMT_YUV8_1X24:
595 case MEDIA_BUS_FMT_UYVY8_1X16:
596 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
599 case MEDIA_BUS_FMT_RGB101010_1X30:
600 case MEDIA_BUS_FMT_YUV10_1X30:
601 case MEDIA_BUS_FMT_UYVY10_1X20:
602 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
605 case MEDIA_BUS_FMT_RGB121212_1X36:
606 case MEDIA_BUS_FMT_YUV12_1X36:
607 case MEDIA_BUS_FMT_UYVY12_1X24:
608 case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
611 case MEDIA_BUS_FMT_RGB161616_1X48:
612 case MEDIA_BUS_FMT_YUV16_1X48:
613 case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
621 static int is_color_space_conversion(struct dw_hdmi *hdmi)
623 return hdmi->hdmi_data.enc_in_bus_format !=
624 hdmi->hdmi_data.enc_out_bus_format;
627 static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
629 const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
633 if (is_color_space_conversion(hdmi)) {
634 if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
635 csc_coeff = &csc_coeff_rgb_out_eitu601;
636 } else if (hdmi_bus_fmt_is_rgb(
637 hdmi->hdmi_data.enc_in_bus_format)) {
638 csc_coeff = &csc_coeff_rgb_in_eitu601;
643 /* The CSC registers are sequential, alternating MSB then LSB */
644 for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) {
645 u16 coeff_a = (*csc_coeff)[0][i];
646 u16 coeff_b = (*csc_coeff)[1][i];
647 u16 coeff_c = (*csc_coeff)[2][i];
649 hdmi_write(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2);
650 hdmi_write(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2);
651 hdmi_write(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2);
652 hdmi_write(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
653 hdmi_write(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2);
654 hdmi_write(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
657 hdmi_mod(hdmi, HDMI_CSC_SCALE, HDMI_CSC_SCALE_CSCSCALE_MASK, csc_scale);
660 static void hdmi_video_csc(struct dw_hdmi *hdmi)
663 int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
666 /* YCC422 interpolation to 444 mode */
667 if (is_color_space_interpolation(hdmi))
668 interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1;
669 else if (is_color_space_decimation(hdmi))
670 decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
672 switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) {
674 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
677 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
680 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
683 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
690 /* Configure the CSC registers */
691 hdmi_write(hdmi, interpolation | decimation, HDMI_CSC_CFG);
693 hdmi_mod(hdmi, HDMI_CSC_SCALE, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
696 dw_hdmi_update_csc_coeffs(hdmi);
699 /* hdmi initialization step b.4 */
700 static void hdmi_enable_video_path(struct dw_hdmi *hdmi, bool audio)
704 /* control period minimum duration */
705 hdmi_write(hdmi, 12, HDMI_FC_CTRLDUR);
706 hdmi_write(hdmi, 32, HDMI_FC_EXCTRLDUR);
707 hdmi_write(hdmi, 1, HDMI_FC_EXCTRLSPAC);
709 /* set to fill tmds data channels */
710 hdmi_write(hdmi, 0x0b, HDMI_FC_CH0PREAM);
711 hdmi_write(hdmi, 0x16, HDMI_FC_CH1PREAM);
712 hdmi_write(hdmi, 0x21, HDMI_FC_CH2PREAM);
714 hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
717 /* enable pixel clock and tmds data path */
719 clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
720 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
722 clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
723 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
725 /* Enable csc path */
726 if (is_color_space_conversion(hdmi)) {
727 clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
728 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
731 /* Enable color space conversion if needed */
732 if (is_color_space_conversion(hdmi))
733 hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
736 hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
740 clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
741 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
745 /* workaround to clear the overflow condition */
746 static void hdmi_clear_overflow(struct dw_hdmi *hdmi)
750 /* tmds software reset */
751 hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
753 val = hdmi_read(hdmi, HDMI_FC_INVIDCONF);
755 for (count = 0; count < 4; count++)
756 hdmi_write(hdmi, val, HDMI_FC_INVIDCONF);
759 static void hdmi_audio_set_format(struct dw_hdmi *hdmi)
761 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 void dw_hdmi_phy_init(struct dw_hdmi *hdmi)
941 /* enable phy i2cm done irq */
942 hdmi_write(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
943 HDMI_PHY_I2CM_INT_ADDR);
945 /* enable phy i2cm nack & arbitration error irq */
946 hdmi_write(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
947 HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
948 HDMI_PHY_I2CM_CTLINT_ADDR);
950 /* enable cable hot plug irq */
951 hdmi_write(hdmi, (u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
953 /* clear hotplug interrupts */
954 hdmi_write(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
957 int dw_hdmi_read_edid(struct dw_hdmi *hdmi, u8 *buf, int buf_size)
959 u32 edid_size = HDMI_EDID_BLOCK_SIZE;
963 edid_size = sizeof(pre_buf);
964 memcpy(buf, pre_buf, edid_size);
966 ret = hdmi_read_edid(hdmi, 0, buf);
968 debug("failed to read edid.\n");
972 if (buf[0x7e] != 0) {
973 hdmi_read_edid(hdmi, 1, buf + HDMI_EDID_BLOCK_SIZE);
974 edid_size += HDMI_EDID_BLOCK_SIZE;
981 int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
985 debug("%s, mode info : clock %d hdis %d vdis %d\n",
986 edid->hdmi_monitor ? "hdmi" : "dvi",
987 edid->pixelclock.typ, edid->hactive.typ, edid->vactive.typ);
989 hdmi_av_composer(hdmi, edid);
991 ret = hdmi->phy_set(hdmi, edid->pixelclock.typ);
995 hdmi_enable_video_path(hdmi, edid->hdmi_monitor);
997 if (edid->hdmi_monitor) {
998 hdmi_audio_fifo_reset(hdmi);
999 hdmi_audio_set_format(hdmi);
1000 hdmi_audio_set_samplerate(hdmi, edid->pixelclock.typ);
1003 hdmi_video_packetize(hdmi);
1004 hdmi_video_csc(hdmi);
1005 hdmi_video_sample(hdmi);
1007 hdmi_clear_overflow(hdmi);
1012 void dw_hdmi_init(struct dw_hdmi *hdmi)
1017 * boot up defaults are:
1018 * hdmi_ih_mute = 0x03 (disabled)
1019 * hdmi_ih_mute_* = 0x00 (enabled)
1021 * disable top level interrupt bits in hdmi block
1023 ih_mute = /*hdmi_read(hdmi, HDMI_IH_MUTE) |*/
1024 HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
1025 HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
1027 if (hdmi->write_reg)
1028 hdmi_write = hdmi->write_reg;
1031 hdmi_read = hdmi->read_reg;
1033 hdmi_write(hdmi, ih_mute, HDMI_IH_MUTE);
1035 /* enable i2c master done irq */
1036 hdmi_write(hdmi, ~0x04, HDMI_I2CM_INT);
1038 /* enable i2c client nack % arbitration error irq */
1039 hdmi_write(hdmi, ~0x44, HDMI_I2CM_CTLINT);