mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-12 07:37:31 -04:00
asoc: codecs: Add support for BCL feature
Add mixer widgets, routing and mixer controls in order to support BCL feature on WSA and RX macros of bolero codec. CRs-Fixed: 2225097 Change-Id: I463f89a517bb3878e51a6aca0c1d73bc652ab8c5 Signed-off-by: Aditya Bavanari <abavanar@codeaurora.org>
This commit is contained in:
parent
965e8d4b00
commit
4f3d5643bd
2 changed files with 729 additions and 0 deletions
|
|
@ -160,6 +160,12 @@ static struct interp_sample_rate sr_val_tbl[] = {
|
|||
{176400, 0xB}, {352800, 0xC},
|
||||
};
|
||||
|
||||
struct rx_macro_bcl_pmic_params {
|
||||
u8 id;
|
||||
u8 sid;
|
||||
u8 ppid;
|
||||
};
|
||||
|
||||
static int rx_macro_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai);
|
||||
|
|
@ -258,6 +264,9 @@ struct rx_macro_priv {
|
|||
struct platform_device *pdev_child_devices
|
||||
[RX_MACRO_CHILD_DEVICES_MAX];
|
||||
int child_count;
|
||||
int is_softclip_on;
|
||||
int softclip_clk_users;
|
||||
struct rx_macro_bcl_pmic_params bcl_pmic_params;
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver rx_macro_dai[];
|
||||
|
|
@ -321,6 +330,14 @@ static const char *const rx_macro_ear_mode_text[] = {"OFF", "ON"};
|
|||
static const struct soc_enum rx_macro_ear_mode_enum =
|
||||
SOC_ENUM_SINGLE_EXT(2, rx_macro_ear_mode_text);
|
||||
|
||||
static const char * const rx_macro_vbat_bcl_gsm_mode_text[] = {"OFF", "ON"};
|
||||
static const struct soc_enum rx_macro_vbat_bcl_gsm_mode_enum =
|
||||
SOC_ENUM_SINGLE_EXT(2, rx_macro_vbat_bcl_gsm_mode_text);
|
||||
|
||||
static const struct snd_kcontrol_new rx_int2_1_vbat_mix_switch[] = {
|
||||
SOC_DAPM_SINGLE("RX AUX VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
|
||||
};
|
||||
|
||||
RX_MACRO_DAPM_ENUM(rx_int0_2, BOLERO_CDC_RX_INP_MUX_RX_INT0_CFG1, 0,
|
||||
rx_int_mix_mux_text);
|
||||
RX_MACRO_DAPM_ENUM(rx_int1_2, BOLERO_CDC_RX_INP_MUX_RX_INT1_CFG1, 0,
|
||||
|
|
@ -1159,6 +1176,52 @@ static int rx_macro_config_compander(struct snd_soc_codec *codec,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void rx_macro_enable_softclip_clk(struct snd_soc_codec *codec,
|
||||
struct rx_macro_priv *rx_priv,
|
||||
bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
if (rx_priv->softclip_clk_users == 0)
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_SOFTCLIP_CRC,
|
||||
0x01, 0x01);
|
||||
rx_priv->softclip_clk_users++;
|
||||
} else {
|
||||
rx_priv->softclip_clk_users--;
|
||||
if (rx_priv->softclip_clk_users == 0)
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_SOFTCLIP_CRC,
|
||||
0x01, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
static int rx_macro_config_softclip(struct snd_soc_codec *codec,
|
||||
struct rx_macro_priv *rx_priv,
|
||||
int event)
|
||||
{
|
||||
dev_dbg(codec->dev, "%s: event %d, enabled %d\n",
|
||||
__func__, event, rx_priv->is_softclip_on);
|
||||
|
||||
if (!rx_priv->is_softclip_on)
|
||||
return 0;
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_ON(event)) {
|
||||
/* Enable Softclip clock */
|
||||
rx_macro_enable_softclip_clk(codec, rx_priv, true);
|
||||
/* Enable Softclip control */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x01, 0x01);
|
||||
}
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_OFF(event)) {
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x01, 0x00);
|
||||
rx_macro_enable_softclip_clk(codec, rx_priv, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
rx_macro_enable_clsh_block(struct rx_macro_priv *rx_priv, bool enable)
|
||||
{
|
||||
|
|
@ -1391,6 +1454,191 @@ static int rx_macro_put_ear_mode(struct snd_kcontrol *kcontrol,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rx_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
|
||||
ucontrol->value.integer.value[0] =
|
||||
((snd_soc_read(codec, BOLERO_CDC_RX_BCL_VBAT_CFG) & 0x04) ?
|
||||
1 : 0);
|
||||
|
||||
dev_dbg(codec->dev, "%s: value: %lu\n", __func__,
|
||||
ucontrol->value.integer.value[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rx_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
|
||||
dev_dbg(codec->dev, "%s: value: %lu\n", __func__,
|
||||
ucontrol->value.integer.value[0]);
|
||||
|
||||
/* Set Vbat register configuration for GSM mode bit based on value */
|
||||
if (ucontrol->value.integer.value[0])
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_RX_BCL_VBAT_CFG,
|
||||
0x04, 0x04);
|
||||
else
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_RX_BCL_VBAT_CFG,
|
||||
0x04, 0x00);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rx_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct device *rx_dev = NULL;
|
||||
struct rx_macro_priv *rx_priv = NULL;
|
||||
|
||||
if (!rx_macro_get_data(codec, &rx_dev, &rx_priv, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
ucontrol->value.integer.value[0] = rx_priv->is_softclip_on;
|
||||
|
||||
dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
|
||||
__func__, ucontrol->value.integer.value[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rx_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct device *rx_dev = NULL;
|
||||
struct rx_macro_priv *rx_priv = NULL;
|
||||
|
||||
if (!rx_macro_get_data(codec, &rx_dev, &rx_priv, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
rx_priv->is_softclip_on = ucontrol->value.integer.value[0];
|
||||
|
||||
dev_dbg(codec->dev, "%s: soft clip enable = %d\n", __func__,
|
||||
rx_priv->is_softclip_on);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rx_macro_enable_vbat(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
int event)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
struct device *rx_dev = NULL;
|
||||
struct rx_macro_priv *rx_priv = NULL;
|
||||
|
||||
dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
|
||||
if (!rx_macro_get_data(codec, &rx_dev, &rx_priv, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
/* Enable clock for VBAT block */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_PATH_CTL, 0x10, 0x10);
|
||||
/* Enable VBAT block */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_CFG, 0x01, 0x01);
|
||||
/* Update interpolator with 384K path */
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_RX_RX2_RX_PATH_CFG1,
|
||||
0x80, 0x80);
|
||||
/* Update DSM FS rate */
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_RX_RX2_RX_PATH_SEC7,
|
||||
0x02, 0x02);
|
||||
/* Use attenuation mode */
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_RX_BCL_VBAT_CFG,
|
||||
0x02, 0x00);
|
||||
/* BCL block needs softclip clock to be enabled */
|
||||
rx_macro_enable_softclip_clk(codec, rx_priv, true);
|
||||
/* Enable VBAT at channel level */
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_RX_RX2_RX_PATH_CFG1,
|
||||
0x02, 0x02);
|
||||
/* Set the ATTK1 gain */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1,
|
||||
0xFF, 0xFF);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2,
|
||||
0xFF, 0x03);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3,
|
||||
0xFF, 0x00);
|
||||
/* Set the ATTK2 gain */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4,
|
||||
0xFF, 0xFF);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5,
|
||||
0xFF, 0x03);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6,
|
||||
0xFF, 0x00);
|
||||
/* Set the ATTK3 gain */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7,
|
||||
0xFF, 0xFF);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8,
|
||||
0xFF, 0x03);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9,
|
||||
0xFF, 0x00);
|
||||
break;
|
||||
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_RX_RX2_RX_PATH_CFG1,
|
||||
0x80, 0x00);
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_RX_RX2_RX_PATH_SEC7,
|
||||
0x02, 0x00);
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_RX_BCL_VBAT_CFG,
|
||||
0x02, 0x02);
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_RX_RX2_RX_PATH_CFG1,
|
||||
0x02, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9,
|
||||
0xFF, 0x00);
|
||||
rx_macro_enable_softclip_clk(codec, rx_priv, false);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_CFG, 0x01, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_PATH_CTL, 0x10, 0x00);
|
||||
break;
|
||||
default:
|
||||
dev_err(rx_dev, "%s: Invalid event %d\n", __func__, event);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rx_macro_idle_detect_control(struct snd_soc_codec *codec,
|
||||
struct rx_macro_priv *rx_priv,
|
||||
int interp, int event)
|
||||
|
|
@ -1504,6 +1752,9 @@ static int rx_macro_enable_interp_clk(struct snd_soc_codec *codec,
|
|||
event);
|
||||
rx_macro_config_compander(codec, rx_priv,
|
||||
interp_idx, event);
|
||||
if (interp_idx == INTERP_AUX)
|
||||
rx_macro_config_softclip(codec, rx_priv,
|
||||
event);
|
||||
rx_macro_config_classh(codec, rx_priv,
|
||||
interp_idx, event);
|
||||
}
|
||||
|
|
@ -1518,6 +1769,9 @@ static int rx_macro_enable_interp_clk(struct snd_soc_codec *codec,
|
|||
interp_idx, event);
|
||||
rx_macro_config_compander(codec, rx_priv,
|
||||
interp_idx, event);
|
||||
if (interp_idx == INTERP_AUX)
|
||||
rx_macro_config_softclip(codec, rx_priv,
|
||||
event);
|
||||
rx_macro_hphdelay_lutbypass(codec, rx_priv, interp_idx,
|
||||
event);
|
||||
rx_macro_hd2_control(codec, interp_idx, event);
|
||||
|
|
@ -1881,6 +2135,13 @@ static const struct snd_kcontrol_new rx_macro_snd_controls[] = {
|
|||
SOC_ENUM_EXT("RX_EAR Mode", rx_macro_ear_mode_enum,
|
||||
rx_macro_get_ear_mode, rx_macro_put_ear_mode),
|
||||
|
||||
SOC_ENUM_EXT("RX_GSM mode Enable", rx_macro_vbat_bcl_gsm_mode_enum,
|
||||
rx_macro_vbat_bcl_gsm_mode_func_get,
|
||||
rx_macro_vbat_bcl_gsm_mode_func_put),
|
||||
SOC_SINGLE_EXT("RX_Softclip Enable", SND_SOC_NOPM, 0, 1, 0,
|
||||
rx_macro_soft_clip_enable_get,
|
||||
rx_macro_soft_clip_enable_put),
|
||||
|
||||
SOC_SINGLE_SX_TLV("IIR0 INP0 Volume",
|
||||
BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0, -84, 40,
|
||||
digital_gain),
|
||||
|
|
@ -2079,6 +2340,12 @@ static const struct snd_soc_dapm_widget rx_macro_dapm_widgets[] = {
|
|||
0, &rx_int2_mix2_inp_mux, rx_macro_enable_rx_path_clk,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_MIXER_E("RX INT2_1 VBAT", SND_SOC_NOPM,
|
||||
0, 0, rx_int2_1_vbat_mix_switch,
|
||||
ARRAY_SIZE(rx_int2_1_vbat_mix_switch),
|
||||
rx_macro_enable_vbat,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_MIXER("RX INT0 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_MIXER("RX INT1 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_MIXER("RX INT2 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
|
|
@ -2269,6 +2536,10 @@ static const struct snd_soc_dapm_route rx_audio_map[] = {
|
|||
{"HPHR_OUT", NULL, "RX_MCLK"},
|
||||
|
||||
{"RX INT2_1 INTERP", NULL, "RX INT2_1 MIX1"},
|
||||
|
||||
{"RX INT2_1 VBAT", "RX AUX VBAT Enable", "RX INT2_1 INTERP"},
|
||||
{"RX INT2 SEC MIX", NULL, "RX INT2_1 VBAT"},
|
||||
|
||||
{"RX INT2 SEC MIX", NULL, "RX INT2_1 INTERP"},
|
||||
{"RX INT2 MIX2", NULL, "RX INT2 SEC MIX"},
|
||||
{"RX INT2 MIX2", NULL, "RX INT2 MIX2 INP"},
|
||||
|
|
@ -2434,6 +2705,53 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void rx_macro_init_bcl_pmic_reg(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct device *rx_dev = NULL;
|
||||
struct rx_macro_priv *rx_priv = NULL;
|
||||
|
||||
if (!codec) {
|
||||
pr_err("%s: NULL codec pointer!\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rx_macro_get_data(codec, &rx_dev, &rx_priv, __func__))
|
||||
return;
|
||||
|
||||
switch (rx_priv->bcl_pmic_params.id) {
|
||||
case 0:
|
||||
/* Enable ID0 to listen to respective PMIC group interrupts */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_DECODE_CTL1, 0x02, 0x02);
|
||||
/* Update MC_SID0 */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG1, 0x0F,
|
||||
rx_priv->bcl_pmic_params.sid);
|
||||
/* Update MC_PPID0 */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG2, 0xFF,
|
||||
rx_priv->bcl_pmic_params.ppid);
|
||||
break;
|
||||
case 1:
|
||||
/* Enable ID1 to listen to respective PMIC group interrupts */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_DECODE_CTL1, 0x01, 0x01);
|
||||
/* Update MC_SID1 */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG3, 0x0F,
|
||||
rx_priv->bcl_pmic_params.sid);
|
||||
/* Update MC_PPID1 */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG1, 0xFF,
|
||||
rx_priv->bcl_pmic_params.ppid);
|
||||
break;
|
||||
default:
|
||||
dev_err(rx_dev, "%s: PMIC ID is invalid\n",
|
||||
__func__, rx_priv->bcl_pmic_params.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int rx_macro_init(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||
|
|
@ -2486,6 +2804,7 @@ static int rx_macro_init(struct snd_soc_codec *codec)
|
|||
snd_soc_update_bits(codec, BOLERO_CDC_RX_RX0_RX_PATH_CFG3, 0x03, 0x02);
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_RX_RX1_RX_PATH_CFG3, 0x03, 0x02);
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_RX_RX2_RX_PATH_CFG3, 0x03, 0x02);
|
||||
rx_macro_init_bcl_pmic_reg(codec);
|
||||
|
||||
rx_priv->codec = codec;
|
||||
|
||||
|
|
@ -2631,6 +2950,7 @@ static int rx_macro_probe(struct platform_device *pdev)
|
|||
char __iomem *rx_io_base = NULL, *muxsel_io = NULL;
|
||||
int ret = 0;
|
||||
struct clk *rx_core_clk = NULL, *rx_npl_clk = NULL;
|
||||
u8 bcl_pmic_params[3];
|
||||
|
||||
rx_priv = devm_kzalloc(&pdev->dev, sizeof(struct rx_macro_priv),
|
||||
GFP_KERNEL);
|
||||
|
|
@ -2700,6 +3020,19 @@ static int rx_macro_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
rx_priv->rx_npl_clk = rx_npl_clk;
|
||||
|
||||
ret = of_property_read_u8_array(pdev->dev.of_node,
|
||||
"qcom,rx-bcl-pmic-params", bcl_pmic_params,
|
||||
sizeof(bcl_pmic_params));
|
||||
if (ret) {
|
||||
dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
|
||||
__func__, "qcom,rx-bcl-pmic-params");
|
||||
} else {
|
||||
rx_priv->bcl_pmic_params.id = bcl_pmic_params[0];
|
||||
rx_priv->bcl_pmic_params.sid = bcl_pmic_params[1];
|
||||
rx_priv->bcl_pmic_params.ppid = bcl_pmic_params[2];
|
||||
}
|
||||
|
||||
dev_set_drvdata(&pdev->dev, rx_priv);
|
||||
mutex_init(&rx_priv->mclk_lock);
|
||||
mutex_init(&rx_priv->swr_clk_lock);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
#define WSA_MACRO_MUX_CFG_OFFSET 0x8
|
||||
#define WSA_MACRO_MUX_CFG1_OFFSET 0x4
|
||||
#define WSA_MACRO_RX_COMP_OFFSET 0x40
|
||||
#define WSA_MACRO_RX_SOFTCLIP_OFFSET 0x40
|
||||
#define WSA_MACRO_RX_PATH_OFFSET 0x80
|
||||
#define WSA_MACRO_RX_PATH_CFG3_OFFSET 0x10
|
||||
#define WSA_MACRO_RX_PATH_DSMDEM_OFFSET 0x4C
|
||||
|
|
@ -82,6 +83,12 @@ enum {
|
|||
WSA_MACRO_COMP_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
WSA_MACRO_SOFTCLIP0, /* RX0 */
|
||||
WSA_MACRO_SOFTCLIP1, /* RX1 */
|
||||
WSA_MACRO_SOFTCLIP_MAX
|
||||
};
|
||||
|
||||
struct interp_sample_rate {
|
||||
int sample_rate;
|
||||
int rate_val;
|
||||
|
|
@ -141,6 +148,12 @@ struct wsa_macro_swr_ctrl_platform_data {
|
|||
int action);
|
||||
};
|
||||
|
||||
struct wsa_macro_bcl_pmic_params {
|
||||
u8 id;
|
||||
u8 sid;
|
||||
u8 ppid;
|
||||
};
|
||||
|
||||
enum {
|
||||
WSA_MACRO_AIF_INVALID = 0,
|
||||
WSA_MACRO_AIF1_PB,
|
||||
|
|
@ -205,6 +218,9 @@ struct wsa_macro_priv {
|
|||
int ear_spkr_gain;
|
||||
int spkr_gain_offset;
|
||||
int spkr_mode;
|
||||
int is_softclip_on[WSA_MACRO_SOFTCLIP_MAX];
|
||||
int softclip_clk_users[WSA_MACRO_SOFTCLIP_MAX];
|
||||
struct wsa_macro_bcl_pmic_params bcl_pmic_params;
|
||||
};
|
||||
|
||||
static int wsa_macro_config_ear_spkr_gain(struct snd_soc_codec *codec,
|
||||
|
|
@ -242,10 +258,24 @@ static const char * const wsa_macro_speaker_boost_stage_text[] = {
|
|||
"NO_MAX_STATE", "MAX_STATE_1", "MAX_STATE_2"
|
||||
};
|
||||
|
||||
static const char * const wsa_macro_vbat_bcl_gsm_mode_text[] = {
|
||||
"OFF", "ON"
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new wsa_int0_vbat_mix_switch[] = {
|
||||
SOC_DAPM_SINGLE("WSA RX0 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new wsa_int1_vbat_mix_switch[] = {
|
||||
SOC_DAPM_SINGLE("WSA RX1 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_ear_spkr_pa_gain_enum,
|
||||
wsa_macro_ear_spkr_pa_gain_text);
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_spkr_boost_stage_enum,
|
||||
wsa_macro_speaker_boost_stage_text);
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_vbat_bcl_gsm_mode_enum,
|
||||
wsa_macro_vbat_bcl_gsm_mode_text);
|
||||
|
||||
/* RX INT0 */
|
||||
static const struct soc_enum rx0_prim_inp0_chain_enum =
|
||||
|
|
@ -1095,6 +1125,82 @@ static int wsa_macro_config_compander(struct snd_soc_codec *codec,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void wsa_macro_enable_softclip_clk(struct snd_soc_codec *codec,
|
||||
struct wsa_macro_priv *wsa_priv,
|
||||
int path,
|
||||
bool enable)
|
||||
{
|
||||
u16 softclip_clk_reg = BOLERO_CDC_WSA_SOFTCLIP0_CRC +
|
||||
(path * WSA_MACRO_RX_SOFTCLIP_OFFSET);
|
||||
u8 softclip_mux_mask = (1 << path);
|
||||
u8 softclip_mux_value = (1 << path);
|
||||
|
||||
dev_dbg(codec->dev, "%s: path %d, enable %d\n",
|
||||
__func__, path, enable);
|
||||
if (enable) {
|
||||
if (wsa_priv->softclip_clk_users[path] == 0) {
|
||||
snd_soc_update_bits(codec,
|
||||
softclip_clk_reg, 0x01, 0x01);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
|
||||
softclip_mux_mask, softclip_mux_value);
|
||||
}
|
||||
wsa_priv->softclip_clk_users[path]++;
|
||||
} else {
|
||||
wsa_priv->softclip_clk_users[path]--;
|
||||
if (wsa_priv->softclip_clk_users[path] == 0) {
|
||||
snd_soc_update_bits(codec,
|
||||
softclip_clk_reg, 0x01, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
|
||||
softclip_mux_mask, 0x00);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int wsa_macro_config_softclip(struct snd_soc_codec *codec,
|
||||
int path, int event)
|
||||
{
|
||||
u16 softclip_ctrl_reg = 0;
|
||||
struct device *wsa_dev = NULL;
|
||||
struct wsa_macro_priv *wsa_priv = NULL;
|
||||
int softclip_path = 0;
|
||||
|
||||
if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
if (path == WSA_MACRO_COMP1)
|
||||
softclip_path = WSA_MACRO_SOFTCLIP0;
|
||||
else if (path == WSA_MACRO_COMP2)
|
||||
softclip_path = WSA_MACRO_SOFTCLIP1;
|
||||
|
||||
dev_dbg(codec->dev, "%s: event %d path %d, enabled %d\n",
|
||||
__func__, event, softclip_path,
|
||||
wsa_priv->is_softclip_on[softclip_path]);
|
||||
|
||||
if (!wsa_priv->is_softclip_on[softclip_path])
|
||||
return 0;
|
||||
|
||||
softclip_ctrl_reg = BOLERO_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL +
|
||||
(softclip_path * WSA_MACRO_RX_SOFTCLIP_OFFSET);
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_ON(event)) {
|
||||
/* Enable Softclip clock and mux */
|
||||
wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
|
||||
true);
|
||||
/* Enable Softclip control */
|
||||
snd_soc_update_bits(codec, softclip_ctrl_reg, 0x01, 0x01);
|
||||
}
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_OFF(event)) {
|
||||
snd_soc_update_bits(codec, softclip_ctrl_reg, 0x01, 0x00);
|
||||
wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
|
||||
false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa_macro_interp_get_primary_reg(u16 reg, u16 *ind)
|
||||
{
|
||||
u16 prim_int_reg = 0;
|
||||
|
|
@ -1204,6 +1310,7 @@ static int wsa_macro_enable_interpolator(struct snd_soc_dapm_widget *w,
|
|||
break;
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
wsa_macro_config_compander(codec, w->shift, event);
|
||||
wsa_macro_config_softclip(codec, w->shift, event);
|
||||
/* apply gain after int clk is enabled */
|
||||
if ((wsa_priv->spkr_gain_offset ==
|
||||
WSA_MACRO_GAIN_OFFSET_M1P5_DB) &&
|
||||
|
|
@ -1231,6 +1338,7 @@ static int wsa_macro_enable_interpolator(struct snd_soc_dapm_widget *w,
|
|||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
wsa_macro_config_compander(codec, w->shift, event);
|
||||
wsa_macro_config_softclip(codec, w->shift, event);
|
||||
wsa_macro_enable_prim_interpolator(codec, reg, event);
|
||||
if ((wsa_priv->spkr_gain_offset ==
|
||||
WSA_MACRO_GAIN_OFFSET_M1P5_DB) &&
|
||||
|
|
@ -1356,6 +1464,127 @@ static int wsa_macro_spk_boost_event(struct snd_soc_dapm_widget *w,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wsa_macro_enable_vbat(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
int event)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
struct device *wsa_dev = NULL;
|
||||
struct wsa_macro_priv *wsa_priv = NULL;
|
||||
u16 vbat_path_cfg = 0;
|
||||
int softclip_path = 0;
|
||||
|
||||
if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
|
||||
if (!strcmp(w->name, "WSA_RX INT0 VBAT")) {
|
||||
vbat_path_cfg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG1;
|
||||
softclip_path = WSA_MACRO_SOFTCLIP0;
|
||||
} else if (!strcmp(w->name, "WSA_RX INT1 VBAT")) {
|
||||
vbat_path_cfg = BOLERO_CDC_WSA_RX1_RX_PATH_CFG1;
|
||||
softclip_path = WSA_MACRO_SOFTCLIP1;
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
/* Enable clock for VBAT block */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x10);
|
||||
/* Enable VBAT block */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x01);
|
||||
/* Update interpolator with 384K path */
|
||||
snd_soc_update_bits(codec, vbat_path_cfg, 0x80, 0x80);
|
||||
/* Use attenuation mode */
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
|
||||
0x02, 0x00);
|
||||
/*
|
||||
* BCL block needs softclip clock and mux config to be enabled
|
||||
*/
|
||||
wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
|
||||
true);
|
||||
/* Enable VBAT at channel level */
|
||||
snd_soc_update_bits(codec, vbat_path_cfg, 0x02, 0x02);
|
||||
/* Set the ATTK1 gain */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
|
||||
0xFF, 0xFF);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
|
||||
0xFF, 0x03);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
|
||||
0xFF, 0x00);
|
||||
/* Set the ATTK2 gain */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
|
||||
0xFF, 0xFF);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
|
||||
0xFF, 0x03);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
|
||||
0xFF, 0x00);
|
||||
/* Set the ATTK3 gain */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
|
||||
0xFF, 0xFF);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
|
||||
0xFF, 0x03);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
|
||||
0xFF, 0x00);
|
||||
break;
|
||||
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
snd_soc_update_bits(codec, vbat_path_cfg, 0x80, 0x00);
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
|
||||
0x02, 0x02);
|
||||
snd_soc_update_bits(codec, vbat_path_cfg, 0x02, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
|
||||
0xFF, 0x00);
|
||||
wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
|
||||
false);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x00);
|
||||
break;
|
||||
default:
|
||||
dev_err(wsa_dev, "%s: Invalid event %d\n", __func__, event);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa_macro_enable_echo(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
int event)
|
||||
|
|
@ -1637,6 +1866,80 @@ static int wsa_macro_rx_mux_put(struct snd_kcontrol *kcontrol,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int wsa_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
|
||||
ucontrol->value.integer.value[0] =
|
||||
((snd_soc_read(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG) & 0x04) ?
|
||||
1 : 0);
|
||||
|
||||
dev_dbg(codec->dev, "%s: value: %lu\n", __func__,
|
||||
ucontrol->value.integer.value[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
|
||||
dev_dbg(codec->dev, "%s: value: %lu\n", __func__,
|
||||
ucontrol->value.integer.value[0]);
|
||||
|
||||
/* Set Vbat register configuration for GSM mode bit based on value */
|
||||
if (ucontrol->value.integer.value[0])
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
|
||||
0x04, 0x04);
|
||||
else
|
||||
snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
|
||||
0x04, 0x00);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct device *wsa_dev = NULL;
|
||||
struct wsa_macro_priv *wsa_priv = NULL;
|
||||
int path = ((struct soc_multi_mixer_control *)
|
||||
kcontrol->private_value)->shift;
|
||||
|
||||
if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
ucontrol->value.integer.value[0] = wsa_priv->is_softclip_on[path];
|
||||
|
||||
dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
|
||||
__func__, ucontrol->value.integer.value[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct device *wsa_dev = NULL;
|
||||
struct wsa_macro_priv *wsa_priv = NULL;
|
||||
int path = ((struct soc_multi_mixer_control *)
|
||||
kcontrol->private_value)->shift;
|
||||
|
||||
if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
wsa_priv->is_softclip_on[path] = ucontrol->value.integer.value[0];
|
||||
|
||||
dev_dbg(codec->dev, "%s: soft clip enable for %d: %d\n", __func__,
|
||||
path, wsa_priv->is_softclip_on[path]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new wsa_macro_snd_controls[] = {
|
||||
SOC_ENUM_EXT("EAR SPKR PA Gain", wsa_macro_ear_spkr_pa_gain_enum,
|
||||
wsa_macro_ear_spkr_pa_gain_get,
|
||||
|
|
@ -1649,6 +1952,17 @@ static const struct snd_kcontrol_new wsa_macro_snd_controls[] = {
|
|||
wsa_macro_spkr_boost_stage_enum,
|
||||
wsa_macro_spkr_right_boost_stage_get,
|
||||
wsa_macro_spkr_right_boost_stage_put),
|
||||
SOC_ENUM_EXT("GSM mode Enable", wsa_macro_vbat_bcl_gsm_mode_enum,
|
||||
wsa_macro_vbat_bcl_gsm_mode_func_get,
|
||||
wsa_macro_vbat_bcl_gsm_mode_func_put),
|
||||
SOC_SINGLE_EXT("WSA_Softclip0 Enable", SND_SOC_NOPM,
|
||||
WSA_MACRO_SOFTCLIP0, 1, 0,
|
||||
wsa_macro_soft_clip_enable_get,
|
||||
wsa_macro_soft_clip_enable_put),
|
||||
SOC_SINGLE_EXT("WSA_Softclip1 Enable", SND_SOC_NOPM,
|
||||
WSA_MACRO_SOFTCLIP1, 1, 0,
|
||||
wsa_macro_soft_clip_enable_get,
|
||||
wsa_macro_soft_clip_enable_put),
|
||||
SOC_SINGLE_SX_TLV("WSA_RX0 Digital Volume",
|
||||
BOLERO_CDC_WSA_RX0_RX_VOL_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
|
|
@ -1862,6 +2176,17 @@ static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = {
|
|||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
|
||||
SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_MIXER_E("WSA_RX INT0 VBAT", SND_SOC_NOPM,
|
||||
0, 0, wsa_int0_vbat_mix_switch,
|
||||
ARRAY_SIZE(wsa_int0_vbat_mix_switch),
|
||||
wsa_macro_enable_vbat,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_MIXER_E("WSA_RX INT1 VBAT", SND_SOC_NOPM,
|
||||
0, 0, wsa_int1_vbat_mix_switch,
|
||||
ARRAY_SIZE(wsa_int1_vbat_mix_switch),
|
||||
wsa_macro_enable_vbat,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_INPUT("VIINPUT_WSA"),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("WSA_SPK1 OUT"),
|
||||
|
|
@ -1939,6 +2264,10 @@ static const struct snd_soc_dapm_route wsa_audio_map[] = {
|
|||
{"WSA_RX0 INT0 SIDETONE MIX", "SRC0", "WSA SRC0_INP"},
|
||||
{"WSA_RX INT0 INTERP", NULL, "WSA_RX0 INT0 SIDETONE MIX"},
|
||||
{"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 INTERP"},
|
||||
|
||||
{"WSA_RX INT0 VBAT", "WSA RX0 VBAT Enable", "WSA_RX INT0 INTERP"},
|
||||
{"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 VBAT"},
|
||||
|
||||
{"WSA_SPK1 OUT", NULL, "WSA_RX INT0 CHAIN"},
|
||||
{"WSA_SPK1 OUT", NULL, "WSA_MCLK"},
|
||||
|
||||
|
|
@ -1974,6 +2303,10 @@ static const struct snd_soc_dapm_route wsa_audio_map[] = {
|
|||
|
||||
{"WSA_RX INT1 SEC MIX", NULL, "WSA_RX INT1 MIX"},
|
||||
{"WSA_RX INT1 INTERP", NULL, "WSA_RX INT1 SEC MIX"},
|
||||
|
||||
{"WSA_RX INT1 VBAT", "WSA RX1 VBAT Enable", "WSA_RX INT1 INTERP"},
|
||||
{"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 VBAT"},
|
||||
|
||||
{"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 INTERP"},
|
||||
{"WSA_SPK2 OUT", NULL, "WSA_RX INT1 CHAIN"},
|
||||
{"WSA_SPK2 OUT", NULL, "WSA_MCLK"},
|
||||
|
|
@ -2006,6 +2339,53 @@ static const struct wsa_macro_reg_mask_val wsa_macro_reg_init[] = {
|
|||
{BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CFG, 0x01, 0x01},
|
||||
};
|
||||
|
||||
static void wsa_macro_init_bcl_pmic_reg(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct device *wsa_dev = NULL;
|
||||
struct wsa_macro_priv *wsa_priv = NULL;
|
||||
|
||||
if (!codec) {
|
||||
pr_err("%s: NULL codec pointer!\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
|
||||
return;
|
||||
|
||||
switch (wsa_priv->bcl_pmic_params.id) {
|
||||
case 0:
|
||||
/* Enable ID0 to listen to respective PMIC group interrupts */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x02, 0x02);
|
||||
/* Update MC_SID0 */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG1, 0x0F,
|
||||
wsa_priv->bcl_pmic_params.sid);
|
||||
/* Update MC_PPID0 */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG2, 0xFF,
|
||||
wsa_priv->bcl_pmic_params.ppid);
|
||||
break;
|
||||
case 1:
|
||||
/* Enable ID1 to listen to respective PMIC group interrupts */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x01, 0x01);
|
||||
/* Update MC_SID1 */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG3, 0x0F,
|
||||
wsa_priv->bcl_pmic_params.sid);
|
||||
/* Update MC_PPID1 */
|
||||
snd_soc_update_bits(codec,
|
||||
BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG4, 0xFF,
|
||||
wsa_priv->bcl_pmic_params.ppid);
|
||||
break;
|
||||
default:
|
||||
dev_err(wsa_dev, "%s: PMIC ID is invalid %d\n",
|
||||
__func__, wsa_priv->bcl_pmic_params.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void wsa_macro_init_reg(struct snd_soc_codec *codec)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -2015,6 +2395,8 @@ static void wsa_macro_init_reg(struct snd_soc_codec *codec)
|
|||
wsa_macro_reg_init[i].reg,
|
||||
wsa_macro_reg_init[i].mask,
|
||||
wsa_macro_reg_init[i].val);
|
||||
|
||||
wsa_macro_init_bcl_pmic_reg(codec);
|
||||
}
|
||||
|
||||
static int wsa_swrm_clock(void *handle, bool enable)
|
||||
|
|
@ -2245,6 +2627,7 @@ static int wsa_macro_probe(struct platform_device *pdev)
|
|||
char __iomem *wsa_io_base;
|
||||
int ret = 0;
|
||||
struct clk *wsa_core_clk, *wsa_npl_clk;
|
||||
u8 bcl_pmic_params[3];
|
||||
|
||||
wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct wsa_macro_priv),
|
||||
GFP_KERNEL);
|
||||
|
|
@ -2300,6 +2683,19 @@ static int wsa_macro_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
wsa_priv->wsa_npl_clk = wsa_npl_clk;
|
||||
|
||||
ret = of_property_read_u8_array(pdev->dev.of_node,
|
||||
"qcom,wsa-bcl-pmic-params", bcl_pmic_params,
|
||||
sizeof(bcl_pmic_params));
|
||||
if (ret) {
|
||||
dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
|
||||
__func__, "qcom,wsa-bcl-pmic-params");
|
||||
} else {
|
||||
wsa_priv->bcl_pmic_params.id = bcl_pmic_params[0];
|
||||
wsa_priv->bcl_pmic_params.sid = bcl_pmic_params[1];
|
||||
wsa_priv->bcl_pmic_params.ppid = bcl_pmic_params[2];
|
||||
}
|
||||
|
||||
dev_set_drvdata(&pdev->dev, wsa_priv);
|
||||
mutex_init(&wsa_priv->mclk_lock);
|
||||
mutex_init(&wsa_priv->swr_clk_lock);
|
||||
|
|
|
|||
Loading…
Reference in a new issue