summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/cs35l41.c
diff options
context:
space:
mode:
authorLucas Tanure <lucas.tanure@collabora.com>2023-02-23 08:43:23 +0000
committerMark Brown <broonie@kernel.org>2023-03-05 23:36:43 +0000
commitf5030564938be112183ba3df0cdd6dea3f694c2e (patch)
treefb28143a527bfa85eebcf316fc1c7b85a8f93b96 /sound/soc/codecs/cs35l41.c
parentbe9457f12e84437259707415364cc5fc96041ed6 (diff)
ALSA: cs35l41: Add shared boost feature
Shared boost allows two amplifiers to share a single boost circuit by communicating on the MDSYNC bus. The passive amplifier does not control the boost and receives data from the active amplifier. Shared Boost is not supported in HDA Systems. Based on David Rhodes shared boost patches. Signed-off-by: Lucas Tanure <lucas.tanure@collabora.com> Reviewed-by: David Rhodes <david.rhodes@cirrus.com> Link: https://lore.kernel.org/r/20230223084324.9076-4-lucas.tanure@collabora.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/codecs/cs35l41.c')
-rw-r--r--sound/soc/codecs/cs35l41.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index c006364e5335..1624510d09c0 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -360,6 +360,7 @@ static void cs35l41_boost_enable(struct cs35l41_private *cs35l41, unsigned int e
{
switch (cs35l41->hw_cfg.bst_type) {
case CS35L41_INT_BOOST:
+ case CS35L41_SHD_BOOST_ACTV:
enable = enable ? CS35L41_BST_EN_DEFAULT : CS35L41_BST_DIS_FET_OFF;
regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK,
enable << CS35L41_BST_EN_SHIFT);
@@ -455,6 +456,12 @@ static irqreturn_t cs35l41_irq(int irq, void *data)
ret = IRQ_HANDLED;
}
+ if (status[2] & CS35L41_PLL_LOCK) {
+ regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS3, CS35L41_PLL_LOCK);
+ complete(&cs35l41->pll_lock);
+ ret = IRQ_HANDLED;
+ }
+
done:
pm_runtime_mark_last_busy(cs35l41->dev);
pm_runtime_put_autosuspend(cs35l41->dev);
@@ -492,10 +499,12 @@ static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w,
cs35l41_pup_patch,
ARRAY_SIZE(cs35l41_pup_patch));
- cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 1);
+ cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 1,
+ &cs35l41->pll_lock);
break;
case SND_SOC_DAPM_POST_PMD:
- cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0);
+ cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0,
+ &cs35l41->pll_lock);
ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
val, val & CS35L41_PDN_DONE_MASK,
@@ -802,6 +811,10 @@ static const struct snd_pcm_hw_constraint_list cs35l41_constraints = {
static int cs35l41_pcm_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
+ struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
+
+ reinit_completion(&cs35l41->pll_lock);
+
if (substream->runtime)
return snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
@@ -1252,6 +1265,10 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *
/* Set interrupt masks for critical errors */
regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1,
CS35L41_INT1_MASK_DEFAULT);
+ if (cs35l41->hw_cfg.bst_type == CS35L41_SHD_BOOST_PASS ||
+ cs35l41->hw_cfg.bst_type == CS35L41_SHD_BOOST_ACTV)
+ regmap_update_bits(cs35l41->regmap, CS35L41_IRQ1_MASK3, CS35L41_INT3_PLL_LOCK_MASK,
+ 0 << CS35L41_INT3_PLL_LOCK_SHIFT);
ret = devm_request_threaded_irq(cs35l41->dev, cs35l41->irq, NULL, cs35l41_irq,
IRQF_ONESHOT | IRQF_SHARED | irq_pol,
@@ -1275,6 +1292,8 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *
if (ret < 0)
goto err;
+ init_completion(&cs35l41->pll_lock);
+
pm_runtime_set_autosuspend_delay(cs35l41->dev, 3000);
pm_runtime_use_autosuspend(cs35l41->dev);
pm_runtime_mark_last_busy(cs35l41->dev);
@@ -1317,6 +1336,10 @@ void cs35l41_remove(struct cs35l41_private *cs35l41)
pm_runtime_disable(cs35l41->dev);
regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF);
+ if (cs35l41->hw_cfg.bst_type == CS35L41_SHD_BOOST_PASS ||
+ cs35l41->hw_cfg.bst_type == CS35L41_SHD_BOOST_ACTV)
+ regmap_update_bits(cs35l41->regmap, CS35L41_IRQ1_MASK3, CS35L41_INT3_PLL_LOCK_MASK,
+ 1 << CS35L41_INT3_PLL_LOCK_SHIFT);
kfree(cs35l41->dsp.system_name);
wm_adsp2_remove(&cs35l41->dsp);
cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);