diff --git a/drivers/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index 48b850fba..f1a060f7d 100644 --- a/drivers/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -5953,15 +5953,19 @@ static int hdmitx_notify_callback_a(struct notifier_block *block, hdev->audio_notify_flag = 0; if (hdmitx_set_i2s_mask(aud_param->chs, aud_param->i2s_ch_mask)) hdev->audio_param_update_flag = 1; - pr_info("%s[%d] type:%d rate:%d size:%d chs:%d fifo_rst:%d aud_src_if:%d\n", - __func__, __LINE__, aud_param->type, aud_param->rate, aud_param->size, + pr_info("%s[%d] type:%lu rate:%d size:%d chs:%d fifo_rst:%d aud_src_if:%d\n", + __func__, __LINE__, cmd, n_rate, n_size, aud_param->chs, aud_param->fifo_rst, aud_param->aud_src_if); if (audio_param->sample_rate != n_rate) { + /* if the audio sample rate or type changes, stop ACR firstly */ + hdev->tx_hw.cntlmisc(&hdev->tx_hw, MISC_AUDIO_ACR_CTRL, 0); audio_param->sample_rate = n_rate; hdev->audio_param_update_flag = 1; } if (audio_param->type != cmd) { + /* if the audio sample rate or type changes, stop ACR firstly */ + hdev->tx_hw.cntlmisc(&hdev->tx_hw, MISC_AUDIO_ACR_CTRL, 0); audio_param->type = cmd; pr_info(AUD "aout notify format %s\n", aud_type_string[audio_param->type & 0xff]); @@ -6003,7 +6007,9 @@ static int hdmitx_notify_callback_a(struct notifier_block *block, hdev->audio_param_update_flag) { /* plug-in & update audio param */ if (hdev->tx_comm.hpd_state == 1) { + hdev->aud_notify_update = 1; hdmitx_set_audio(hdev, &hdev->cur_audio_param); + hdev->aud_notify_update = 0; if (hdev->audio_notify_flag == 1 || hdev->audio_step == 1) { hdev->audio_notify_flag = 0; diff --git a/drivers/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c b/drivers/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c index ae996e686..151111dcd 100644 --- a/drivers/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c +++ b/drivers/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c @@ -2656,12 +2656,13 @@ static void set_aud_info_pkt(struct hdmitx_dev *hdev, hdmitx_wr_reg(HDMITX_DWC_FC_AUDICONF3, 0); } -static void set_aud_acr_pkt(struct hdmitx_dev *hdev, +static int set_aud_acr_pkt(struct hdmitx_dev *hdev, struct hdmitx_audpara *audio_param) { unsigned int data32; unsigned int aud_n_para; unsigned int char_rate; + static unsigned int pre_aud_n_para; /* audio packetizer config */ hdmitx_wr_reg(HDMITX_DWC_AUD_INPUTCLKFS, audio_param->aud_src_if ? 4 : 0); @@ -2688,7 +2689,6 @@ static void set_aud_acr_pkt(struct hdmitx_dev *hdev, default: break; } - pr_info(HW "aud_n_para = %d\n", aud_n_para); /* ACR packet configuration */ data32 = 0; @@ -2708,10 +2708,19 @@ static void set_aud_acr_pkt(struct hdmitx_dev *hdev, data32 = 0; data32 |= (1 << 7); /* [ 7] ncts_atomic_write */ data32 |= (((aud_n_para >> 16) & 0xf) << 0); /* [3:0] AudN[19:16] */ + /* if only audio module update and previous n_para is same as current + * value, then skip update audio_n_para + */ + if (hdev->aud_notify_update && pre_aud_n_para == aud_n_para) + return 0; + /* update audio_n_para */ + pre_aud_n_para = aud_n_para; hdmitx_wr_reg(HDMITX_DWC_AUD_N3, data32); hdmitx_wr_reg(HDMITX_DWC_AUD_N2, (aud_n_para >> 8) & 0xff); /* AudN[15:8] */ hdmitx_wr_reg(HDMITX_DWC_AUD_N1, aud_n_para & 0xff); /* AudN[7:0] */ + pr_info("update audio N %d", aud_n_para); + return 1; } static void set_aud_fifo_rst(void) @@ -2815,6 +2824,7 @@ static int hdmitx_set_audmode(struct hdmitx_dev *hdev, struct hdmitx_audpara *audio_param) { unsigned int data32; + int acr_update = 0; if (!hdev) return 0; @@ -2892,7 +2902,7 @@ static int hdmitx_set_audmode(struct hdmitx_dev *hdev, hdmitx_wr_reg(HDMITX_DWC_AUD_SPDIF0, data32); set_aud_info_pkt(hdev, audio_param); - set_aud_acr_pkt(hdev, audio_param); + acr_update = set_aud_acr_pkt(hdev, audio_param); set_aud_samp_pkt(hdev, audio_param); set_aud_chnls(hdev, audio_param); @@ -2911,20 +2921,13 @@ static int hdmitx_set_audmode(struct hdmitx_dev *hdev, /* Wait for 40 us for TX I2S decoder to settle */ msleep(20); } - data32 = hdmitx_rd_reg(HDMITX_DWC_FC_PACKET_TX_EN); - pr_debug(HW "[0x10e3] = 0x%x\n", data32); set_aud_fifo_rst(); usleep_range(9, 11); - hdmitx_wr_reg(HDMITX_DWC_AUD_N1, hdmitx_rd_reg(HDMITX_DWC_AUD_N1)); - /* double confirm that ACR packet is enabled - * simultaneously with audio sample packet - */ - data32 = hdmitx_rd_reg(HDMITX_DWC_FC_PACKET_TX_EN); - if ((data32 & 0x9) == 0x8) { - hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 1, 0, 1); - pr_debug(HW "enable ACR: [0x10e3] = 0x%x\n", data32); - } + if (acr_update) + hdmitx_wr_reg(HDMITX_DWC_AUD_N1, hdmitx_rd_reg(HDMITX_DWC_AUD_N1)); hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO3, 1, 0, 1); + usleep_range(4000, 5000); + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 1, 0, 1); mutex_unlock(&aud_mutex); return 1; @@ -5940,6 +5943,12 @@ static int hdmitx_cntl_misc(struct hdmitx_hw_common *tx_hw, unsigned int cmd, hd_set_reg_bits(pll_cntl, 0, 30, 1); } break; + case MISC_AUDIO_ACR_CTRL: + if (argv == 0) + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 0, 0, 1); + if (argv == 1) + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 1, 0, 1); + break; default: break; } diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h index 694049799..7a7d20ba2 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h @@ -407,6 +407,11 @@ struct hdmitx_dev { enum eotf_type hdmi_current_eotf_type; enum mode_type hdmi_current_tunnel_mode; bool hdmi_current_signal_sdr; + /* if switching from 48k pcm to 48k DD, the ACR/N parameter is same, + * so there is no need to update ACR/N. but for mode change, different + * sample rate, need to update ACR/N. + */ + bool aud_notify_update; unsigned int flag_3dfp:1; unsigned int flag_3dtb:1; unsigned int flag_3dss:1; diff --git a/include/linux/amlogic/media/vout/hdmitx_common/hdmitx_hw_common.h b/include/linux/amlogic/media/vout/hdmitx_common/hdmitx_hw_common.h index e28314de9..4d2b7b9bd 100644 --- a/include/linux/amlogic/media/vout/hdmitx_common/hdmitx_hw_common.h +++ b/include/linux/amlogic/media/vout/hdmitx_common/hdmitx_hw_common.h @@ -58,6 +58,7 @@ #define MISC_SUSFLAG (CMD_MISC_OFFSET + 0X15) #define MISC_AUDIO_RESET (CMD_MISC_OFFSET + 0x16) #define MISC_DIS_HPLL (CMD_MISC_OFFSET + 0x17) +#define MISC_AUDIO_ACR_CTRL (CMD_MISC_OFFSET + 0x18) /*********************************************************************** * Get State //getstate