22 #include <linux/kernel.h>
23 #include <linux/module.h>
29 #include <linux/string.h>
32 #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
41 static inline void hdmi_write_reg(
void __iomem *base_addr,
47 static inline u32 hdmi_read_reg(
void __iomem *base_addr,
78 static inline int hdmi_wait_for_bit_change(
void __iomem *base_addr,
83 while (val !=
REG_GET(base_addr, idx, b2, b1)) {
94 void __iomem *pll_base = hdmi_pll_base(ip_data);
135 pr_err(
"PLL GO bit not set\n");
140 if (hdmi_wait_for_bit_change(pll_base,
142 pr_err(
"cannot lock PLL\n");
168 if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data),
170 pr_err(
"Failed to set PHY power mode to %d\n", val);
186 pr_err(
"Failed to set PLL_PWR_STATUS\n");
199 if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data),
201 pr_err(
"Failed to sysreset PLL\n");
220 r = hdmi_pll_reset(ip_data);
224 r = hdmi_pll_init(ip_data);
236 static int hdmi_check_hpd_state(
struct hdmi_ip_data *ip_data)
251 DSSERR(
"Failed to %s PHY TX power\n",
252 hpd ?
"enable" :
"disable");
265 hdmi_check_hpd_state(ip_data);
273 void __iomem *phy_base = hdmi_phy_base(ip_data);
301 NULL, hpd_irq_handler,
305 DSSERR(
"HPD IRQ request failed\n");
310 r = hdmi_check_hpd_state(ip_data);
327 static int hdmi_core_ddc_init(
struct hdmi_ip_data *ip_data)
341 DSSERR(
"Timeout aborting DDC transaction\n");
352 DSSERR(
"Timeout starting SCL clock\n");
362 DSSERR(
"Timeout clearing DDC fifo\n");
369 static int hdmi_core_ddc_edid(
struct hdmi_ip_data *ip_data,
372 void __iomem *base = hdmi_core_sys_base(ip_data);
380 DSSERR(
"Timeout waiting DDC to be ready\n");
417 for (i = 0; i < 0x80; ++
i) {
422 DSSERR(
"operation stopped when reading edid\n");
430 DSSERR(
"timeout reading edid\n");
440 for (i = 0; i < 0x80; ++
i)
441 checksum += pedid[i];
444 pr_err(
"E-EDID checksum failed!!\n");
459 r = hdmi_core_ddc_init(ip_data);
463 r = hdmi_core_ddc_edid(ip_data, edid, 0);
469 if (len >= 128 * 2 && edid[0x7e] > 0) {
470 r = hdmi_core_ddc_edid(ip_data, edid + 0x80, 1);
528 static void hdmi_core_powerdown_disable(
struct hdmi_ip_data *ip_data)
530 pr_debug(
"Enter hdmi_core_powerdown_disable\n");
534 static void hdmi_core_swreset_release(
struct hdmi_ip_data *ip_data)
536 pr_debug(
"Enter hdmi_core_swreset_release\n");
540 static void hdmi_core_swreset_assert(
struct hdmi_ip_data *ip_data)
542 pr_debug(
"Enter hdmi_core_swreset_assert\n");
551 void __iomem *core_sys_base = hdmi_core_sys_base(ip_data);
589 static void hdmi_core_aux_infoframe_avi_config(
struct hdmi_ip_data *ip_data)
592 char sum = 0, checksum = 0;
593 void __iomem *av_base = hdmi_av_base(ip_data);
596 sum += 0x82 + 0x002 + 0x00D;
614 val = (info_avi.
db3_itc << 7) |
661 checksum = 0x100 -
sum;
665 static void hdmi_core_av_packet_config(
struct hdmi_ip_data *ip_data,
696 video_fmt->
y_res = 0;
697 video_fmt->
x_res = 0;
715 pr_debug(
"Enter hdmi_wp_video_init_format\n");
728 static void hdmi_wp_video_config_format(
struct hdmi_ip_data *ip_data,
741 static void hdmi_wp_video_config_interface(
struct hdmi_ip_data *ip_data)
744 bool vsync_pol, hsync_pol;
745 pr_debug(
"Enter hdmi_wp_video_config_interface\n");
751 r =
FLD_MOD(r, vsync_pol, 7, 7);
752 r =
FLD_MOD(r, hsync_pol, 6, 6);
753 r =
FLD_MOD(r, ip_data->
cfg.timings.interlace, 3, 3);
758 static void hdmi_wp_video_config_timing(
struct hdmi_ip_data *ip_data,
764 pr_debug(
"Enter hdmi_wp_video_config_timing\n");
788 hdmi_wp_init(&video_timing, &video_format);
790 hdmi_core_init(&v_core_cfg,
794 hdmi_wp_video_init_format(&video_format, &video_timing, cfg);
796 hdmi_wp_video_config_timing(ip_data, &video_timing);
801 hdmi_wp_video_config_format(ip_data, &video_format);
803 hdmi_wp_video_config_interface(ip_data);
809 hdmi_core_swreset_assert(ip_data);
812 hdmi_core_powerdown_disable(ip_data);
820 hdmi_core_swreset_release(ip_data);
845 hdmi_core_aux_infoframe_avi_config(ip_data);
853 hdmi_core_av_packet_config(ip_data, repeat_cfg);
858 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r,\
859 hdmi_read_reg(hdmi_wp_base(ip_data), r))
880 #define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
881 hdmi_read_reg(hdmi_pll_base(ip_data), r))
896 #define CORE_REG(i, name) name(i)
897 #define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\
898 hdmi_read_reg(hdmi_core_sys_base(ip_data), r))
899 #define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\
900 hdmi_read_reg(hdmi_av_base(ip_data), r))
901 #define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
902 (i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \
903 hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r)))
1017 #define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\
1018 hdmi_read_reg(hdmi_phy_base(ip_data), r))
1026 #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
1027 static void ti_hdmi_4xxx_wp_audio_config_format(
struct hdmi_ip_data *ip_data,
1032 DSSDBG(
"Enter hdmi_wp_audio_config_format\n");
1046 static void ti_hdmi_4xxx_wp_audio_config_dma(
struct hdmi_ip_data *ip_data,
1051 DSSDBG(
"Enter hdmi_wp_audio_config_dma\n");
1064 static void ti_hdmi_4xxx_core_audio_config(
struct hdmi_ip_data *ip_data,
1068 void __iomem *av_base = hdmi_av_base(ip_data);
1143 cfg->
i2s_cfg.in_length_bits, 3, 0);
1163 static void ti_hdmi_4xxx_core_audio_infoframe_cfg(
struct hdmi_ip_data *ip_data,
1166 u8 sum = 0, checksum = 0;
1167 void __iomem *av_base = hdmi_av_base(ip_data);
1177 sum += 0x84 + 0x001 + 0x00a;
1188 sum += info_aud->
db3;
1203 checksum = 0x100 -
sum;
1204 hdmi_write_reg(av_base,
1213 int ti_hdmi_4xxx_audio_config(
struct hdmi_ip_data *ip_data,
1221 bool word_length_16b =
false;
1223 if (!audio || !audio->
iec || !audio->
cea || !ip_data)
1226 core.iec60958_cfg = audio->
iec;
1233 word_length_16b =
true;
1236 if (word_length_16b)
1245 core.i2s_cfg.in_length_bits = audio->
iec->status[4]
1248 core.i2s_cfg.in_length_bits++;
1281 err = hdmi_compute_acr(fs_nr, &n, &cts);
1287 core.aud_par_busclk = 0;
1291 core.aud_par_busclk = (((128 * 31) - 1) << 8);
1293 core.use_mclk =
true;
1300 channel_count = (audio->
cea->db1_ct_cc &
1303 switch (channel_count) {
1305 audio_format.active_chnnls_msk = 0x03;
1308 audio_format.active_chnnls_msk = 0x07;
1311 audio_format.active_chnnls_msk = 0x0f;
1314 audio_format.active_chnnls_msk = 0x1f;
1317 audio_format.active_chnnls_msk = 0x3f;
1320 audio_format.active_chnnls_msk = 0x7f;
1323 audio_format.active_chnnls_msk = 0xff;
1333 if (channel_count == 2) {
1345 core.en_spdif =
false;
1347 core.fs_override =
true;
1349 core.en_acr_pkt =
true;
1351 core.en_dsd_audio =
false;
1353 core.en_parallel_aud_input =
true;
1356 if (word_length_16b)
1357 audio_dma.transfer_size = 0x10;
1359 audio_dma.transfer_size = 0x20;
1360 audio_dma.block_size = 0xC0;
1362 audio_dma.fifo_threshold = 0x20;
1365 if (word_length_16b) {
1380 ti_hdmi_4xxx_wp_audio_config_dma(ip_data, &audio_dma);
1381 ti_hdmi_4xxx_wp_audio_config_format(ip_data, &audio_format);
1384 ti_hdmi_4xxx_core_audio_config(ip_data, &
core);
1387 ti_hdmi_4xxx_core_audio_infoframe_cfg(ip_data, audio->
cea);
1392 int ti_hdmi_4xxx_wp_audio_enable(
struct hdmi_ip_data *ip_data)
1399 void ti_hdmi_4xxx_wp_audio_disable(
struct hdmi_ip_data *ip_data)
1405 int ti_hdmi_4xxx_audio_start(
struct hdmi_ip_data *ip_data)
1414 void ti_hdmi_4xxx_audio_stop(
struct hdmi_ip_data *ip_data)