Merge "ASoC: wsa: add support for WSA 2.0 version and sequences"

This commit is contained in:
Linux Build Service Account 2015-08-19 12:24:08 -07:00 committed by Gerrit - the friendly Code Review server
commit ad2908ab59
5 changed files with 317 additions and 64 deletions

View file

@ -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,

View file

@ -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 */

View file

@ -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)

View file

@ -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;

View file

@ -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,