ASoC: rt722: fix pop noise at the beginning of headphone playback

This patch added the function_status check to avoid the calibration again.
The codec driver reinitializes when the 'FUNCTION_NEEDS_INITIALIZATION' flag raises.

Signed-off-by: Shuming Fan <shumingf@realtek.com>
Link: https://patch.msgid.link/20250416092528.737845-1-shumingf@realtek.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Shuming Fan 2025-04-16 17:25:28 +08:00 committed by Mark Brown
parent d1965f008f
commit 91f4ca7324
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
3 changed files with 176 additions and 122 deletions

View File

@ -24,6 +24,7 @@ static int rt722_sdca_mbq_size(struct device *dev, unsigned int reg)
case 0x2f50:
case 0x2f54:
case 0x2f58 ... 0x2f5d:
case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0):
case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_GE49, RT722_SDCA_CTL_SELECTED_MODE,
0):
case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_GE49, RT722_SDCA_CTL_DETECTED_MODE,
@ -56,6 +57,7 @@ static int rt722_sdca_mbq_size(struct device *dev, unsigned int reg)
RT722_SDCA_CTL_VENDOR_DEF, 0):
case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_PDE2A,
RT722_SDCA_CTL_REQ_POWER_STATE, 0):
case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0):
case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_CS1F,
RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0):
case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01,
@ -70,6 +72,7 @@ static int rt722_sdca_mbq_size(struct device *dev, unsigned int reg)
RT722_SDCA_CTL_VENDOR_DEF, CH_08):
case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_PDE23,
RT722_SDCA_CTL_REQ_POWER_STATE, 0):
case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0):
case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_CS31,
RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0):
case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2:
@ -150,11 +153,14 @@ static bool rt722_sdca_volatile_register(struct device *dev, unsigned int reg)
switch (reg) {
case 0x2f01:
case 0x2f54:
case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0):
case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_GE49, RT722_SDCA_CTL_DETECTED_MODE,
0):
case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0):
case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, RT722_SDCA_CTL_HIDTX_CURRENT_OWNER,
0) ... SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01,
RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0):
case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0):
case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2:
case 0x2000000:
case 0x200000d:
@ -166,6 +172,8 @@ static bool rt722_sdca_volatile_register(struct device *dev, unsigned int reg)
case 0x2000084:
case 0x2000086:
case 0x3110000:
case 0x5800003:
case 0x5810000:
return true;
default:
return false;

View File

