mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-10-31 18:09:19 +00:00
Merge "ASoC: wsa: add support for WSA 2.0 version and sequences"
This commit is contained in:
commit
ad2908ab59
5 changed files with 317 additions and 64 deletions
|
@ -62,6 +62,7 @@ struct wsa881x_pdata {
|
|||
struct wsa881x_tz_priv tz_pdata;
|
||||
int bg_cnt;
|
||||
int clk_cnt;
|
||||
int version;
|
||||
struct mutex bg_lock;
|
||||
struct mutex res_lock;
|
||||
};
|
||||
|
@ -338,22 +339,66 @@ static int wsa881x_i2c_get_client_index(struct i2c_client *client,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int wsa881x_temp_sensor_ctrl(struct snd_soc_codec *codec, bool enable)
|
||||
{
|
||||
dev_dbg(codec->dev, "%s: enable:%d\n", __func__, enable);
|
||||
snd_soc_update_bits(codec, WSA881X_TEMP_OP, (0x01 << 2),
|
||||
(enable << 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa881x_boost_ctrl(struct snd_soc_codec *codec, bool enable)
|
||||
{
|
||||
struct wsa881x_pdata *wsa881x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
pr_debug("%s: enable:%d\n", __func__, enable);
|
||||
if (enable) {
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL, 0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL, 0x04, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PS_CTL, 0x40, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PRESET_OUT1,
|
||||
0xF0, 0xB0);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_ZX_CTL, 0x20, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_EN_CTL, 0x80, 0x80);
|
||||
if (!WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL,
|
||||
0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL,
|
||||
0x04, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PS_CTL,
|
||||
0x40, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PRESET_OUT1,
|
||||
0xF0, 0xB0);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_ZX_CTL,
|
||||
0x20, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_EN_CTL,
|
||||
0x80, 0x80);
|
||||
} else {
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_LOOP_STABILITY,
|
||||
0x03, 0x03);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_MISC2_CTL,
|
||||
0xFF, 0x14);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_START_CTL,
|
||||
0x80, 0x80);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_START_CTL,
|
||||
0x03, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
WSA881X_BOOST_SLOPE_COMP_ISENSE_FB,
|
||||
0x0C, 0x04);
|
||||
snd_soc_update_bits(codec,
|
||||
WSA881X_BOOST_SLOPE_COMP_ISENSE_FB,
|
||||
0x03, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PRESET_OUT1,
|
||||
0xF0, 0x70);
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL, 0x03, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN,
|
||||
0x08, 0x08);
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL, 0x04, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_CURRENT_LIMIT,
|
||||
0x0F, 0x08);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_EN_CTL,
|
||||
0x80, 0x80);
|
||||
}
|
||||
/* For WSA8810, start-up time is 1500us as per qcrg sequence */
|
||||
usleep_range(1500, 1510);
|
||||
} else {
|
||||
/* ENSURE: Class-D amp is shutdown. CLK is still on */
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_EN_CTL, 0x80, 0x00);
|
||||
/* boost settle time is 1500us as per qcrg sequence */
|
||||
usleep_range(1500, 1510);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -363,17 +408,30 @@ static int wsa881x_visense_txfe_ctrl(struct snd_soc_codec *codec, bool enable,
|
|||
u8 vsense_gain)
|
||||
{
|
||||
u8 value = 0;
|
||||
struct wsa881x_pdata *wsa881x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
pr_debug("%s: enable:%d\n", __func__, enable);
|
||||
|
||||
if (enable) {
|
||||
if (WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_OTP_REG_28,
|
||||
0x3F, 0x3A);
|
||||
snd_soc_update_bits(codec, WSA881X_BONGO_RESRV_REG1,
|
||||
0xFF, 0xB2);
|
||||
snd_soc_update_bits(codec, WSA881X_BONGO_RESRV_REG2,
|
||||
0xFF, 0x05);
|
||||
}
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_FE_VSENSE_VCM,
|
||||
0x08, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x08, 0x08);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x02, 0x02);
|
||||
|
||||
if (WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x1C, 0x04);
|
||||
} else {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x08, 0x08);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x02, 0x02);
|
||||
}
|
||||
value = ((isense2_gain << 6) | (isense1_gain << 4) |
|
||||
(vsense_gain << 3));
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_FE_GAIN,
|
||||
|
@ -381,8 +439,12 @@ static int wsa881x_visense_txfe_ctrl(struct snd_soc_codec *codec, bool enable,
|
|||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_FE_GAIN,
|
||||
0x01, 0x01);
|
||||
} else {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_FE_VSENSE_VCM,
|
||||
0x08, 0x08);
|
||||
if (WSA881X_IS_2_0(wsa881x->version))
|
||||
snd_soc_update_bits(codec,
|
||||
WSA881X_SPKR_PROT_FE_VSENSE_VCM, 0x10, 0x10);
|
||||
else
|
||||
snd_soc_update_bits(codec,
|
||||
WSA881X_SPKR_PROT_FE_VSENSE_VCM, 0x08, 0x08);
|
||||
/*
|
||||
* 200us sleep is needed after visense txfe disable as per
|
||||
* HW requirement.
|
||||
|
@ -397,9 +459,13 @@ static int wsa881x_visense_txfe_ctrl(struct snd_soc_codec *codec, bool enable,
|
|||
|
||||
static int wsa881x_visense_adc_ctrl(struct snd_soc_codec *codec, bool enable)
|
||||
{
|
||||
struct wsa881x_pdata *wsa881x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
pr_debug("%s: enable:%d\n", __func__, enable);
|
||||
if (enable) {
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_SEL_IBIAS, 0x70, 0x40);
|
||||
if (!WSA881X_IS_2_0(wsa881x->version))
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_SEL_IBIAS,
|
||||
0x70, 0x40);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_SEL_IBIAS,
|
||||
0x07, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_MODU_V, 0x80, 0x80);
|
||||
|
@ -460,8 +526,11 @@ static void wsa881x_clk_ctrl(struct snd_soc_codec *codec, bool enable)
|
|||
if (wsa881x->clk_cnt <= 0) {
|
||||
WARN_ON(wsa881x->clk_cnt < 0);
|
||||
wsa881x->clk_cnt = 0;
|
||||
snd_soc_write(codec, WSA881X_CDC_DIG_CLK_CTL, 0x00);
|
||||
snd_soc_write(codec, WSA881X_CDC_ANA_CLK_CTL, 0x00);
|
||||
snd_soc_write(codec, WSA881X_CDC_DIG_CLK_CTL, 0x00);
|
||||
if (WSA881X_IS_2_0(wsa881x->version))
|
||||
snd_soc_update_bits(codec,
|
||||
WSA881X_CDC_TOP_CLK_CTL, 0x01, 0x00);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&wsa881x->res_lock);
|
||||
|
@ -469,6 +538,8 @@ static void wsa881x_clk_ctrl(struct snd_soc_codec *codec, bool enable)
|
|||
|
||||
static int wsa881x_rdac_ctrl(struct snd_soc_codec *codec, bool enable)
|
||||
{
|
||||
struct wsa881x_pdata *wsa881x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
pr_debug("%s: enable:%d\n", __func__, enable);
|
||||
if (enable) {
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL, 0x08, 0x00);
|
||||
|
@ -477,18 +548,26 @@ static int wsa881x_rdac_ctrl(struct snd_soc_codec *codec, bool enable)
|
|||
snd_soc_update_bits(codec, WSA881X_SPKR_DAC_CTL, 0x20, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DAC_CTL, 0x40, 0x40);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DAC_CTL, 0x80, 0x80);
|
||||
if (WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_CAL,
|
||||
0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_OCP_CTL,
|
||||
0x30, 0x30);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_OCP_CTL,
|
||||
0x0C, 0x00);
|
||||
}
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_GAIN, 0xF0, 0x40);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0x01, 0x01);
|
||||
} else {
|
||||
/* Ensure class-D amp is off */
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DAC_CTL, 0x80, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DAC_CTL, 0x40, 0x00);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa881x_spkr_pa_ctrl(struct snd_soc_codec *codec, bool enable)
|
||||
{
|
||||
int ret = 0;
|
||||
struct wsa881x_pdata *wsa881x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
pr_debug("%s: enable:%d\n", __func__, enable);
|
||||
|
@ -497,44 +576,72 @@ static int wsa881x_spkr_pa_ctrl(struct snd_soc_codec *codec, bool enable)
|
|||
* Ensure: Boost is enabled and stable, Analog input is up
|
||||
* and outputting silence
|
||||
*/
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_I,
|
||||
if (!WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_I,
|
||||
0xFF, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_MODU_V, 0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_V,
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_MODU_V,
|
||||
0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_V,
|
||||
0xFF, 0x10);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PWRSTG_DBG, 0xA0, 0xA0);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN, 0x80, 0x80);
|
||||
usleep_range(700, 710);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PWRSTG_DBG, 0x00, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_V,
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PWRSTG_DBG,
|
||||
0xA0, 0xA0);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN,
|
||||
0x80, 0x80);
|
||||
usleep_range(700, 710);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PWRSTG_DBG,
|
||||
0x00, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_V,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_MODU_V, 0x02, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_I,
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_MODU_V,
|
||||
0x02, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_I,
|
||||
0xFF, 0x00);
|
||||
} else
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN,
|
||||
0x80, 0x80);
|
||||
/* add 1000us delay as per qcrg */
|
||||
usleep_range(1000, 1010);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN, 0x01, 0x01);
|
||||
if (WSA881X_IS_2_0(wsa881x->version))
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_CAL,
|
||||
0x01, 0x00);
|
||||
usleep_range(1000, 1010);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_GAIN, 0xF0,
|
||||
(wsa881x->spk_pa_gain << 4));
|
||||
if (wsa881x->visense_enable) {
|
||||
ret = msm_gpioset_activate(CLIENT_WSA_BONGO_1,
|
||||
"wsa_vi");
|
||||
if (ret) {
|
||||
pr_err("%s: gpio set cannot be activated %s\n",
|
||||
__func__, "wsa_vi");
|
||||
return ret;
|
||||
}
|
||||
wsa881x_visense_txfe_ctrl(codec, true,
|
||||
0x00, 0x01, 0x00);
|
||||
wsa881x_visense_adc_ctrl(codec, true);
|
||||
wsa881x_temp_sensor_ctrl(codec, true);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Ensure: Boost is still on, Stream from Analog input and
|
||||
* Speaker Protection has been stopped and input is at 0V
|
||||
*/
|
||||
if (WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_CAL,
|
||||
0x01, 0x01);
|
||||
usleep_range(1000, 1010);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_CAL,
|
||||
0x01, 0x00);
|
||||
msleep(20);
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL,
|
||||
0x03, 0x00);
|
||||
usleep_range(200, 210);
|
||||
}
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN, 0x80, 0x00);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa881x_temp_sensor_ctrl(struct snd_soc_codec *codec, bool enable)
|
||||
{
|
||||
dev_dbg(codec->dev, "%s: enable:%d\n", __func__, enable);
|
||||
snd_soc_update_bits(codec, WSA881X_TEMP_OP, (0x01 << 2),
|
||||
(enable << 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa881x_get_boost(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
|
@ -623,44 +730,39 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w,
|
|||
pr_err("%s: wsa startup failed ret: %d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
snd_soc_update_bits(codec, WSA881X_CDC_RST_CTL, 0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_CDC_RST_CTL, 0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_CLOCK_CONFIG, 0x01, 0x01);
|
||||
wsa881x_clk_ctrl(codec, true);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DAC_CTL, 0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_CDC_DIG_CLK_CTL, 0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_CDC_ANA_CLK_CTL, 0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_BIAS_REF_CTRL, 0x0F, 0x08);
|
||||
if (!WSA881X_IS_2_0(wsa881x->version))
|
||||
snd_soc_update_bits(codec, WSA881X_BIAS_REF_CTRL,
|
||||
0x0F, 0x08);
|
||||
wsa881x_bandgap_ctrl(codec, true);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BBM_CTL, 0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0x40, 0x40);
|
||||
if (!WSA881X_IS_2_0(wsa881x->version))
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BBM_CTL,
|
||||
0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0xC0, 0x80);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0x06, 0x06);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL2, 0x04, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_INT, 0x09, 0x09);
|
||||
if (!WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL2,
|
||||
0x04, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_INT,
|
||||
0x09, 0x09);
|
||||
}
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PA_INT, 0xF0, 0x20);
|
||||
if (WSA881X_IS_2_0(wsa881x->version))
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PA_INT,
|
||||
0x0E, 0x0E);
|
||||
if (wsa881x->boost_enable)
|
||||
wsa881x_boost_ctrl(codec, true);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
wsa881x_rdac_ctrl(codec, true);
|
||||
if (wsa881x->visense_enable) {
|
||||
ret = msm_gpioset_activate(CLIENT_WSA_BONGO_1,
|
||||
"wsa_vi");
|
||||
if (ret) {
|
||||
pr_err("%s: gpio set cannot be activated %s\n",
|
||||
__func__, "wsa_vi");
|
||||
return ret;
|
||||
}
|
||||
wsa881x_visense_txfe_ctrl(codec, true,
|
||||
0x00, 0x01, 0x00);
|
||||
wsa881x_visense_adc_ctrl(codec, true);
|
||||
wsa881x_temp_sensor_ctrl(codec, true);
|
||||
}
|
||||
break;
|
||||
case SND_SOC_DAPM_PRE_PMD:
|
||||
wsa881x_rdac_ctrl(codec, false);
|
||||
if (wsa881x->visense_enable) {
|
||||
wsa881x_visense_adc_ctrl(codec, false);
|
||||
wsa881x_visense_txfe_ctrl(codec, false,
|
||||
0x00, 0x01, 0x00);
|
||||
wsa881x_visense_adc_ctrl(codec, false);
|
||||
ret = msm_gpioset_suspend(CLIENT_WSA_BONGO_1,
|
||||
"wsa_vi");
|
||||
if (ret) {
|
||||
|
@ -669,11 +771,11 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w,
|
|||
return ret;
|
||||
}
|
||||
}
|
||||
wsa881x_rdac_ctrl(codec, false);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
if (wsa881x->boost_enable)
|
||||
wsa881x_boost_ctrl(codec, false);
|
||||
wsa881x_clk_ctrl(codec, false);
|
||||
wsa881x_bandgap_ctrl(codec, false);
|
||||
ret = wsa881x_shutdown(wsa881x);
|
||||
if (ret < 0) {
|
||||
|
@ -1084,6 +1186,11 @@ static int wsa881x_i2c_probe(struct i2c_client *client,
|
|||
client->dev.platform_data = pdata;
|
||||
i2c_set_clientdata(client, pdata);
|
||||
pdata->client[WSA881X_ANALOG_SLAVE] = client;
|
||||
if (pdata->version == WSA881X_2_0)
|
||||
wsa881x_update_regmap_2_0(
|
||||
pdata->regmap[WSA881X_ANALOG_SLAVE],
|
||||
WSA881X_ANALOG_SLAVE);
|
||||
|
||||
return ret;
|
||||
} else if (pdata->status == WSA881X_STATUS_PROBING) {
|
||||
pdata->index = wsa881x_index;
|
||||
|
@ -1141,6 +1248,15 @@ static int wsa881x_i2c_probe(struct i2c_client *client,
|
|||
wsa881x_probing_count++;
|
||||
goto err1;
|
||||
}
|
||||
pdata->version = wsa881x_i2c_read_device(pdata,
|
||||
WSA881X_CHIP_ID1);
|
||||
pr_debug("%s: wsa881x version: %d\n", __func__, pdata->version);
|
||||
if (pdata->version == WSA881X_2_0) {
|
||||
wsa881x_update_reg_defaults_2_0();
|
||||
wsa881x_update_regmap_2_0(
|
||||
pdata->regmap[WSA881X_DIGITAL_SLAVE],
|
||||
WSA881X_DIGITAL_SLAVE);
|
||||
}
|
||||
wsa881x_presence_count++;
|
||||
wsa881x_probing_count++;
|
||||
ret = snd_soc_register_codec(&client->dev,
|
||||
|
|
|
@ -28,13 +28,23 @@
|
|||
#define WSA881X_DIGITAL_SLAVE 0
|
||||
#define WSA881X_ANALOG_SLAVE 1
|
||||
|
||||
enum {
|
||||
WSA881X_1_X = 0,
|
||||
WSA881X_2_0,
|
||||
};
|
||||
|
||||
#define WSA881X_IS_2_0(ver) \
|
||||
((ver == WSA881X_2_0) ? 1 : 0)
|
||||
|
||||
extern const u8 wsa881x_ana_reg_readable[WSA881X_CACHE_SIZE];
|
||||
extern const struct reg_default wsa881x_ana_reg_defaults[WSA881X_CACHE_SIZE];
|
||||
extern struct reg_default wsa881x_ana_reg_defaults[WSA881X_CACHE_SIZE];
|
||||
extern struct regmap_config wsa881x_ana_regmap_config[2];
|
||||
int wsa881x_get_client_index(void);
|
||||
int wsa881x_get_probing_count(void);
|
||||
int wsa881x_get_presence_count(void);
|
||||
int wsa881x_set_mclk_callback(
|
||||
int (*enable_mclk_callback)(struct snd_soc_card *, bool));
|
||||
void wsa881x_update_reg_defaults_2_0(void);
|
||||
void wsa881x_update_regmap_2_0(struct regmap *regmap, int flag);
|
||||
|
||||
#endif /* _WSA881X_H */
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#define WSA881X_CLOCK_CONFIG (WSA881X_DIGITAL_BASE+0x0009)
|
||||
#define WSA881X_ANA_CTL (WSA881X_DIGITAL_BASE+0x000A)
|
||||
#define WSA881X_SWR_RESET_EN (WSA881X_DIGITAL_BASE+0x000B)
|
||||
#define WSA881X_RESET_CTL (WSA881X_DIGITAL_BASE+0x000C)
|
||||
#define WSA881X_TADC_VALUE_CTL (WSA881X_DIGITAL_BASE+0x000F)
|
||||
#define WSA881X_TEMP_DETECT_CTL (WSA881X_DIGITAL_BASE+0x0010)
|
||||
#define WSA881X_TEMP_MSB (WSA881X_DIGITAL_BASE+0x0011)
|
||||
#define WSA881X_TEMP_LSB (WSA881X_DIGITAL_BASE+0x0012)
|
||||
|
@ -66,6 +68,7 @@
|
|||
#define WSA881X_TEMP_DEBUG_MSB (WSA881X_DIGITAL_BASE+0x003E)
|
||||
#define WSA881X_TEMP_DEBUG_LSB (WSA881X_DIGITAL_BASE+0x003F)
|
||||
#define WSA881X_SAMPLE_EDGE_SEL (WSA881X_DIGITAL_BASE+0x0044)
|
||||
#define WSA881X_IOPAD_CTL (WSA881X_DIGITAL_BASE+0x0045)
|
||||
#define WSA881X_SPARE_0 (WSA881X_DIGITAL_BASE+0x0050)
|
||||
#define WSA881X_SPARE_1 (WSA881X_DIGITAL_BASE+0x0051)
|
||||
#define WSA881X_SPARE_2 (WSA881X_DIGITAL_BASE+0x0052)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "wsa881x-registers-analog.h"
|
||||
#include "wsa881x-analog.h"
|
||||
|
||||
const struct reg_default wsa881x_ana_reg_defaults[] = {
|
||||
struct reg_default wsa881x_ana_reg_defaults[] = {
|
||||
{WSA881X_CHIP_ID0, 0x00},
|
||||
{WSA881X_CHIP_ID1, 0x00},
|
||||
{WSA881X_CHIP_ID2, 0x00},
|
||||
|
@ -168,7 +168,7 @@ const struct reg_default wsa881x_ana_reg_defaults[] = {
|
|||
{WSA881X_SPKR_STATUS3, 0x00},
|
||||
};
|
||||
|
||||
const struct reg_default wsa881x_ana_reg_defaults_0[] = {
|
||||
struct reg_default wsa881x_ana_reg_defaults_0[] = {
|
||||
{WSA881X_CHIP_ID0, 0x00},
|
||||
{WSA881X_CHIP_ID1, 0x00},
|
||||
{WSA881X_CHIP_ID2, 0x00},
|
||||
|
@ -257,7 +257,7 @@ const struct reg_default wsa881x_ana_reg_defaults_0[] = {
|
|||
{WSA881X_OTP_REG_63, 0x40},
|
||||
};
|
||||
|
||||
const struct reg_default wsa881x_ana_reg_defaults_1[] = {
|
||||
struct reg_default wsa881x_ana_reg_defaults_1[] = {
|
||||
{WSA881X_BIAS_REF_CTRL - WSA881X_ANALOG_BASE, 0x6C},
|
||||
{WSA881X_BIAS_TEST - WSA881X_ANALOG_BASE, 0x16},
|
||||
{WSA881X_BIAS_BIAS - WSA881X_ANALOG_BASE, 0xF0},
|
||||
|
@ -322,6 +322,113 @@ const struct reg_default wsa881x_ana_reg_defaults_1[] = {
|
|||
{WSA881X_SPKR_STATUS3 - WSA881X_ANALOG_BASE, 0x00},
|
||||
};
|
||||
|
||||
struct reg_default wsa881x_rev_2_0_dig[] = {
|
||||
{WSA881X_RESET_CTL, 0x00},
|
||||
{WSA881X_TADC_VALUE_CTL, 0x01},
|
||||
{WSA881X_INTR_MASK, 0x1B},
|
||||
{WSA881X_IOPAD_CTL, 0x00},
|
||||
{WSA881X_OTP_REG_28, 0x3F},
|
||||
{WSA881X_OTP_REG_29, 0x3F},
|
||||
{WSA881X_OTP_REG_30, 0x01},
|
||||
{WSA881X_OTP_REG_31, 0x01},
|
||||
};
|
||||
|
||||
struct reg_default wsa881x_rev_2_0_ana[] = {
|
||||
{WSA881X_TEMP_ADC_CTRL, 0x03},
|
||||
{WSA881X_ADC_SEL_IBIAS, 0x45},
|
||||
{WSA881X_SPKR_DRV_GAIN, 0xC1},
|
||||
{WSA881X_SPKR_DAC_CTL, 0x42},
|
||||
{WSA881X_SPKR_BBM_CTL, 0x02},
|
||||
{WSA881X_SPKR_MISC_CTL1, 0x40},
|
||||
{WSA881X_SPKR_MISC_CTL2, 0x07},
|
||||
{WSA881X_SPKR_BIAS_INT, 0x5F},
|
||||
{WSA881X_SPKR_BIAS_PSRR, 0x44},
|
||||
{WSA881X_BOOST_PS_CTL, 0xA0},
|
||||
{WSA881X_BOOST_PRESET_OUT1, 0xB7},
|
||||
{WSA881X_BOOST_LOOP_STABILITY, 0x8D},
|
||||
{WSA881X_SPKR_PROT_ATEST2, 0x02},
|
||||
{WSA881X_BONGO_RESRV_REG1, 0x5E},
|
||||
{WSA881X_BONGO_RESRV_REG2, 0x07},
|
||||
};
|
||||
|
||||
struct reg_default wsa881x_rev_2_0_regmap_ana[] = {
|
||||
{WSA881X_TEMP_ADC_CTRL - WSA881X_ANALOG_BASE, 0x03},
|
||||
{WSA881X_ADC_SEL_IBIAS - WSA881X_ANALOG_BASE, 0x45},
|
||||
{WSA881X_SPKR_DRV_GAIN - WSA881X_ANALOG_BASE, 0xC1},
|
||||
{WSA881X_SPKR_DAC_CTL - WSA881X_ANALOG_BASE, 0x42},
|
||||
{WSA881X_SPKR_BBM_CTL - WSA881X_ANALOG_BASE, 0x02},
|
||||
{WSA881X_SPKR_MISC_CTL1 - WSA881X_ANALOG_BASE, 0x40},
|
||||
{WSA881X_SPKR_MISC_CTL2 - WSA881X_ANALOG_BASE, 0x07},
|
||||
{WSA881X_SPKR_BIAS_INT - WSA881X_ANALOG_BASE, 0x5F},
|
||||
{WSA881X_SPKR_BIAS_PSRR - WSA881X_ANALOG_BASE, 0x44},
|
||||
{WSA881X_BOOST_PS_CTL - WSA881X_ANALOG_BASE, 0xA0},
|
||||
{WSA881X_BOOST_PRESET_OUT1 - WSA881X_ANALOG_BASE, 0xB7},
|
||||
{WSA881X_BOOST_LOOP_STABILITY - WSA881X_ANALOG_BASE, 0x8D},
|
||||
{WSA881X_SPKR_PROT_ATEST2 - WSA881X_ANALOG_BASE, 0x02},
|
||||
{WSA881X_BONGO_RESRV_REG1 - WSA881X_ANALOG_BASE, 0x5E},
|
||||
{WSA881X_BONGO_RESRV_REG2 - WSA881X_ANALOG_BASE, 0x07},
|
||||
};
|
||||
|
||||
/**
|
||||
* wsa881x_update_reg_defaults_2_0 - update default values of regs for v2.0
|
||||
*
|
||||
* Bongo v2.0 has different default values for certain analog and digital
|
||||
* registers compared to v1.x. Therefore, update the values of these registers
|
||||
* with the values from tables defined above for v2.0.
|
||||
*/
|
||||
void wsa881x_update_reg_defaults_2_0(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wsa881x_rev_2_0_dig); i++) {
|
||||
for (j = 0; j < ARRAY_SIZE(wsa881x_ana_reg_defaults); j++)
|
||||
if (wsa881x_ana_reg_defaults[j].reg ==
|
||||
wsa881x_rev_2_0_dig[i].reg)
|
||||
wsa881x_ana_reg_defaults[j].def =
|
||||
wsa881x_rev_2_0_dig[i].def;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(wsa881x_rev_2_0_ana); i++) {
|
||||
for (j = 0; j < ARRAY_SIZE(wsa881x_ana_reg_defaults); j++)
|
||||
if (wsa881x_ana_reg_defaults[j].reg ==
|
||||
wsa881x_rev_2_0_ana[i].reg)
|
||||
wsa881x_ana_reg_defaults[j].def =
|
||||
wsa881x_rev_2_0_ana[i].def;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(wsa881x_update_reg_defaults_2_0);
|
||||
|
||||
/**
|
||||
* wsa881x_update_regmap_2_0 - update regmap framework with new tables
|
||||
* @regmap: pointer to bongo regmap structure
|
||||
* @flag: indicates digital or analog bongo slave
|
||||
*
|
||||
* Bongo v2.0 has some new registers for both analog and digital slaves.
|
||||
* Update the regmap framework with all the new registers.
|
||||
*/
|
||||
void wsa881x_update_regmap_2_0(struct regmap *regmap, int flag)
|
||||
{
|
||||
u16 ret = 0;
|
||||
|
||||
switch (flag) {
|
||||
case WSA881X_DIGITAL_SLAVE:
|
||||
ret = regmap_register_patch(regmap, wsa881x_rev_2_0_dig,
|
||||
ARRAY_SIZE(wsa881x_rev_2_0_dig));
|
||||
break;
|
||||
case WSA881X_ANALOG_SLAVE:
|
||||
ret = regmap_register_patch(regmap, wsa881x_rev_2_0_ana,
|
||||
ARRAY_SIZE(wsa881x_rev_2_0_ana));
|
||||
break;
|
||||
default:
|
||||
pr_debug("%s: unknown version", __func__);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (ret)
|
||||
pr_err("%s: Failed to update regmap defaults ret= %d\n",
|
||||
__func__, ret);
|
||||
}
|
||||
EXPORT_SYMBOL(wsa881x_update_regmap_2_0);
|
||||
|
||||
static bool wsa881x_readable_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return wsa881x_ana_reg_readable[reg];
|
||||
|
@ -330,20 +437,34 @@ static bool wsa881x_readable_register(struct device *dev, unsigned int reg)
|
|||
static bool wsa881x_volatile_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case WSA881X_CHIP_ID0:
|
||||
case WSA881X_CHIP_ID1:
|
||||
case WSA881X_CHIP_ID2:
|
||||
case WSA881X_CHIP_ID3:
|
||||
case WSA881X_BUS_ID:
|
||||
case WSA881X_TEMP_MSB:
|
||||
case WSA881X_TEMP_LSB:
|
||||
case WSA881X_SDM_PDM9_LSB:
|
||||
case WSA881X_SDM_PDM9_MSB:
|
||||
case WSA881X_OTP_REG_0:
|
||||
case WSA881X_OTP_REG_1:
|
||||
case WSA881X_OTP_REG_2:
|
||||
case WSA881X_OTP_REG_3:
|
||||
case WSA881X_OTP_REG_4:
|
||||
case WSA881X_OTP_REG_5:
|
||||
case WSA881X_OTP_REG_31:
|
||||
case WSA881X_TEMP_DOUT_MSB:
|
||||
case WSA881X_TEMP_DOUT_LSB:
|
||||
case WSA881X_TEMP_OP:
|
||||
case WSA881X_OTP_CTRL1:
|
||||
case WSA881X_INTR_STATUS:
|
||||
case WSA881X_ATE_TEST_MODE:
|
||||
case WSA881X_PIN_STATUS:
|
||||
case WSA881X_SWR_HM_TEST2:
|
||||
case WSA881X_SPKR_STATUS1:
|
||||
case WSA881X_SPKR_STATUS2:
|
||||
case WSA881X_SPKR_STATUS3:
|
||||
case WSA881X_SPKR_PROT_SAR:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -28,6 +28,8 @@ const u8 wsa881x_ana_reg_readable[WSA881X_CACHE_SIZE] = {
|
|||
[WSA881X_CLOCK_CONFIG] = 1,
|
||||
[WSA881X_ANA_CTL] = 1,
|
||||
[WSA881X_SWR_RESET_EN] = 1,
|
||||
[WSA881X_RESET_CTL] = 1,
|
||||
[WSA881X_TADC_VALUE_CTL] = 1,
|
||||
[WSA881X_TEMP_DETECT_CTL] = 1,
|
||||
[WSA881X_TEMP_MSB] = 1,
|
||||
[WSA881X_TEMP_LSB] = 1,
|
||||
|
@ -66,6 +68,7 @@ const u8 wsa881x_ana_reg_readable[WSA881X_CACHE_SIZE] = {
|
|||
[WSA881X_TEMP_DEBUG_MSB] = 1,
|
||||
[WSA881X_TEMP_DEBUG_LSB] = 1,
|
||||
[WSA881X_SAMPLE_EDGE_SEL] = 1,
|
||||
[WSA881X_IOPAD_CTL] = 1,
|
||||
[WSA881X_SPARE_0] = 1,
|
||||
[WSA881X_SPARE_1] = 1,
|
||||
[WSA881X_SPARE_2] = 1,
|
||||
|
|
Loading…
Reference in a new issue