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>
22 static const struct tmds_n_cts n_cts_table[] = {
24 .tmds = 25175000, .n = 6144, .cts = 25175,
26 .tmds = 25200000, .n = 6144, .cts = 25200,
28 .tmds = 27000000, .n = 6144, .cts = 27000,
30 .tmds = 27027000, .n = 6144, .cts = 27027,
32 .tmds = 40000000, .n = 6144, .cts = 40000,
34 .tmds = 54000000, .n = 6144, .cts = 54000,
36 .tmds = 54054000, .n = 6144, .cts = 54054,
38 .tmds = 65000000, .n = 6144, .cts = 65000,
40 .tmds = 74176000, .n = 11648, .cts = 140625,
42 .tmds = 74250000, .n = 6144, .cts = 74250,
44 .tmds = 83500000, .n = 6144, .cts = 83500,
46 .tmds = 106500000, .n = 6144, .cts = 106500,
48 .tmds = 108000000, .n = 6144, .cts = 108000,
50 .tmds = 148352000, .n = 5824, .cts = 140625,
52 .tmds = 148500000, .n = 6144, .cts = 148500,
54 .tmds = 297000000, .n = 5120, .cts = 247500,
58 static const u16 csc_coeff_default[3][4] = {
59 { 0x2000, 0x0000, 0x0000, 0x0000 },
60 { 0x0000, 0x2000, 0x0000, 0x0000 },
61 { 0x0000, 0x0000, 0x2000, 0x0000 }
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 }
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 }
76 static void dw_hdmi_write(struct dw_hdmi *hdmi, u8 val, int offset)
78 switch (hdmi->reg_io_width) {
80 writeb(val, hdmi->ioaddr + offset);
83 writel(val, hdmi->ioaddr + (offset << 2));
86 debug("reg_io_width has unsupported width!\n");
91 static u8 dw_hdmi_read(struct dw_hdmi *hdmi, int offset)
93 switch (hdmi->reg_io_width) {
95 return readb(hdmi->ioaddr + offset);
97 return readl(hdmi->ioaddr + (offset << 2));
99 debug("reg_io_width has unsupported width!\n");
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) =
110 static void hdmi_mod(struct dw_hdmi *hdmi, unsigned reg, u8 mask, u8 data)
112 u8 val = hdmi_read(hdmi, reg) & ~mask;
115 hdmi_write(hdmi, val, reg);
118 static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi, u32 n, u32 cts)
123 /* first set ncts_atomic_write (if present) */
124 n3 = HDMI_AUD_N3_NCTS_ATOMIC_WRITE;
125 hdmi_write(hdmi, n3, HDMI_AUD_N3);
127 /* set cts_manual (if present) */
128 cts3 = HDMI_AUD_CTS3_CTS_MANUAL;
130 cts3 |= HDMI_AUD_CTS3_N_SHIFT_1 << HDMI_AUD_CTS3_N_SHIFT_OFFSET;
131 cts3 |= (cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK;
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);
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);
144 hdmi_write(hdmi, HDMI_AUD_INPUTCLKFS_128, HDMI_AUD_INPUTCLKFS);
147 static int hdmi_lookup_n_cts(u32 pixel_clk)
151 for (i = 0; i < ARRAY_SIZE(n_cts_table); i++)
152 if (pixel_clk <= n_cts_table[i].tmds)
155 if (i >= ARRAY_SIZE(n_cts_table))
161 static void hdmi_audio_set_samplerate(struct dw_hdmi *hdmi, u32 pixel_clk)
166 index = hdmi_lookup_n_cts(pixel_clk);
168 debug("audio not supported for pixel clk %d\n", pixel_clk);
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);
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]
184 static void hdmi_video_sample(struct dw_hdmi *hdmi)
189 switch (hdmi->hdmi_data.enc_in_bus_format) {
190 case MEDIA_BUS_FMT_RGB888_1X24:
193 case MEDIA_BUS_FMT_RGB101010_1X30:
196 case MEDIA_BUS_FMT_RGB121212_1X36:
199 case MEDIA_BUS_FMT_RGB161616_1X48:
202 case MEDIA_BUS_FMT_YUV8_1X24:
203 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
206 case MEDIA_BUS_FMT_YUV10_1X30:
207 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
210 case MEDIA_BUS_FMT_YUV12_1X36:
211 case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
214 case MEDIA_BUS_FMT_YUV16_1X48:
215 case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
218 case MEDIA_BUS_FMT_UYVY8_1X16:
221 case MEDIA_BUS_FMT_UYVY10_1X20:
224 case MEDIA_BUS_FMT_UYVY12_1X24:
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);
236 hdmi_write(hdmi, val, HDMI_TX_INVID0);
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);
251 static void hdmi_video_packetize(struct dw_hdmi *hdmi)
253 u32 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
254 u32 remap_size = HDMI_VP_REMAP_YCC422_16BIT;
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);
265 hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PR_STUFFING_MASK,
266 HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE);
268 /* data from pixel repeater block */
269 vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
270 HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
272 hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_PR_EN_MASK |
273 HDMI_VP_CONF_BYPASS_SELECT_MASK, vp_conf);
275 hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_IDEFAULT_PHASE_MASK,
276 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET);
278 hdmi_write(hdmi, remap_size, HDMI_VP_REMAP);
280 vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
281 HDMI_VP_CONF_PP_EN_DISABLE |
282 HDMI_VP_CONF_YCC422_EN_DISABLE;
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,
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);
293 hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
297 static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, uint bit)
299 hdmi_mod(hdmi, HDMI_PHY_TST0, HDMI_PHY_TST0_TSTCLR_MASK,
300 bit << HDMI_PHY_TST0_TSTCLR_OFFSET);
303 static int hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, u32 msec)
308 start = get_timer(0);
310 val = hdmi_read(hdmi, HDMI_IH_I2CMPHY_STAT0);
312 hdmi_write(hdmi, val, HDMI_IH_I2CMPHY_STAT0);
317 } while (get_timer(start) < msec);
322 static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, uint data, uint addr)
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);
331 hdmi_phy_wait_i2c_done(hdmi, 1000);
334 static void hdmi_phy_enable_power(struct dw_hdmi *hdmi, uint enable)
336 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_PDZ_MASK,
337 enable << HDMI_PHY_CONF0_PDZ_OFFSET);
340 static void hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, uint enable)
342 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_ENTMDS_MASK,
343 enable << HDMI_PHY_CONF0_ENTMDS_OFFSET);
346 static void hdmi_phy_enable_spare(struct dw_hdmi *hdmi, uint enable)
348 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SPARECTRL_MASK,
349 enable << HDMI_PHY_CONF0_SPARECTRL_OFFSET);
352 static void hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, uint enable)
354 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_GEN2_PDDQ_MASK,
355 enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET);
358 static void hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, uint enable)
360 hdmi_mod(hdmi, HDMI_PHY_CONF0,
361 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK,
362 enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET);
365 static void hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, uint enable)
367 hdmi_mod(hdmi, HDMI_PHY_CONF0,
368 HDMI_PHY_CONF0_SELDATAENPOL_MASK,
369 enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET);
372 static void hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi,
375 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SELDIPIF_MASK,
376 enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET);
379 static int hdmi_phy_configure(struct dw_hdmi *hdmi, u32 mpixelclock)
384 if (!hdmi->mpll_cfg || !hdmi->phy_cfg)
387 /* gen2 tx power off */
388 hdmi_phy_gen2_txpwron(hdmi, 0);
391 hdmi_phy_gen2_pddq(hdmi, 1);
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);
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);
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)
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);
412 hdmi_phy_i2c_write(hdmi, 0x0000, PHY_PLLPHBYCTRL);
413 hdmi_phy_i2c_write(hdmi, 0x0006, PHY_PLLCLKBISTPHASE);
415 for (i = 0; hdmi->phy_cfg[i].mpixelclock != (~0ul); i++)
416 if (mpixelclock <= hdmi->phy_cfg[i].mpixelclock)
420 * resistance term 133ohm cfg
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);
428 /* remove clk term */
429 hdmi_phy_i2c_write(hdmi, 0x8000, PHY_CKCALCTRL);
431 hdmi_phy_enable_power(hdmi, 1);
433 /* toggle tmds enable */
434 hdmi_phy_enable_tmds(hdmi, 0);
435 hdmi_phy_enable_tmds(hdmi, 1);
437 /* gen2 tx power on */
438 hdmi_phy_gen2_txpwron(hdmi, 1);
439 hdmi_phy_gen2_pddq(hdmi, 0);
441 hdmi_phy_enable_spare(hdmi, 1);
443 /* wait for phy pll lock */
444 start = get_timer(0);
446 val = hdmi_read(hdmi, HDMI_PHY_STAT0);
447 if (!(val & HDMI_PHY_TX_PHY_LOCK))
451 } while (get_timer(start) < 5);
456 static void hdmi_av_composer(struct dw_hdmi *hdmi,
457 const struct display_timing *edid)
459 bool mdataenablepolarity = true;
464 hbl = edid->hback_porch.typ + edid->hfront_porch.typ +
466 vbl = edid->vback_porch.typ + edid->vfront_porch.typ +
469 /* set up hdmi_fc_invidconf */
470 inv_val = HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE;
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);
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);
480 inv_val |= (mdataenablepolarity ?
481 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
482 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
484 inv_val |= (edid->hdmi_monitor ?
485 HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
486 HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE);
488 inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
490 inv_val |= HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
492 hdmi_write(hdmi, inv_val, HDMI_FC_INVIDCONF);
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);
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);
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);
506 /* set up vertical blanking pixel region width */
507 hdmi_write(hdmi, vbl, HDMI_FC_INVBLANK);
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);
513 /* set up vsync active edge delay (in lines) */
514 hdmi_write(hdmi, edid->vfront_porch.typ, HDMI_FC_VSYNCINDELAY);
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);
520 /* set up vsync active edge delay (in lines) */
521 hdmi_write(hdmi, edid->vsync_len.typ, HDMI_FC_VSYNCINWIDTH);
524 static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
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:
538 static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
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:
552 static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
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:
565 static int is_color_space_interpolation(struct dw_hdmi *hdmi)
567 if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format))
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))
577 static int is_color_space_decimation(struct dw_hdmi *hdmi)
579 if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
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))
589 static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
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:
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:
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:
610 case MEDIA_BUS_FMT_RGB161616_1X48:
611 case MEDIA_BUS_FMT_YUV16_1X48:
612 case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
620 static int is_color_space_conversion(struct dw_hdmi *hdmi)
622 return hdmi->hdmi_data.enc_in_bus_format !=
623 hdmi->hdmi_data.enc_out_bus_format;
626 static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
628 const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
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;
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];
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);
656 hdmi_mod(hdmi, HDMI_CSC_SCALE, HDMI_CSC_SCALE_CSCSCALE_MASK, csc_scale);
659 static void hdmi_video_csc(struct dw_hdmi *hdmi)
662 int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
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;
671 switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) {
673 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
676 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
679 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
682 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
689 /* Configure the CSC registers */
690 hdmi_write(hdmi, interpolation | decimation, HDMI_CSC_CFG);
692 hdmi_mod(hdmi, HDMI_CSC_SCALE, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
695 dw_hdmi_update_csc_coeffs(hdmi);
698 /* hdmi initialization step b.4 */
699 static void hdmi_enable_video_path(struct dw_hdmi *hdmi, bool audio)
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);
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);
713 hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
716 /* enable pixel clock and tmds data path */
718 clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
719 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
721 clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
722 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
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);
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,
735 hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
739 clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
740 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
744 /* workaround to clear the overflow condition */
745 static void hdmi_clear_overflow(struct dw_hdmi *hdmi)
749 /* tmds software reset */
750 hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
752 val = hdmi_read(hdmi, HDMI_FC_INVIDCONF);
754 for (count = 0; count < 4; count++)
755 hdmi_write(hdmi, val, HDMI_FC_INVIDCONF);
758 static void hdmi_audio_set_format(struct dw_hdmi *hdmi)
760 hdmi_write(hdmi, HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_IN_EN_0,
764 hdmi_write(hdmi, HDMI_AUD_CONF1_I2S_MODE_STANDARD_MODE |
765 HDMI_AUD_CONF1_I2S_WIDTH_16BIT, HDMI_AUD_CONF1);
767 hdmi_write(hdmi, 0x00, HDMI_AUD_CONF2);
770 static void hdmi_audio_fifo_reset(struct dw_hdmi *hdmi)
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);
775 hdmi_write(hdmi, 0x00, HDMI_AUD_INT);
776 hdmi_write(hdmi, 0x00, HDMI_AUD_INT1);
779 static int hdmi_get_plug_in_status(struct dw_hdmi *hdmi)
781 uint val = hdmi_read(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD;
786 static int hdmi_ddc_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
791 start = get_timer(0);
793 val = hdmi_read(hdmi, HDMI_IH_I2CM_STAT0);
795 hdmi_write(hdmi, val, HDMI_IH_I2CM_STAT0);
800 } while (get_timer(start) < msec);
805 static void hdmi_ddc_reset(struct dw_hdmi *hdmi)
807 hdmi_mod(hdmi, HDMI_I2CM_SOFTRSTZ, HDMI_I2CM_SOFTRSTZ_MASK, 0);
810 static int hdmi_read_edid(struct dw_hdmi *hdmi, int block, u8 *buff)
812 int shift = (block % 2) * 0x80;
813 int edid_read_err = 0;
817 if (CONFIG_IS_ENABLED(DM_I2C) && hdmi->ddc_bus) {
818 struct udevice *chip;
820 edid_read_err = i2c_get_chip(hdmi->ddc_bus,
821 HDMI_I2CM_SLAVE_DDC_ADDR,
824 return edid_read_err;
826 return dm_i2c_read(chip, shift, buff, HDMI_EDID_BLOCK_SIZE);
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);
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);
842 for (n = 0; n < HDMI_EDID_BLOCK_SIZE; n++) {
843 hdmi_write(hdmi, shift + n, HDMI_I2CM_ADDRESS);
846 hdmi_write(hdmi, HDMI_I2CM_OP_RD8,
847 HDMI_I2CM_OPERATION);
849 hdmi_write(hdmi, HDMI_I2CM_OP_RD8_EXT,
850 HDMI_I2CM_OPERATION);
852 if (hdmi_ddc_wait_i2c_done(hdmi, 10)) {
853 hdmi_ddc_reset(hdmi);
858 buff[n] = hdmi_read(hdmi, HDMI_I2CM_DATAI);
865 return edid_read_err;
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,
903 int dw_hdmi_phy_cfg(struct dw_hdmi *hdmi, uint mpixelclock)
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);
914 ret = hdmi_phy_configure(hdmi, mpixelclock);
916 debug("hdmi phy config failure %d\n", ret);
924 int dw_hdmi_phy_wait_for_hpd(struct dw_hdmi *hdmi)
928 start = get_timer(0);
930 if (hdmi_get_plug_in_status(hdmi))
933 } while (get_timer(start) < 300);
938 void dw_hdmi_phy_init(struct dw_hdmi *hdmi)
940 /* enable phy i2cm done irq */
941 hdmi_write(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
942 HDMI_PHY_I2CM_INT_ADDR);
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);
949 /* enable cable hot plug irq */
950 hdmi_write(hdmi, (u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
952 /* clear hotplug interrupts */
953 hdmi_write(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
956 int dw_hdmi_read_edid(struct dw_hdmi *hdmi, u8 *buf, int buf_size)
958 u32 edid_size = HDMI_EDID_BLOCK_SIZE;
962 edid_size = sizeof(pre_buf);
963 memcpy(buf, pre_buf, edid_size);
965 ret = hdmi_read_edid(hdmi, 0, buf);
967 debug("failed to read edid.\n");
971 if (buf[0x7e] != 0) {
972 hdmi_read_edid(hdmi, 1, buf + HDMI_EDID_BLOCK_SIZE);
973 edid_size += HDMI_EDID_BLOCK_SIZE;
980 int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
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);
988 hdmi_av_composer(hdmi, edid);
990 ret = hdmi->phy_set(hdmi, edid->pixelclock.typ);
994 hdmi_enable_video_path(hdmi, edid->hdmi_monitor);
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);
1002 hdmi_video_packetize(hdmi);
1003 hdmi_video_csc(hdmi);
1004 hdmi_video_sample(hdmi);
1006 hdmi_clear_overflow(hdmi);
1011 void dw_hdmi_init(struct dw_hdmi *hdmi)
1016 * boot up defaults are:
1017 * hdmi_ih_mute = 0x03 (disabled)
1018 * hdmi_ih_mute_* = 0x00 (enabled)
1020 * disable top level interrupt bits in hdmi block
1022 ih_mute = /*hdmi_read(hdmi, HDMI_IH_MUTE) |*/
1023 HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
1024 HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
1026 if (hdmi->write_reg)
1027 hdmi_write = hdmi->write_reg;
1030 hdmi_read = hdmi->read_reg;
1032 hdmi_write(hdmi, ih_mute, HDMI_IH_MUTE);
1034 /* enable i2c master done irq */
1035 hdmi_write(hdmi, ~0x04, HDMI_I2CM_INT);
1037 /* enable i2c client nack % arbitration error irq */
1038 hdmi_write(hdmi, ~0x44, HDMI_I2CM_CTLINT);