@ -1302,140 +1302,181 @@ int rt722_sdca_init(struct device *dev, struct regmap *regmap, struct sdw_slave
static void rt722_sdca_dmic_preset(struct rt722_sdca_priv *rt722)
{
/* Set AD07 power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_ADC0A_08_PDE_FLOAT_CTL, 0x2a29);
/* Set AD10 power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_ADC10_PDE_FLOAT_CTL, 0x2a00);
/* Set DMIC1/DMIC2 power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_DMIC1_2_PDE_FLOAT_CTL, 0x2a2a);
/* Set DMIC2 IT entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_DMIC_ENT_FLOAT_CTL, 0x2626);
/* Set AD10 FU entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_ADC_ENT_FLOAT_CTL, 0x1e00);
/* Set DMIC2 FU entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_DMIC_GAIN_ENT_FLOAT_CTL0, 0x1515);
/* Set AD10 FU channel floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_ADC_VOL_CH_FLOAT_CTL, 0x0304);
/* Set DMIC2 FU channel floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_DMIC_GAIN_ENT_FLOAT_CTL2, 0x0304);
/* vf71f_r12_07_06 and vf71f_r13_07_06 = 2b00 */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_HDA_LEGACY_CONFIG_CTL0, 0x0000);
/* Enable vf707_r12_05/vf707_r13_05 */
regmap_write(rt722->regmap,
SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_IT26,
RT722_SDCA_CTL_VENDOR_DEF, 0), 0x01);
/* Fine tune PDE2A latency */
regmap_write(rt722->regmap, 0x2f5c, 0x25);
unsigned int mic_func_status;
struct device *dev = &rt722->slave->dev;
regmap_read(rt722->regmap,
SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0), &mic_func_status);
dev_dbg(dev, "%s mic func_status=0x%x\n", __func__, mic_func_status);
if ((mic_func_status & FUNCTION_NEEDS_INITIALIZATION) || (!rt722->first_hw_init)) {
/* Set AD07 power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_ADC0A_08_PDE_FLOAT_CTL, 0x2a29);
/* Set AD10 power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_ADC10_PDE_FLOAT_CTL, 0x2a00);
/* Set DMIC1/DMIC2 power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_DMIC1_2_PDE_FLOAT_CTL, 0x2a2a);
/* Set DMIC2 IT entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_DMIC_ENT_FLOAT_CTL, 0x2626);
/* Set AD10 FU entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_ADC_ENT_FLOAT_CTL, 0x1e00);
/* Set DMIC2 FU entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_DMIC_GAIN_ENT_FLOAT_CTL0, 0x1515);
/* Set AD10 FU channel floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_ADC_VOL_CH_FLOAT_CTL, 0x0304);
/* Set DMIC2 FU channel floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_DMIC_GAIN_ENT_FLOAT_CTL2, 0x0304);
/* vf71f_r12_07_06 and vf71f_r13_07_06 = 2b00 */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL,
RT722_HDA_LEGACY_CONFIG_CTL0, 0x0000);
/* Enable vf707_r12_05/vf707_r13_05 */
regmap_write(rt722->regmap,
SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_IT26,
RT722_SDCA_CTL_VENDOR_DEF, 0), 0x01);
/* Fine tune PDE2A latency */
regmap_write(rt722->regmap, 0x2f5c, 0x25);
/* clear flag */
regmap_write(rt722->regmap,
SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0),
FUNCTION_NEEDS_INITIALIZATION);
}
}
static void rt722_sdca_amp_preset(struct rt722_sdca_priv *rt722)
{
/* Set DVQ=01 */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_CLSD_CTRL6,
0xc215);
/* Reset dc_cal_top */
rt722_sdca_index_write(rt722, RT722_VENDOR_CALI, RT722_DC_CALIB_CTRL,
0x702c);
/* W1C Trigger Calibration */
rt722_sdca_index_write(rt722, RT722_VENDOR_CALI, RT722_DC_CALIB_CTRL,
0xf02d);
/* Set DAC02/ClassD power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_AMP_PDE_FLOAT_CTL,
0x2323);
/* Set EAPD high */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_EAPD_CTL,
0x0002);
/* Enable vf707_r14 */
regmap_write(rt722->regmap,
SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_OT23,
RT722_SDCA_CTL_VENDOR_DEF, CH_08), 0x04);
unsigned int amp_func_status;
struct device *dev = &rt722->slave->dev;
regmap_read(rt722->regmap,
SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0), &amp_func_status);
dev_dbg(dev, "%s amp func_status=0x%x\n", __func__, amp_func_status);
if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION) || (!rt722->first_hw_init)) {
/* Set DVQ=01 */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_CLSD_CTRL6,
0xc215);
/* Reset dc_cal_top */
rt722_sdca_index_write(rt722, RT722_VENDOR_CALI, RT722_DC_CALIB_CTRL,
0x702c);
/* W1C Trigger Calibration */
rt722_sdca_index_write(rt722, RT722_VENDOR_CALI, RT722_DC_CALIB_CTRL,
0xf02d);
/* Set DAC02/ClassD power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_AMP_PDE_FLOAT_CTL,
0x2323);
/* Set EAPD high */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_EAPD_CTL,
0x0002);
/* Enable vf707_r14 */
regmap_write(rt722->regmap,
SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_OT23,
RT722_SDCA_CTL_VENDOR_DEF, CH_08), 0x04);
/* clear flag */
regmap_write(rt722->regmap,
SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0),
FUNCTION_NEEDS_INITIALIZATION);
}
}
static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
{
int loop_check, chk_cnt = 100, ret;
unsigned int calib_status = 0;
unsigned int jack_func_status;
struct device *dev = &rt722->slave->dev;
/* Config analog bias */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_ANALOG_BIAS_CTL3,
0xa081);
/* GE related settings */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_GE_RELATED_CTL2,
0xa009);
/* Button A, B, C, D bypass mode */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_UMP_HID_CTL4,
0xcf00);
/* HID1 slot enable */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_UMP_HID_CTL5,
0x000f);
/* Report ID for HID1 */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_UMP_HID_CTL0,
0x1100);
/* OSC/OOC for slot 2, 3 */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_UMP_HID_CTL7,
0x0c12);
/* Set JD de-bounce clock control */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_JD_CTRL1,
0x7002);
/* Set DVQ=01 */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_CLSD_CTRL6,
0xc215);
/* FSM switch to calibration manual mode */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_FSM_CTL,
0x4100);
/* W1C Trigger DC calibration (HP) */
rt722_sdca_index_write(rt722, RT722_VENDOR_CALI, RT722_DAC_DC_CALI_CTL3,
0x008d);
/* check HP calibration FSM status */
for (loop_check = 0; loop_check < chk_cnt; loop_check++) {
usleep_range(10000, 11000);
ret = rt722_sdca_index_read(rt722, RT722_VENDOR_CALI,
RT722_DAC_DC_CALI_CTL3, &calib_status);
if (ret < 0)
dev_dbg(&rt722->slave->dev, "calibration failed!, ret=%d\n", ret);
if ((calib_status & 0x0040) == 0x0)
break;
regmap_read(rt722->regmap,
SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0), &jack_func_status);
dev_dbg(dev, "%s jack func_status=0x%x\n", __func__, jack_func_status);
if ((jack_func_status & FUNCTION_NEEDS_INITIALIZATION) || (!rt722->first_hw_init)) {
/* Config analog bias */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_ANALOG_BIAS_CTL3,
0xa081);
/* GE related settings */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_GE_RELATED_CTL2,
0xa009);
/* Button A, B, C, D bypass mode */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_UMP_HID_CTL4,
0xcf00);
/* HID1 slot enable */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_UMP_HID_CTL5,
0x000f);
/* Report ID for HID1 */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_UMP_HID_CTL0,
0x1100);
/* OSC/OOC for slot 2, 3 */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_UMP_HID_CTL7,
0x0c12);
/* Set JD de-bounce clock control */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_JD_CTRL1,
0x7002);
/* Set DVQ=01 */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_CLSD_CTRL6,
0xc215);
/* FSM switch to calibration manual mode */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_FSM_CTL,
0x4100);
/* W1C Trigger DC calibration (HP) */
rt722_sdca_index_write(rt722, RT722_VENDOR_CALI, RT722_DAC_DC_CALI_CTL3,
0x008d);
/* check HP calibration FSM status */
for (loop_check = 0; loop_check < chk_cnt; loop_check++) {
usleep_range(10000, 11000);
ret = rt722_sdca_index_read(rt722, RT722_VENDOR_CALI,
RT722_DAC_DC_CALI_CTL3, &calib_status);
if (ret < 0)
dev_dbg(&rt722->slave->dev, "calibration failed!, ret=%d\n", ret);
if ((calib_status & 0x0040) == 0x0)
break;
}
if (loop_check == chk_cnt)
dev_dbg(&rt722->slave->dev, "%s, calibration time-out!\n", __func__);
/* Set ADC09 power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ADC0A_08_PDE_FLOAT_CTL,
0x2a12);
/* Set MIC2 and LINE1 power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_MIC2_LINE2_PDE_FLOAT_CTL,
0x3429);
/* Set ET41h and LINE2 power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ET41_LINE2_PDE_FLOAT_CTL,
0x4112);
/* Set DAC03 and HP power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_DAC03_HP_PDE_FLOAT_CTL,
0x4040);
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ENT_FLOAT_CTRL_1,
0x4141);
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_FLOAT_CTRL_1,
0x0101);
/* Fine tune PDE40 latency */
regmap_write(rt722->regmap, 0x2f58, 0x07);
regmap_write(rt722->regmap, 0x2f03, 0x06);
/* MIC VRefo */
rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
RT722_COMBO_JACK_AUTO_CTL1, 0x0200, 0x0200);
rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
RT722_VREFO_GAT, 0x4000, 0x4000);
/* Release HP-JD, EN_CBJ_TIE_GL/R open, en_osw gating auto done bit */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_DIGITAL_MISC_CTRL4,
0x0010);
/* clear flag */
regmap_write(rt722->regmap,
SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0),
FUNCTION_NEEDS_INITIALIZATION);
}
if (loop_check == chk_cnt)
dev_dbg(&rt722->slave->dev, "%s, calibration time-out!\n", __func__);
/* Set ADC09 power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ADC0A_08_PDE_FLOAT_CTL,
0x2a12);
/* Set MIC2 and LINE1 power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_MIC2_LINE2_PDE_FLOAT_CTL,
0x3429);
/* Set ET41h and LINE2 power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ET41_LINE2_PDE_FLOAT_CTL,
0x4112);
/* Set DAC03 and HP power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_DAC03_HP_PDE_FLOAT_CTL,
0x4040);
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ENT_FLOAT_CTRL_1,
0x4141);
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_FLOAT_CTRL_1,
0x0101);
/* Fine tune PDE40 latency */
regmap_write(rt722->regmap, 0x2f58, 0x07);
regmap_write(rt722->regmap, 0x2f03, 0x06);
/* MIC VRefo */
rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
RT722_COMBO_JACK_AUTO_CTL1, 0x0200, 0x0200);
rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
RT722_VREFO_GAT, 0x4000, 0x4000);
/* Release HP-JD, EN_CBJ_TIE_GL/R open, en_osw gating auto done bit */
rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_DIGITAL_MISC_CTRL4,
0x0010);
}
int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave)

