diff options
| -rw-r--r-- | sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c | 26 | ||||
| -rw-r--r-- | sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.h | 5 | ||||
| -rw-r--r-- | sound/soc/codecs/wcd934x/wcd934x.c | 60 |
3 files changed, 91 insertions, 0 deletions
diff --git a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c index 306a4352ca46..225b3a755f66 100644 --- a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c +++ b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c @@ -466,6 +466,11 @@ static void wcd_cntl_do_shutdown(struct wcd_dsp_cntl *cntl) /* Put WDSP in reset state */ snd_soc_update_bits(codec, WCD934X_CPE_SS_CPE_CTL, 0x02, 0x00); + + /* If DSP transitions from boot to shutdown, then vote for SVS */ + if (cntl->is_wdsp_booted) + cntl->cdc_cb->cdc_vote_svs(codec, true); + cntl->is_wdsp_booted = false; } static int wcd_cntl_do_boot(struct wcd_dsp_cntl *cntl) @@ -507,6 +512,7 @@ static int wcd_cntl_do_boot(struct wcd_dsp_cntl *cntl) if (cntl->debug_mode) { wait_for_completion(&cntl->boot_complete); dev_dbg(codec->dev, "%s: WDSP booted in dbg mode\n", __func__); + cntl->is_wdsp_booted = true; goto done; } @@ -521,11 +527,16 @@ static int wcd_cntl_do_boot(struct wcd_dsp_cntl *cntl) } dev_dbg(codec->dev, "%s: WDSP booted in normal mode\n", __func__); + cntl->is_wdsp_booted = true; /* Enable WDOG */ snd_soc_update_bits(codec, WCD934X_CPE_SS_WDOG_CFG, 0x10, 0x10); done: + /* If dsp booted up, then remove vote on SVS */ + if (cntl->is_wdsp_booted) + cntl->cdc_cb->cdc_vote_svs(codec, false); + return ret; err_boot: /* call shutdown to perform cleanup */ @@ -899,6 +910,14 @@ void wcd_dsp_cntl_init(struct snd_soc_codec *codec, return; } + if (!params->cb || !params->cb->cdc_clk_en || + !params->cb->cdc_vote_svs) { + dev_err(codec->dev, + "%s: clk_en and vote_svs callbacks must be provided\n", + __func__); + return; + } + control = kzalloc(sizeof(*control), GFP_KERNEL); if (!(control)) return; @@ -912,6 +931,13 @@ void wcd_dsp_cntl_init(struct snd_soc_codec *codec, mutex_init(&control->clk_mutex); /* + * The default state of WDSP is in SVS mode. + * Vote for SVS now, the vote will be removed only + * after DSP is booted up. + */ + control->cdc_cb->cdc_vote_svs(codec, true); + + /* * If this is the last component needed by master to be ready, * then component_bind will be called within the component_add. * Hence, the data pointer should be assigned before component_add, diff --git a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.h b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.h index caa7edc02da8..3d6db776a0b5 100644 --- a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.h +++ b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.h @@ -20,6 +20,8 @@ struct wcd_dsp_cdc_cb { /* Callback to enable codec clock */ int (*cdc_clk_en)(struct snd_soc_codec *, bool); + /* Callback to vote and unvote for SVS2 mode */ + void (*cdc_vote_svs)(struct snd_soc_codec *, bool); }; struct wcd_dsp_irq_info { @@ -83,6 +85,9 @@ struct wcd_dsp_cntl { /* clk related */ struct mutex clk_mutex; bool is_clk_enabled; + + /* Keep track of WDSP boot status */ + bool is_wdsp_booted; }; void wcd_dsp_cntl_init(struct snd_soc_codec *codec, diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c index 26059caba07a..364aa17ea7e6 100644 --- a/sound/soc/codecs/wcd934x/wcd934x.c +++ b/sound/soc/codecs/wcd934x/wcd934x.c @@ -488,6 +488,10 @@ struct tavil_priv { /* cal info for codec */ struct fw_info *fw_data; + + /* SVS voting related */ + struct mutex svs_mutex; + int svs_ref_cnt; }; static const struct tavil_reg_mask_val tavil_spkr_default[] = { @@ -715,6 +719,36 @@ void *tavil_get_afe_config(struct snd_soc_codec *codec, } EXPORT_SYMBOL(tavil_get_afe_config); +static void tavil_vote_svs(struct tavil_priv *tavil, bool vote) +{ + struct wcd9xxx *wcd9xxx; + + wcd9xxx = tavil->wcd9xxx; + + mutex_lock(&tavil->svs_mutex); + if (vote) { + tavil->svs_ref_cnt++; + if (tavil->svs_ref_cnt == 1) + regmap_update_bits(wcd9xxx->regmap, + WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_0, + 0x01, 0x01); + } else { + /* Do not decrement ref count if it is already 0 */ + if (tavil->svs_ref_cnt == 0) + goto done; + + tavil->svs_ref_cnt--; + if (tavil->svs_ref_cnt == 0) + regmap_update_bits(wcd9xxx->regmap, + WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_0, + 0x01, 0x00); + } +done: + dev_dbg(tavil->dev, "%s: vote = %s, updated ref cnt = %u\n", __func__, + vote ? "vote" : "Unvote", tavil->svs_ref_cnt); + mutex_unlock(&tavil->svs_mutex); +} + static int tavil_vi_feed_mixer_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -5664,6 +5698,7 @@ static int __tavil_cdc_mclk_enable_locked(struct tavil_priv *tavil, dev_dbg(tavil->dev, "%s: mclk_enable = %u\n", __func__, enable); if (enable) { + tavil_vote_svs(tavil, true); ret = tavil_cdc_req_mclk_enable(tavil, true); if (ret) goto done; @@ -5671,6 +5706,7 @@ static int __tavil_cdc_mclk_enable_locked(struct tavil_priv *tavil, set_bit(AUDIO_NOMINAL, &tavil->status_mask); } else { tavil_cdc_req_mclk_enable(tavil, false); + tavil_vote_svs(tavil, false); } done: @@ -6148,8 +6184,16 @@ static void tavil_enable_sido_buck(struct snd_soc_codec *codec) tavil->resmgr->sido_input_src = SIDO_SOURCE_RCO_BG; } +static void tavil_cdc_vote_svs(struct snd_soc_codec *codec, bool vote) +{ + struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec); + + return tavil_vote_svs(tavil, vote); +} + struct wcd_dsp_cdc_cb cdc_cb = { .cdc_clk_en = tavil_codec_internal_rco_ctrl, + .cdc_vote_svs = tavil_cdc_vote_svs, }; static int tavil_wdsp_initialize(struct snd_soc_codec *codec) @@ -6326,6 +6370,12 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec) tavil_wdsp_initialize(codec); + /* + * Once the codec initialization is completed, the svs vote + * can be released allowing the codec to go to SVS2. + */ + tavil_vote_svs(tavil, false); + return ret; err_pdata: @@ -6870,6 +6920,14 @@ static int tavil_probe(struct platform_device *pdev) mutex_init(&tavil->swr.write_mutex); mutex_init(&tavil->swr.clk_mutex); mutex_init(&tavil->codec_mutex); + mutex_init(&tavil->svs_mutex); + + /* + * Codec hardware by default comes up in SVS mode. + * Initialize the svs_ref_cnt to 1 to reflect the hardware + * state in the driver. + */ + tavil->svs_ref_cnt = 1; /* * Init resource manager so that if child nodes such as SoundWire @@ -6932,6 +6990,7 @@ err_clk: wcd_resmgr_remove(tavil->resmgr); err_resmgr: mutex_destroy(&tavil->micb_lock); + mutex_destroy(&tavil->svs_mutex); mutex_destroy(&tavil->codec_mutex); mutex_destroy(&tavil->swr.read_mutex); mutex_destroy(&tavil->swr.write_mutex); @@ -6950,6 +7009,7 @@ static int tavil_remove(struct platform_device *pdev) return -EINVAL; mutex_destroy(&tavil->micb_lock); + mutex_destroy(&tavil->svs_mutex); mutex_destroy(&tavil->codec_mutex); mutex_destroy(&tavil->swr.read_mutex); mutex_destroy(&tavil->swr.write_mutex); |
