diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c index d5071279f53f..449b73e4d97c 100644 --- a/asoc/codecs/bolero/rx-macro.c +++ b/asoc/codecs/bolero/rx-macro.c @@ -227,6 +227,8 @@ struct rx_macro_priv { int rx_mclk_users; int swr_clk_users; int rx_mclk_cnt; + bool is_native_on; + u16 mclk_mux; struct mutex mclk_lock; struct mutex swr_clk_lock; struct rx_swr_ctrl_data *swr_ctrl_data; @@ -307,6 +309,10 @@ static const char *const rx_macro_mux_text[] = { "ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB", "AIF4_PB" }; +static const char *const rx_macro_native_text[] = {"OFF", "ON"}; +static const struct soc_enum rx_macro_native_enum = + SOC_ENUM_SINGLE_EXT(2, rx_macro_native_text); + 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, @@ -730,22 +736,25 @@ static int rx_macro_mclk_enable(struct rx_macro_priv *rx_priv, bool mclk_enable, bool dapm) { struct regmap *regmap = dev_get_regmap(rx_priv->dev->parent, NULL); - int ret = 0; + int ret = 0, mclk_mux = MCLK_MUX0; dev_dbg(rx_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n", __func__, mclk_enable, dapm, rx_priv->rx_mclk_users); + if(rx_priv->is_native_on) + mclk_mux = MCLK_MUX1; mutex_lock(&rx_priv->mclk_lock); if (mclk_enable) { if (rx_priv->rx_mclk_users == 0) { ret = bolero_request_clock(rx_priv->dev, - RX_MACRO, MCLK_MUX0, true); + RX_MACRO, mclk_mux, true); if (ret < 0) { dev_err(rx_priv->dev, "%s: rx request clock enable failed\n", __func__); goto exit; } + rx_priv->mclk_mux = mclk_mux; regcache_mark_dirty(regmap); regcache_sync_region(regmap, RX_START_OFFSET, @@ -774,7 +783,8 @@ static int rx_macro_mclk_enable(struct rx_macro_priv *rx_priv, BOLERO_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL, 0x01, 0x00); bolero_request_clock(rx_priv->dev, - RX_MACRO, MCLK_MUX0, false); + RX_MACRO, mclk_mux, false); + rx_priv->mclk_mux = MCLK_MUX0; } } exit: @@ -796,6 +806,17 @@ static int rx_macro_mclk_event(struct snd_soc_dapm_widget *w, dev_dbg(rx_dev, "%s: event = %d\n", __func__, event); switch (event) { case SND_SOC_DAPM_PRE_PMU: + /* if swr_clk_users > 0, call device down */ + if (rx_priv->swr_clk_users > 0) { + if ((rx_priv->mclk_mux == MCLK_MUX0 && + rx_priv->is_native_on) || + (rx_priv->mclk_mux == MCLK_MUX1 && + !rx_priv->is_native_on)) { + swrm_wcd_notify( + rx_priv->swr_ctrl_data[0].rx_swr_pdev, + SWR_DEVICE_DOWN, NULL); + } + } ret = rx_macro_mclk_enable(rx_priv, 1, true); break; case SND_SOC_DAPM_POST_PMD: @@ -1227,6 +1248,36 @@ static int rx_macro_mux_put(struct snd_kcontrol *kcontrol, return -EINVAL; } +static int rx_macro_get_native(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_native_on == true ? 1 : 0); + return 0; +} + +static int rx_macro_put_native(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_native_on = + (!ucontrol->value.integer.value[0] ? false : true); + return 0; +} + static void rx_macro_idle_detect_control(struct snd_soc_codec *codec, struct rx_macro_priv *rx_priv, int interp, int event) @@ -1695,6 +1746,9 @@ static const struct snd_kcontrol_new rx_macro_snd_controls[] = { SOC_SINGLE_EXT("RX_COMP2 Switch", SND_SOC_NOPM, RX_MACRO_COMP2, 1, 0, rx_macro_get_compander, rx_macro_set_compander), + SOC_ENUM_EXT("RX_Native", rx_macro_native_enum, rx_macro_get_native, + rx_macro_put_native), + SOC_SINGLE_SX_TLV("IIR0 INP0 Volume", BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0, -84, 40, digital_gain),