View File

@ -183,6 +183,7 @@ struct rt722_sdca_dmic_kctrl_priv {
#define RT722_SDCA_ENT_PLATFORM_FU44 0x44
#define RT722_SDCA_ENT_XU03 0x03
#define RT722_SDCA_ENT_XU0D 0x0d
#define RT722_SDCA_ENT0 0x00
/* RT722 SDCA control */
#define RT722_SDCA_CTL_SAMPLE_FREQ_INDEX 0x10
@ -197,6 +198,7 @@ struct rt722_sdca_dmic_kctrl_priv {
#define RT722_SDCA_CTL_REQ_POWER_STATE 0x01
#define RT722_SDCA_CTL_VENDOR_DEF 0x30
#define RT722_SDCA_CTL_FU_CH_GAIN 0x0b
#define RT722_SDCA_CTL_FUNC_STATUS 0x10
/* RT722 SDCA channel */
#define CH_L 0x01
@ -215,6 +217,9 @@ struct rt722_sdca_dmic_kctrl_priv {
#define RT722_SDCA_RATE_96000HZ 0x0b
#define RT722_SDCA_RATE_192000HZ 0x0d
/* Function_Status */
#define FUNCTION_NEEDS_INITIALIZATION BIT(5)
enum {
RT722_AIF1, /* For headset mic and headphone */
RT722_AIF2, /* For speaker */