mirror of
https://github.com/hardkernel/kernel_common_drivers.git
synced 2026-06-25 12:03:48 +09:00
hdmitx: fix a special no audio output case [1/1]
PD#SWPL-117332 PD#OTT-39191 BUG=266994705 Problem: The HDMI audio ACR parameter will change when audio format change. In this intermediate state, some TVset like Vizio has audio compliance issue and maybe the error correction or handling mechanism of tvset can not cover such kind of glitch data. It will cause no audio output issue for such kind of tvset Solution: From tx side, optimize the intermediate state. In the beginning of audio format change, stop the ACR package send, continue ACR package sending after finish format changing. Meanwhile, only change the ACR related param when setting is difference compared with previous one from audio module callback Verify: issue Vizio TV and other brand TVset in our hand Change-Id: I739acba93590ba4c02c0b4a3f50319fa16ea42cf Signed-off-by: Zongdong Jiao <zongdong.jiao@amlogic.com>
This commit is contained in:
committed by
gerrit autosubmit
parent
7d5a856a25
commit
3a18e69dfe
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user