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>
12 #include <media_bus_format.h>
21 static const struct tmds_n_cts n_cts_table[] = {
23 .tmds = 25175000, .n = 6144, .cts = 25175,
25 .tmds = 25200000, .n = 6144, .cts = 25200,
27 .tmds = 27000000, .n = 6144, .cts = 27000,
29 .tmds = 27027000, .n = 6144, .cts = 27027,
31 .tmds = 40000000, .n = 6144, .cts = 40000,
33 .tmds = 54000000, .n = 6144, .cts = 54000,
35 .tmds = 54054000, .n = 6144, .cts = 54054,
37 .tmds = 65000000, .n = 6144, .cts = 65000,
39 .tmds = 74176000, .n = 11648, .cts = 140625,
41 .tmds = 74250000, .n = 6144, .cts = 74250,
43 .tmds = 83500000, .n = 6144, .cts = 83500,
45 .tmds = 106500000, .n = 6144, .cts = 106500,
47 .tmds = 108000000, .n = 6144, .cts = 108000,
49 .tmds = 148352000, .n = 5824, .cts = 140625,
51 .tmds = 148500000, .n = 6144, .cts = 148500,
53 .tmds = 297000000, .n = 5120, .cts = 247500,
57 static const u16 csc_coeff_default[3][4] = {
58 { 0x2000, 0x0000, 0x0000, 0x0000 },
59 { 0x0000, 0x2000, 0x0000, 0x0000 },
60 { 0x0000, 0x0000, 0x2000, 0x0000 }
63 static const u16 csc_coeff_rgb_in_eitu601[3][4] = {
64 { 0x2591, 0x1322, 0x074b, 0x0000 },
65 { 0x6535, 0x2000, 0x7acc, 0x0200 },
66 { 0x6acd, 0x7534, 0x2000, 0x0200 }
69 static const u16 csc_coeff_rgb_out_eitu601[3][4] = {
70 { 0x2000, 0x6926, 0x74fd, 0x010e },
71 { 0x2000, 0x2cdd, 0x0000, 0x7e9a },
72 { 0x2000, 0x0000, 0x38b4, 0x7e3b }
75 static void dw_hdmi_write(struct dw_hdmi *hdmi, u8 val, int offset)
77 switch (hdmi->reg_io_width) {
79 writeb(val, hdmi->ioaddr + offset);
82 writel(val, hdmi->ioaddr + (offset << 2));
85 debug("reg_io_width has unsupported width!\n");
90 static u8 dw_hdmi_read(struct dw_hdmi *hdmi, int offset)
92 switch (hdmi->reg_io_width) {
94 return readb(hdmi->ioaddr + offset);
96 return readl(hdmi->ioaddr + (offset << 2));
98 debug("reg_io_width has unsupported width!\n");
105 static u8 (*hdmi_read)(struct dw_hdmi *hdmi, int offset) = dw_hdmi_read;
106 static void (*hdmi_write)(struct dw_hdmi *hdmi, u8 val, int offset) =
109 static void hdmi_mod(struct dw_hdmi *hdmi, unsigned reg, u8 mask, u8 data)
111 u8 val = hdmi_read(hdmi, reg) & ~mask;
114 hdmi_write(hdmi, val, reg);
117 static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi, u32 n, u32 cts)
122 /* first set ncts_atomic_write (if present) */
123 n3 = HDMI_AUD_N3_NCTS_ATOMIC_WRITE;
124 hdmi_write(hdmi, n3, HDMI_AUD_N3);
126 /* set cts_manual (if present) */
127 cts3 = HDMI_AUD_CTS3_CTS_MANUAL;
129 cts3 |= HDMI_AUD_CTS3_N_SHIFT_1 << HDMI_AUD_CTS3_N_SHIFT_OFFSET;
130 cts3 |= (cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK;
132 /* write cts values; cts3 must be written first */
133 hdmi_write(hdmi, cts3, HDMI_AUD_CTS3);
134 hdmi_write(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
135 hdmi_write(hdmi, cts & 0xff, HDMI_AUD_CTS1);
137 /* write n values; n1 must be written last */
138 n3 |= (n >> 16) & HDMI_AUD_N3_AUDN19_16_MASK;
139 hdmi_write(hdmi, n3, HDMI_AUD_N3);
140 hdmi_write(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
141 hdmi_write(hdmi, n & 0xff, HDMI_AUD_N3);
143 hdmi_write(hdmi, HDMI_AUD_INPUTCLKFS_128, HDMI_AUD_INPUTCLKFS);
146 static int hdmi_lookup_n_cts(u32 pixel_clk)
150 for (i = 0; i < ARRAY_SIZE(n_cts_table); i++)
151 if (pixel_clk <= n_cts_table[i].tmds)
154 if (i >= ARRAY_SIZE(n_cts_table))
160 static void hdmi_audio_set_samplerate(struct dw_hdmi *hdmi, u32 pixel_clk)
165 index = hdmi_lookup_n_cts(pixel_clk);
167 debug("audio not supported for pixel clk %d\n", pixel_clk);
171 clk_n = n_cts_table[index].n;
172 clk_cts = n_cts_table[index].cts;
173 hdmi_set_clock_regenerator(hdmi, clk_n, clk_cts);
177 * this submodule is responsible for the video data synchronization.
178 * for example, for rgb 4:4:4 input, the data map is defined as
179 * pin{47~40} <==> r[7:0]
180 * pin{31~24} <==> g[7:0]
181 * pin{15~8} <==> b[7:0]
183 static void hdmi_video_sample(struct dw_hdmi *hdmi)
188 switch (hdmi->hdmi_data.enc_in_bus_format) {
189 case MEDIA_BUS_FMT_RGB888_1X24:
192 case MEDIA_BUS_FMT_RGB101010_1X30:
195 case MEDIA_BUS_FMT_RGB121212_1X36:
198 case MEDIA_BUS_FMT_RGB161616_1X48:
201 case MEDIA_BUS_FMT_YUV8_1X24:
202 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
205 case MEDIA_BUS_FMT_YUV10_1X30:
206 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
209 case MEDIA_BUS_FMT_YUV12_1X36:
210 case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
213 case MEDIA_BUS_FMT_YUV16_1X48:
214 case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
217 case MEDIA_BUS_FMT_UYVY8_1X16:
220 case MEDIA_BUS_FMT_UYVY10_1X20:
223 case MEDIA_BUS_FMT_UYVY12_1X24:
231 val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
232 ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
233 HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
235 hdmi_write(hdmi, val, HDMI_TX_INVID0);
237 /* enable tx stuffing: when de is inactive, fix the output data to 0 */
238 val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
239 HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
240 HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
241 hdmi_write(hdmi, val, HDMI_TX_INSTUFFING);
242 hdmi_write(hdmi, 0x0, HDMI_TX_GYDATA0);
243 hdmi_write(hdmi, 0x0, HDMI_TX_GYDATA1);
244 hdmi_write(hdmi, 0x0, HDMI_TX_RCRDATA0);
245 hdmi_write(hdmi, 0x0, HDMI_TX_RCRDATA1);
246 hdmi_write(hdmi, 0x0, HDMI_TX_BCBDATA0);
247 hdmi_write(hdmi, 0x0, HDMI_TX_BCBDATA1);
250 static void hdmi_video_packetize(struct dw_hdmi *hdmi)
252 u32 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
253 u32 remap_size = HDMI_VP_REMAP_YCC422_16BIT;
257 /* set the packetizer registers */
258 val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
259 HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
260 ((0 << HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
261 HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
262 hdmi_write(hdmi, val, HDMI_VP_PR_CD);
264 hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PR_STUFFING_MASK,
265 HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE);
267 /* data from pixel repeater block */
268 vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
269 HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
271 hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_PR_EN_MASK |
272 HDMI_VP_CONF_BYPASS_SELECT_MASK, vp_conf);
274 hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_IDEFAULT_PHASE_MASK,
275 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET);
277 hdmi_write(hdmi, remap_size, HDMI_VP_REMAP);
279 vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
280 HDMI_VP_CONF_PP_EN_DISABLE |
281 HDMI_VP_CONF_YCC422_EN_DISABLE;
283 hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_BYPASS_EN_MASK |
284 HDMI_VP_CONF_PP_EN_ENMASK | HDMI_VP_CONF_YCC422_EN_MASK,
287 hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PP_STUFFING_MASK |
288 HDMI_VP_STUFF_YCC422_STUFFING_MASK,
289 HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
290 HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE);
292 hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
296 static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, uint bit)
298 hdmi_mod(hdmi, HDMI_PHY_TST0, HDMI_PHY_TST0_TSTCLR_MASK,
299 bit << HDMI_PHY_TST0_TSTCLR_OFFSET);
302 static int hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, u32 msec)
307 start = get_timer(0);
309 val = hdmi_read(hdmi, HDMI_IH_I2CMPHY_STAT0);
311 hdmi_write(hdmi, val, HDMI_IH_I2CMPHY_STAT0);
316 } while (get_timer(start) < msec);
321 static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, uint data, uint addr)
323 hdmi_write(hdmi, 0xff, HDMI_IH_I2CMPHY_STAT0);
324 hdmi_write(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
325 hdmi_write(hdmi, (u8)(data >> 8), HDMI_PHY_I2CM_DATAO_1_ADDR);
326 hdmi_write(hdmi, (u8)(data >> 0), HDMI_PHY_I2CM_DATAO_0_ADDR);
327 hdmi_write(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
328 HDMI_PHY_I2CM_OPERATION_ADDR);
330 hdmi_phy_wait_i2c_done(hdmi, 1000);
333 static void hdmi_phy_enable_power(struct dw_hdmi *hdmi, uint enable)
335 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_PDZ_MASK,
336 enable << HDMI_PHY_CONF0_PDZ_OFFSET);
339 static void hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, uint enable)
341 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_ENTMDS_MASK,
342 enable << HDMI_PHY_CONF0_ENTMDS_OFFSET);
345 static void hdmi_phy_enable_spare(struct dw_hdmi *hdmi, uint enable)
347 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SPARECTRL_MASK,
348 enable << HDMI_PHY_CONF0_SPARECTRL_OFFSET);
351 static void hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, uint enable)
353 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_GEN2_PDDQ_MASK,
354 enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET);
357 static void hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, uint enable)
359 hdmi_mod(hdmi, HDMI_PHY_CONF0,
360 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK,
361 enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET);
364 static void hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, uint enable)
366 hdmi_mod(hdmi, HDMI_PHY_CONF0,
367 HDMI_PHY_CONF0_SELDATAENPOL_MASK,
368 enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET);
371 static void hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi,
374 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SELDIPIF_MASK,
375 enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET);
378 static int hdmi_phy_configure(struct dw_hdmi *hdmi, u32 mpixelclock)
383 if (!hdmi->mpll_cfg || !hdmi->phy_cfg)
386 /* gen2 tx power off */
387 hdmi_phy_gen2_txpwron(hdmi, 0);
390 hdmi_phy_gen2_pddq(hdmi, 1);
393 hdmi_write(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
394 hdmi_write(hdmi, HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
395 hdmi_write(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
397 hdmi_phy_test_clear(hdmi, 1);
398 hdmi_write(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
399 HDMI_PHY_I2CM_SLAVE_ADDR);
400 hdmi_phy_test_clear(hdmi, 0);
402 /* pll/mpll cfg - always match on final entry */
403 for (i = 0; hdmi->mpll_cfg[i].mpixelclock != (~0ul); i++)
404 if (mpixelclock <= hdmi->mpll_cfg[i].mpixelclock)
407 hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].cpce, PHY_OPMODE_PLLCFG);
408 hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].gmp, PHY_PLLGMPCTRL);
409 hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].curr, PHY_PLLCURRCTRL);
411 hdmi_phy_i2c_write(hdmi, 0x0000, PHY_PLLPHBYCTRL);
412 hdmi_phy_i2c_write(hdmi, 0x0006, PHY_PLLCLKBISTPHASE);
414 for (i = 0; hdmi->phy_cfg[i].mpixelclock != (~0ul); i++)
415 if (mpixelclock <= hdmi->phy_cfg[i].mpixelclock)
419 * resistance term 133ohm cfg
423 hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].term, PHY_TXTERM);
424 hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].sym_ctr, PHY_CKSYMTXCTRL);
425 hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].vlev_ctr, PHY_VLEVCTRL);
427 /* remove clk term */
428 hdmi_phy_i2c_write(hdmi, 0x8000, PHY_CKCALCTRL);
430 hdmi_phy_enable_power(hdmi, 1);
432 /* toggle tmds enable */
433 hdmi_phy_enable_tmds(hdmi, 0);
434 hdmi_phy_enable_tmds(hdmi, 1);
436 /* gen2 tx power on */
437 hdmi_phy_gen2_txpwron(hdmi, 1);
438 hdmi_phy_gen2_pddq(hdmi, 0);
440 hdmi_phy_enable_spare(hdmi, 1);
442 /* wait for phy pll lock */
443 start = get_timer(0);
445 val = hdmi_read(hdmi, HDMI_PHY_STAT0);
446 if (!(val & HDMI_PHY_TX_PHY_LOCK))
450 } while (get_timer(start) < 5);
455 static void hdmi_av_composer(struct dw_hdmi *hdmi,
456 const struct display_timing *edid)
458 bool mdataenablepolarity = true;
463 hbl = edid->hback_porch.typ + edid->hfront_porch.typ +
465 vbl = edid->vback_porch.typ + edid->vfront_porch.typ +
468 /* set up hdmi_fc_invidconf */
469 inv_val = HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE;
471 inv_val |= (edid->flags & DISPLAY_FLAGS_VSYNC_HIGH ?
472 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
473 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
475 inv_val |= (edid->flags & DISPLAY_FLAGS_HSYNC_HIGH ?
476 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
477 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
479 inv_val |= (mdataenablepolarity ?
480 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
481 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
483 inv_val |= (edid->hdmi_monitor ?
484 HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
485 HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE);
487 inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
489 inv_val |= HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
491 hdmi_write(hdmi, inv_val, HDMI_FC_INVIDCONF);
493 /* set up horizontal active pixel width */
494 hdmi_write(hdmi, edid->hactive.typ >> 8, HDMI_FC_INHACTV1);
495 hdmi_write(hdmi, edid->hactive.typ, HDMI_FC_INHACTV0);
497 /* set up vertical active lines */
498 hdmi_write(hdmi, edid->vactive.typ >> 8, HDMI_FC_INVACTV1);
499 hdmi_write(hdmi, edid->vactive.typ, HDMI_FC_INVACTV0);
501 /* set up horizontal blanking pixel region width */
502 hdmi_write(hdmi, hbl >> 8, HDMI_FC_INHBLANK1);
503 hdmi_write(hdmi, hbl, HDMI_FC_INHBLANK0);
505 /* set up vertical blanking pixel region width */
506 hdmi_write(hdmi, vbl, HDMI_FC_INVBLANK);
508 /* set up hsync active edge delay width (in pixel clks) */
509 hdmi_write(hdmi, edid->hfront_porch.typ >> 8, HDMI_FC_HSYNCINDELAY1);
510 hdmi_write(hdmi, edid->hfront_porch.typ, HDMI_FC_HSYNCINDELAY0);
512 /* set up vsync active edge delay (in lines) */
513 hdmi_write(hdmi, edid->vfront_porch.typ, HDMI_FC_VSYNCINDELAY);
515 /* set up hsync active pulse width (in pixel clks) */
516 hdmi_write(hdmi, edid->hsync_len.typ >> 8, HDMI_FC_HSYNCINWIDTH1);
517 hdmi_write(hdmi, edid->hsync_len.typ, HDMI_FC_HSYNCINWIDTH0);
519 /* set up vsync active edge delay (in lines) */
520 hdmi_write(hdmi, edid->vsync_len.typ, HDMI_FC_VSYNCINWIDTH);
523 static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
525 switch (bus_format) {
526 case MEDIA_BUS_FMT_RGB888_1X24:
527 case MEDIA_BUS_FMT_RGB101010_1X30:
528 case MEDIA_BUS_FMT_RGB121212_1X36:
529 case MEDIA_BUS_FMT_RGB161616_1X48:
537 static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
539 switch (bus_format) {
540 case MEDIA_BUS_FMT_YUV8_1X24:
541 case MEDIA_BUS_FMT_YUV10_1X30:
542 case MEDIA_BUS_FMT_YUV12_1X36:
543 case MEDIA_BUS_FMT_YUV16_1X48:
551 static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
553 switch (bus_format) {
554 case MEDIA_BUS_FMT_UYVY8_1X16:
555 case MEDIA_BUS_FMT_UYVY10_1X20:
556 case MEDIA_BUS_FMT_UYVY12_1X24:
564 static int is_color_space_interpolation(struct dw_hdmi *hdmi)
566 if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format))
569 if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) ||
570 hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
576 static int is_color_space_decimation(struct dw_hdmi *hdmi)
578 if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
581 if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) ||
582 hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format))
588 static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
590 switch (bus_format) {
591 case MEDIA_BUS_FMT_RGB888_1X24:
592 case MEDIA_BUS_FMT_YUV8_1X24:
593 case MEDIA_BUS_FMT_UYVY8_1X16:
594 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
597 case MEDIA_BUS_FMT_RGB101010_1X30:
598 case MEDIA_BUS_FMT_YUV10_1X30:
599 case MEDIA_BUS_FMT_UYVY10_1X20:
600 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
603 case MEDIA_BUS_FMT_RGB121212_1X36:
604 case MEDIA_BUS_FMT_YUV12_1X36:
605 case MEDIA_BUS_FMT_UYVY12_1X24:
606 case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
609 case MEDIA_BUS_FMT_RGB161616_1X48:
610 case MEDIA_BUS_FMT_YUV16_1X48:
611 case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
619 static int is_color_space_conversion(struct dw_hdmi *hdmi)
621 return hdmi->hdmi_data.enc_in_bus_format !=
622 hdmi->hdmi_data.enc_out_bus_format;
625 static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
627 const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
631 if (is_color_space_conversion(hdmi)) {
632 if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
633 csc_coeff = &csc_coeff_rgb_out_eitu601;
634 } else if (hdmi_bus_fmt_is_rgb(
635 hdmi->hdmi_data.enc_in_bus_format)) {
636 csc_coeff = &csc_coeff_rgb_in_eitu601;
641 /* The CSC registers are sequential, alternating MSB then LSB */
642 for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) {
643 u16 coeff_a = (*csc_coeff)[0][i];
644 u16 coeff_b = (*csc_coeff)[1][i];
645 u16 coeff_c = (*csc_coeff)[2][i];
647 hdmi_write(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2);
648 hdmi_write(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2);
649 hdmi_write(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2);
650 hdmi_write(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
651 hdmi_write(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2);
652 hdmi_write(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
655 hdmi_mod(hdmi, HDMI_CSC_SCALE, HDMI_CSC_SCALE_CSCSCALE_MASK, csc_scale);
658 static void hdmi_video_csc(struct dw_hdmi *hdmi)
661 int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
664 /* YCC422 interpolation to 444 mode */
665 if (is_color_space_interpolation(hdmi))
666 interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1;
667 else if (is_color_space_decimation(hdmi))
668 decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
670 switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) {
672 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
675 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
678 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
681 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
688 /* Configure the CSC registers */
689 hdmi_write(hdmi, interpolation | decimation, HDMI_CSC_CFG);
691 hdmi_mod(hdmi, HDMI_CSC_SCALE, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
694 dw_hdmi_update_csc_coeffs(hdmi);
697 /* hdmi initialization step b.4 */
698 static void hdmi_enable_video_path(struct dw_hdmi *hdmi, bool audio)
702 /* control period minimum duration */
703 hdmi_write(hdmi, 12, HDMI_FC_CTRLDUR);
704 hdmi_write(hdmi, 32, HDMI_FC_EXCTRLDUR);
705 hdmi_write(hdmi, 1, HDMI_FC_EXCTRLSPAC);
707 /* set to fill tmds data channels */
708 hdmi_write(hdmi, 0x0b, HDMI_FC_CH0PREAM);
709 hdmi_write(hdmi, 0x16, HDMI_FC_CH1PREAM);
710 hdmi_write(hdmi, 0x21, HDMI_FC_CH2PREAM);
712 hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
715 /* enable pixel clock and tmds data path */
717 clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
718 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
720 clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
721 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
723 /* Enable csc path */
724 if (is_color_space_conversion(hdmi)) {
725 clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
726 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
729 /* Enable color space conversion if needed */
730 if (is_color_space_conversion(hdmi))
731 hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
734 hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
738 clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
739 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
743 /* workaround to clear the overflow condition */
744 static void hdmi_clear_overflow(struct dw_hdmi *hdmi)
748 /* tmds software reset */
749 hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
751 val = hdmi_read(hdmi, HDMI_FC_INVIDCONF);
753 for (count = 0; count < 4; count++)
754 hdmi_write(hdmi, val, HDMI_FC_INVIDCONF);
757 static void hdmi_audio_set_format(struct dw_hdmi *hdmi)
759 hdmi_write(hdmi, HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_IN_EN_0,
763 hdmi_write(hdmi, HDMI_AUD_CONF1_I2S_MODE_STANDARD_MODE |
764 HDMI_AUD_CONF1_I2S_WIDTH_16BIT, HDMI_AUD_CONF1);
766 hdmi_write(hdmi, 0x00, HDMI_AUD_CONF2);
769 static void hdmi_audio_fifo_reset(struct dw_hdmi *hdmi)
771 hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_II2SSWRST_REQ, HDMI_MC_SWRSTZ);
772 hdmi_write(hdmi, HDMI_AUD_CONF0_SW_AUDIO_FIFO_RST, HDMI_AUD_CONF0);
774 hdmi_write(hdmi, 0x00, HDMI_AUD_INT);
775 hdmi_write(hdmi, 0x00, HDMI_AUD_INT1);
778 static int hdmi_get_plug_in_status(struct dw_hdmi *hdmi)
780 uint val = hdmi_read(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD;
785 static int hdmi_ddc_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
790 start = get_timer(0);
792 val = hdmi_read(hdmi, HDMI_IH_I2CM_STAT0);
794 hdmi_write(hdmi, val, HDMI_IH_I2CM_STAT0);
799 } while (get_timer(start) < msec);
804 static void hdmi_ddc_reset(struct dw_hdmi *hdmi)
806 hdmi_mod(hdmi, HDMI_I2CM_SOFTRSTZ, HDMI_I2CM_SOFTRSTZ_MASK, 0);
809 static int hdmi_read_edid(struct dw_hdmi *hdmi, int block, u8 *buff)
811 int shift = (block % 2) * 0x80;
812 int edid_read_err = 0;
816 if (CONFIG_IS_ENABLED(DM_I2C) && hdmi->ddc_bus) {
817 struct udevice *chip;
819 edid_read_err = i2c_get_chip(hdmi->ddc_bus,
820 HDMI_I2CM_SLAVE_DDC_ADDR,
823 return edid_read_err;
825 return dm_i2c_read(chip, shift, buff, HDMI_EDID_BLOCK_SIZE);
828 /* set ddc i2c clk which devided from ddc_clk to 100khz */
829 hdmi_write(hdmi, hdmi->i2c_clk_high, HDMI_I2CM_SS_SCL_HCNT_0_ADDR);
830 hdmi_write(hdmi, hdmi->i2c_clk_low, HDMI_I2CM_SS_SCL_LCNT_0_ADDR);
831 hdmi_mod(hdmi, HDMI_I2CM_DIV, HDMI_I2CM_DIV_FAST_STD_MODE,
832 HDMI_I2CM_DIV_STD_MODE);
834 hdmi_write(hdmi, HDMI_I2CM_SLAVE_DDC_ADDR, HDMI_I2CM_SLAVE);
835 hdmi_write(hdmi, HDMI_I2CM_SEGADDR_DDC, HDMI_I2CM_SEGADDR);
836 hdmi_write(hdmi, block >> 1, HDMI_I2CM_SEGPTR);
841 for (n = 0; n < HDMI_EDID_BLOCK_SIZE; n++) {
842 hdmi_write(hdmi, shift + n, HDMI_I2CM_ADDRESS);
845 hdmi_write(hdmi, HDMI_I2CM_OP_RD8,
846 HDMI_I2CM_OPERATION);
848 hdmi_write(hdmi, HDMI_I2CM_OP_RD8_EXT,
849 HDMI_I2CM_OPERATION);
851 if (hdmi_ddc_wait_i2c_done(hdmi, 10)) {
852 hdmi_ddc_reset(hdmi);
857 buff[n] = hdmi_read(hdmi, HDMI_I2CM_DATAI);
864 return edid_read_err;
867 static const u8 pre_buf[] = {
868 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
869 0x04, 0x69, 0xfa, 0x23, 0xc8, 0x28, 0x01, 0x00,
870 0x10, 0x17, 0x01, 0x03, 0x80, 0x33, 0x1d, 0x78,
871 0x2a, 0xd9, 0x45, 0xa2, 0x55, 0x4d, 0xa0, 0x27,
872 0x12, 0x50, 0x54, 0xb7, 0xef, 0x00, 0x71, 0x4f,
873 0x81, 0x40, 0x81, 0x80, 0x95, 0x00, 0xb3, 0x00,
874 0xd1, 0xc0, 0x81, 0xc0, 0x81, 0x00, 0x02, 0x3a,
875 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
876 0x45, 0x00, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
877 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x34, 0x4c,
878 0x4d, 0x54, 0x46, 0x30, 0x37, 0x35, 0x39, 0x37,
879 0x36, 0x0a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
880 0x4b, 0x18, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20,
881 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
882 0x00, 0x41, 0x53, 0x55, 0x53, 0x20, 0x56, 0x53,
883 0x32, 0x33, 0x38, 0x0a, 0x20, 0x20, 0x01, 0xb0,
884 0x02, 0x03, 0x22, 0x71, 0x4f, 0x01, 0x02, 0x03,
885 0x11, 0x12, 0x13, 0x04, 0x14, 0x05, 0x0e, 0x0f,
886 0x1d, 0x1e, 0x1f, 0x10, 0x23, 0x09, 0x17, 0x07,
887 0x83, 0x01, 0x00, 0x00, 0x65, 0x03, 0x0c, 0x00,
888 0x10, 0x00, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0,
889 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xfd, 0x1e,
890 0x11, 0x00, 0x00, 0x18, 0x01, 0x1d, 0x00, 0x72,
891 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
892 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e, 0x01, 0x1d,
893 0x00, 0xbc, 0x52, 0xd0, 0x1e, 0x20, 0xb8, 0x28,
894 0x55, 0x40, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
895 0x8c, 0x0a, 0xd0, 0x90, 0x20, 0x40, 0x31, 0x20,
896 0x0c, 0x40, 0x55, 0x00, 0xfd, 0x1e, 0x11, 0x00,
897 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
898 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
899 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9,
902 int dw_hdmi_phy_cfg(struct dw_hdmi *hdmi, uint mpixelclock)
906 /* hdmi phy spec says to do the phy initialization sequence twice */
907 for (i = 0; i < 2; i++) {
908 hdmi_phy_sel_data_en_pol(hdmi, 1);
909 hdmi_phy_sel_interface_control(hdmi, 0);
910 hdmi_phy_enable_tmds(hdmi, 0);
911 hdmi_phy_enable_power(hdmi, 0);
913 ret = hdmi_phy_configure(hdmi, mpixelclock);
915 debug("hdmi phy config failure %d\n", ret);
923 int dw_hdmi_phy_wait_for_hpd(struct dw_hdmi *hdmi)
927 start = get_timer(0);
929 if (hdmi_get_plug_in_status(hdmi))
932 } while (get_timer(start) < 300);
937 void dw_hdmi_phy_init(struct dw_hdmi *hdmi)
939 /* enable phy i2cm done irq */
940 hdmi_write(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
941 HDMI_PHY_I2CM_INT_ADDR);
943 /* enable phy i2cm nack & arbitration error irq */
944 hdmi_write(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
945 HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
946 HDMI_PHY_I2CM_CTLINT_ADDR);
948 /* enable cable hot plug irq */
949 hdmi_write(hdmi, (u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
951 /* clear hotplug interrupts */
952 hdmi_write(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
955 int dw_hdmi_read_edid(struct dw_hdmi *hdmi, u8 *buf, int buf_size)
957 u32 edid_size = HDMI_EDID_BLOCK_SIZE;
961 edid_size = sizeof(pre_buf);
962 memcpy(buf, pre_buf, edid_size);
964 ret = hdmi_read_edid(hdmi, 0, buf);
966 debug("failed to read edid.\n");
970 if (buf[0x7e] != 0) {
971 hdmi_read_edid(hdmi, 1, buf + HDMI_EDID_BLOCK_SIZE);
972 edid_size += HDMI_EDID_BLOCK_SIZE;
979 int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
983 debug("%s, mode info : clock %d hdis %d vdis %d\n",
984 edid->hdmi_monitor ? "hdmi" : "dvi",
985 edid->pixelclock.typ, edid->hactive.typ, edid->vactive.typ);
987 hdmi_av_composer(hdmi, edid);
989 ret = hdmi->phy_set(hdmi, edid->pixelclock.typ);
993 hdmi_enable_video_path(hdmi, edid->hdmi_monitor);
995 if (edid->hdmi_monitor) {
996 hdmi_audio_fifo_reset(hdmi);
997 hdmi_audio_set_format(hdmi);
998 hdmi_audio_set_samplerate(hdmi, edid->pixelclock.typ);
1001 hdmi_video_packetize(hdmi);
1002 hdmi_video_csc(hdmi);
1003 hdmi_video_sample(hdmi);
1005 hdmi_clear_overflow(hdmi);
1010 void dw_hdmi_init(struct dw_hdmi *hdmi)
1015 * boot up defaults are:
1016 * hdmi_ih_mute = 0x03 (disabled)
1017 * hdmi_ih_mute_* = 0x00 (enabled)
1019 * disable top level interrupt bits in hdmi block
1021 ih_mute = /*hdmi_read(hdmi, HDMI_IH_MUTE) |*/
1022 HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
1023 HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
1025 if (hdmi->write_reg)
1026 hdmi_write = hdmi->write_reg;
1029 hdmi_read = hdmi->read_reg;
1031 hdmi_write(hdmi, ih_mute, HDMI_IH_MUTE);
1033 /* enable i2c master done irq */
1034 hdmi_write(hdmi, ~0x04, HDMI_I2CM_INT);
1036 /* enable i2c client nack % arbitration error irq */
1037 hdmi_write(hdmi, ~0x44, HDMI_I2CM_CTLINT);