From 4658de99d43cd740e019e7fd124b4128f8f4027f Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Thu, 23 Feb 2023 08:43:21 +0000 Subject: ASoC: cs35l41: Only disable internal boost In error situations, only the internal boost case should be disabled and re-enabled. Also, for other boost cases re-enabling the boost to the default internal boost config is incorrect. Fixes: 6450ef559056 ("ASoC: cs35l41: CS35L41 Boosted Smart Amplifier") Signed-off-by: Lucas Tanure Acked-by: Charles Keepax Reviewed-by: David Rhodes Link: https://lore.kernel.org/r/20230223084324.9076-2-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l41.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index c223d83e02cf..f2b5032daa6a 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -356,6 +356,19 @@ static const struct snd_kcontrol_new cs35l41_aud_controls[] = { WM_ADSP_FW_CONTROL("DSP1", 0), }; +static void cs35l41_boost_enable(struct cs35l41_private *cs35l41, unsigned int enable) +{ + switch (cs35l41->hw_cfg.bst_type) { + case CS35L41_INT_BOOST: + 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); + break; + default: + break; + } +} + static irqreturn_t cs35l41_irq(int irq, void *data) { struct cs35l41_private *cs35l41 = data; @@ -431,8 +444,7 @@ static irqreturn_t cs35l41_irq(int irq, void *data) if (status[0] & CS35L41_BST_OVP_ERR) { dev_crit_ratelimited(cs35l41->dev, "VBST Over Voltage error\n"); - regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, - CS35L41_BST_EN_MASK, 0); + cs35l41_boost_enable(cs35l41, 0); regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, CS35L41_BST_OVP_ERR); regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); @@ -441,16 +453,13 @@ static irqreturn_t cs35l41_irq(int irq, void *data) CS35L41_BST_OVP_ERR_RLS); regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, CS35L41_BST_OVP_ERR_RLS, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, - CS35L41_BST_EN_MASK, - CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT); + cs35l41_boost_enable(cs35l41, 1); ret = IRQ_HANDLED; } if (status[0] & CS35L41_BST_DCM_UVP_ERR) { dev_crit_ratelimited(cs35l41->dev, "DCM VBST Under Voltage Error\n"); - regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, - CS35L41_BST_EN_MASK, 0); + cs35l41_boost_enable(cs35l41, 0); regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, CS35L41_BST_DCM_UVP_ERR); regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); @@ -459,16 +468,13 @@ static irqreturn_t cs35l41_irq(int irq, void *data) CS35L41_BST_UVP_ERR_RLS); regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, CS35L41_BST_UVP_ERR_RLS, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, - CS35L41_BST_EN_MASK, - CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT); + cs35l41_boost_enable(cs35l41, 1); ret = IRQ_HANDLED; } if (status[0] & CS35L41_BST_SHORT_ERR) { dev_crit_ratelimited(cs35l41->dev, "LBST error: powering off!\n"); - regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, - CS35L41_BST_EN_MASK, 0); + cs35l41_boost_enable(cs35l41, 0); regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, CS35L41_BST_SHORT_ERR); regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); @@ -477,9 +483,7 @@ static irqreturn_t cs35l41_irq(int irq, void *data) CS35L41_BST_SHORT_ERR_RLS); regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, CS35L41_BST_SHORT_ERR_RLS, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, - CS35L41_BST_EN_MASK, - CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT); + cs35l41_boost_enable(cs35l41, 1); ret = IRQ_HANDLED; } -- cgit From be9457f12e84437259707415364cc5fc96041ed6 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Thu, 23 Feb 2023 08:43:22 +0000 Subject: ASoC: cs35l41: Refactor error release code Add cs35l41_error_release function to handle error release sequences. Signed-off-by: Lucas Tanure Acked-by: Charles Keepax Reviewed-by: David Rhodes Link: https://lore.kernel.org/r/20230223084324.9076-3-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l41.c | 64 ++++++++++++---------------------------------- 1 file changed, 16 insertions(+), 48 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index f2b5032daa6a..c006364e5335 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -369,6 +369,16 @@ static void cs35l41_boost_enable(struct cs35l41_private *cs35l41, unsigned int e } } + +static void cs35l41_error_release(struct cs35l41_private *cs35l41, unsigned int irq_err_bit, + unsigned int rel_err_bit) +{ + regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, irq_err_bit); + regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); + regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, rel_err_bit, rel_err_bit); + regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, rel_err_bit, 0); +} + static irqreturn_t cs35l41_irq(int irq, void *data) { struct cs35l41_private *cs35l41 = data; @@ -405,54 +415,26 @@ static irqreturn_t cs35l41_irq(int irq, void *data) */ if (status[0] & CS35L41_AMP_SHORT_ERR) { dev_crit_ratelimited(cs35l41->dev, "Amp short error\n"); - regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, - CS35L41_AMP_SHORT_ERR); - regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_AMP_SHORT_ERR_RLS, - CS35L41_AMP_SHORT_ERR_RLS); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_AMP_SHORT_ERR_RLS, 0); + cs35l41_error_release(cs35l41, CS35L41_AMP_SHORT_ERR, CS35L41_AMP_SHORT_ERR_RLS); ret = IRQ_HANDLED; } if (status[0] & CS35L41_TEMP_WARN) { dev_crit_ratelimited(cs35l41->dev, "Over temperature warning\n"); - regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, - CS35L41_TEMP_WARN); - regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_TEMP_WARN_ERR_RLS, - CS35L41_TEMP_WARN_ERR_RLS); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_TEMP_WARN_ERR_RLS, 0); + cs35l41_error_release(cs35l41, CS35L41_TEMP_WARN, CS35L41_TEMP_WARN_ERR_RLS); ret = IRQ_HANDLED; } if (status[0] & CS35L41_TEMP_ERR) { dev_crit_ratelimited(cs35l41->dev, "Over temperature error\n"); - regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, - CS35L41_TEMP_ERR); - regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_TEMP_ERR_RLS, - CS35L41_TEMP_ERR_RLS); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_TEMP_ERR_RLS, 0); + cs35l41_error_release(cs35l41, CS35L41_TEMP_ERR, CS35L41_TEMP_ERR_RLS); ret = IRQ_HANDLED; } if (status[0] & CS35L41_BST_OVP_ERR) { dev_crit_ratelimited(cs35l41->dev, "VBST Over Voltage error\n"); cs35l41_boost_enable(cs35l41, 0); - regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, - CS35L41_BST_OVP_ERR); - regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_BST_OVP_ERR_RLS, - CS35L41_BST_OVP_ERR_RLS); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_BST_OVP_ERR_RLS, 0); + cs35l41_error_release(cs35l41, CS35L41_BST_OVP_ERR, CS35L41_BST_OVP_ERR_RLS); cs35l41_boost_enable(cs35l41, 1); ret = IRQ_HANDLED; } @@ -460,14 +442,7 @@ static irqreturn_t cs35l41_irq(int irq, void *data) if (status[0] & CS35L41_BST_DCM_UVP_ERR) { dev_crit_ratelimited(cs35l41->dev, "DCM VBST Under Voltage Error\n"); cs35l41_boost_enable(cs35l41, 0); - regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, - CS35L41_BST_DCM_UVP_ERR); - regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_BST_UVP_ERR_RLS, - CS35L41_BST_UVP_ERR_RLS); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_BST_UVP_ERR_RLS, 0); + cs35l41_error_release(cs35l41, CS35L41_BST_DCM_UVP_ERR, CS35L41_BST_UVP_ERR_RLS); cs35l41_boost_enable(cs35l41, 1); ret = IRQ_HANDLED; } @@ -475,14 +450,7 @@ static irqreturn_t cs35l41_irq(int irq, void *data) if (status[0] & CS35L41_BST_SHORT_ERR) { dev_crit_ratelimited(cs35l41->dev, "LBST error: powering off!\n"); cs35l41_boost_enable(cs35l41, 0); - regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, - CS35L41_BST_SHORT_ERR); - regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_BST_SHORT_ERR_RLS, - CS35L41_BST_SHORT_ERR_RLS); - regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, - CS35L41_BST_SHORT_ERR_RLS, 0); + cs35l41_error_release(cs35l41, CS35L41_BST_SHORT_ERR, CS35L41_BST_SHORT_ERR_RLS); cs35l41_boost_enable(cs35l41, 1); ret = IRQ_HANDLED; } -- cgit From f5030564938be112183ba3df0cdd6dea3f694c2e Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Thu, 23 Feb 2023 08:43:23 +0000 Subject: 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 Reviewed-by: David Rhodes Link: https://lore.kernel.org/r/20230223084324.9076-4-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/pci/hda/cs35l41_hda.c | 6 ++-- sound/soc/codecs/cs35l41-lib.c | 73 +++++++++++++++++++++++++++++++++++++++++- sound/soc/codecs/cs35l41.c | 27 ++++++++++++++-- sound/soc/codecs/cs35l41.h | 1 + 4 files changed, 101 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 75020edd39e7..b5210abb5141 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -514,13 +514,13 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action) break; case HDA_GEN_PCM_ACT_PREPARE: mutex_lock(&cs35l41->fw_mutex); - ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 1); + ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 1, NULL); mutex_unlock(&cs35l41->fw_mutex); break; case HDA_GEN_PCM_ACT_CLEANUP: mutex_lock(&cs35l41->fw_mutex); regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); - ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 0); + ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 0, NULL); mutex_unlock(&cs35l41->fw_mutex); break; case HDA_GEN_PCM_ACT_CLOSE: @@ -672,7 +672,7 @@ static int cs35l41_runtime_suspend(struct device *dev) if (cs35l41->playback_started) { regmap_multi_reg_write(cs35l41->regmap, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); - cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0); + cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0, NULL); regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT); if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c index 04be71435491..8538e2871c5f 100644 --- a/sound/soc/codecs/cs35l41-lib.c +++ b/sound/soc/codecs/cs35l41-lib.c @@ -1114,12 +1114,31 @@ static const struct reg_sequence cs35l41_reset_to_safe[] = { { 0x00000040, 0x00000033 }, }; +static const struct reg_sequence cs35l41_actv_seq[] = { + /* SYNC_BST_CTL_RX_EN = 1; SYNC_BST_CTL_TX_EN = 1 */ + {CS35L41_MDSYNC_EN, 0x00003000}, + /* BST_CTL_SEL = MDSYNC */ + {CS35L41_BSTCVRT_VCTRL2, 0x00000002}, +}; + +static const struct reg_sequence cs35l41_pass_seq[] = { + /* SYNC_BST_CTL_RX_EN = 0; SYNC_BST_CTL_TX_EN = 1 */ + {CS35L41_MDSYNC_EN, 0x00001000}, + /* BST_EN = 0 */ + {CS35L41_PWR_CTRL2, 0x00003300}, + /* BST_CTL_SEL = MDSYNC */ + {CS35L41_BSTCVRT_VCTRL2, 0x00000002}, +}; + int cs35l41_init_boost(struct device *dev, struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg) { int ret; switch (hw_cfg->bst_type) { + case CS35L41_SHD_BOOST_ACTV: + regmap_multi_reg_write(regmap, cs35l41_actv_seq, ARRAY_SIZE(cs35l41_actv_seq)); + fallthrough; case CS35L41_INT_BOOST: ret = cs35l41_boost_config(dev, regmap, hw_cfg->bst_ind, hw_cfg->bst_cap, hw_cfg->bst_ipk); @@ -1138,6 +1157,10 @@ int cs35l41_init_boost(struct device *dev, struct regmap *regmap, ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK, CS35L41_BST_DIS_FET_OFF << CS35L41_BST_EN_SHIFT); break; + case CS35L41_SHD_BOOST_PASS: + ret = regmap_multi_reg_write(regmap, cs35l41_pass_seq, + ARRAY_SIZE(cs35l41_pass_seq)); + break; default: dev_err(dev, "Boost type %d not supported\n", hw_cfg->bst_type); ret = -EINVAL; @@ -1165,11 +1188,59 @@ bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type) } EXPORT_SYMBOL_GPL(cs35l41_safe_reset); -int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable) +int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable, + struct completion *pll_lock) { int ret; + unsigned int gpio1_func, pad_control, pwr_ctrl1, pwr_ctrl3; + struct reg_sequence cs35l41_mdsync_down_seq[] = { + {CS35L41_PWR_CTRL3, 0}, + {CS35L41_GPIO_PAD_CONTROL, 0}, + {CS35L41_PWR_CTRL1, 0, 3000}, + }; + struct reg_sequence cs35l41_mdsync_up_seq[] = { + {CS35L41_PWR_CTRL3, 0}, + {CS35L41_PWR_CTRL1, 0x00000000, 3000}, + {CS35L41_PWR_CTRL1, 0x00000001, 3000}, + }; switch (b_type) { + case CS35L41_SHD_BOOST_ACTV: + case CS35L41_SHD_BOOST_PASS: + regmap_read(regmap, CS35L41_PWR_CTRL3, &pwr_ctrl3); + regmap_read(regmap, CS35L41_GPIO_PAD_CONTROL, &pad_control); + + pwr_ctrl3 &= ~CS35L41_SYNC_EN_MASK; + pwr_ctrl1 = enable << CS35L41_GLOBAL_EN_SHIFT; + + gpio1_func = enable ? CS35L41_GPIO1_MDSYNC : CS35L41_GPIO1_HIZ; + gpio1_func <<= CS35L41_GPIO1_CTRL_SHIFT; + + pad_control &= ~CS35L41_GPIO1_CTRL_MASK; + pad_control |= gpio1_func & CS35L41_GPIO1_CTRL_MASK; + + cs35l41_mdsync_down_seq[0].def = pwr_ctrl3; + cs35l41_mdsync_down_seq[1].def = pad_control; + cs35l41_mdsync_down_seq[2].def = pwr_ctrl1; + ret = regmap_multi_reg_write(regmap, cs35l41_mdsync_down_seq, + ARRAY_SIZE(cs35l41_mdsync_down_seq)); + if (!enable) + break; + + if (!pll_lock) + return -EINVAL; + + ret = wait_for_completion_timeout(pll_lock, msecs_to_jiffies(1000)); + if (ret == 0) { + ret = -ETIMEDOUT; + } else { + regmap_read(regmap, CS35L41_PWR_CTRL3, &pwr_ctrl3); + pwr_ctrl3 |= CS35L41_SYNC_EN_MASK; + cs35l41_mdsync_up_seq[0].def = pwr_ctrl3; + ret = regmap_multi_reg_write(regmap, cs35l41_mdsync_up_seq, + ARRAY_SIZE(cs35l41_mdsync_up_seq)); + } + break; case CS35L41_INT_BOOST: ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL1, CS35L41_GLOBAL_EN_MASK, enable << CS35L41_GLOBAL_EN_SHIFT); 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); diff --git a/sound/soc/codecs/cs35l41.h b/sound/soc/codecs/cs35l41.h index c85cbc1dd333..34d967d4372b 100644 --- a/sound/soc/codecs/cs35l41.h +++ b/sound/soc/codecs/cs35l41.h @@ -33,6 +33,7 @@ struct cs35l41_private { int irq; /* GPIO for /RST */ struct gpio_desc *reset_gpio; + struct completion pll_lock; }; int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *hw_cfg); -- cgit From 38c042b59af0248a8b13f01b1a09d890997c9f6e Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 17 Feb 2023 18:52:23 +0000 Subject: ASoC: sh: rz-ssi: Update interrupt handling for half duplex channels For half duplex channels we dont have separate interrupts for Tx and Rx instead we have single interrupt Rt (where the signal for Rx and Tx is muxed). To handle such a case install a handler in case we have a dma_rt interrupt specified in the DT for the PIO mode. Note, for backward compatibility we check if the Rx and Tx interrupts are present first instead of checking Rt interrupt. Signed-off-by: Lad Prabhakar Reviewed-by: Biju Das Link: https://lore.kernel.org/r/20230217185225.43310-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rz-ssi.c | 63 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 19 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c index 5d6bae33ae34..d502aa55c5a8 100644 --- a/sound/soc/sh/rz-ssi.c +++ b/sound/soc/sh/rz-ssi.c @@ -109,6 +109,7 @@ struct rz_ssi_priv { int irq_int; int irq_tx; int irq_rx; + int irq_rt; spinlock_t lock; @@ -565,6 +566,17 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data) rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); } + if (irq == ssi->irq_rt) { + struct snd_pcm_substream *substream = strm->substream; + + if (rz_ssi_stream_is_play(ssi, substream)) { + strm->transfer(ssi, &ssi->playback); + } else { + strm->transfer(ssi, &ssi->capture); + rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); + } + } + return IRQ_HANDLED; } @@ -993,26 +1005,39 @@ static int rz_ssi_probe(struct platform_device *pdev) if (!rz_ssi_is_dma_enabled(ssi)) { /* Tx and Rx interrupts (pio only) */ ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx"); - if (ssi->irq_tx < 0) - return ssi->irq_tx; - - ret = devm_request_irq(&pdev->dev, ssi->irq_tx, - &rz_ssi_interrupt, 0, - dev_name(&pdev->dev), ssi); - if (ret < 0) - return dev_err_probe(&pdev->dev, ret, - "irq request error (dma_tx)\n"); - ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx"); - if (ssi->irq_rx < 0) - return ssi->irq_rx; - - ret = devm_request_irq(&pdev->dev, ssi->irq_rx, - &rz_ssi_interrupt, 0, - dev_name(&pdev->dev), ssi); - if (ret < 0) - return dev_err_probe(&pdev->dev, ret, - "irq request error (dma_rx)\n"); + if (ssi->irq_tx == -ENXIO && ssi->irq_rx == -ENXIO) { + ssi->irq_rt = platform_get_irq_byname(pdev, "dma_rt"); + if (ssi->irq_rt < 0) + return ssi->irq_rt; + + ret = devm_request_irq(&pdev->dev, ssi->irq_rt, + &rz_ssi_interrupt, 0, + dev_name(&pdev->dev), ssi); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "irq request error (dma_tx)\n"); + } else { + if (ssi->irq_tx < 0) + return ssi->irq_tx; + + if (ssi->irq_rx < 0) + return ssi->irq_rx; + + ret = devm_request_irq(&pdev->dev, ssi->irq_tx, + &rz_ssi_interrupt, 0, + dev_name(&pdev->dev), ssi); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "irq request error (dma_tx)\n"); + + ret = devm_request_irq(&pdev->dev, ssi->irq_rx, + &rz_ssi_interrupt, 0, + dev_name(&pdev->dev), ssi); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "irq request error (dma_rx)\n"); + } } ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); -- cgit From f5db4d00f73871988beba0277ea29cff73d38445 Mon Sep 17 00:00:00 2001 From: Kamel Bouhara Date: Wed, 22 Feb 2023 09:33:00 +0100 Subject: ASoC: tas571x: add support for TAS5733 This adds support for TAS5733. Signed-off-by: Kamel Bouhara Link: https://lore.kernel.org/r/20230222083300.218523-3-kamel.bouhara@bootlin.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas571x.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index 84ec1b527646..f39c3273b2fd 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -718,6 +718,63 @@ static const struct regmap_config tas5721_regmap_config = { .volatile_table = &tas571x_volatile_regs, }; +static const char *const tas5733_supply_names[] = { + "AVDD", + "DVDD", + "PVDD", +}; + +static const struct reg_default tas5733_reg_defaults[] = { + {TAS571X_CLK_CTRL_REG, 0x6c}, + {TAS571X_DEV_ID_REG, 0x00}, + {TAS571X_ERR_STATUS_REG, 0x00}, + {TAS571X_SYS_CTRL_1_REG, 0xa0}, + {TAS571X_SDI_REG, 0x05}, + {TAS571X_SYS_CTRL_2_REG, 0x40}, + {TAS571X_SOFT_MUTE_REG, 0x07}, + {TAS571X_MVOL_REG, 0x03ff}, + {TAS571X_CH1_VOL_REG, 0x00c0}, + {TAS571X_CH2_VOL_REG, 0x00c0}, + {TAS571X_CH3_VOL_REG, 0x00c0}, + {TAS571X_VOL_CFG_REG, 0xf0}, + {TAS571X_MODULATION_LIMIT_REG, 0x07}, + {TAS571X_IC_DELAY_CH1_REG, 0xb8}, + {TAS571X_IC_DELAY_CH2_REG, 0x60}, + {TAS571X_IC_DELAY_CH3_REG, 0xa0}, + {TAS571X_IC_DELAY_CH4_REG, 0x48}, + {TAS571X_PWM_CH_SDN_GROUP_REG, 0x30}, + {TAS571X_START_STOP_PERIOD_REG, 0x68}, + {TAS571X_OSC_TRIM_REG, 0x82}, + {TAS571X_BKND_ERR_REG, 0x02}, + {TAS571X_INPUT_MUX_REG, 0x00897772}, + {TAS571X_PWM_MUX_REG, 0x01021345}, + {TAS5717_CH1_RIGHT_CH_MIX_REG, 0x00}, + {TAS5717_CH1_LEFT_CH_MIX_REG, 0x800000}, + {TAS5717_CH2_LEFT_CH_MIX_REG, 0x00}, + {TAS5717_CH2_RIGHT_CH_MIX_REG, 0x800000}, +}; + +static const struct regmap_config tas5733_regmap_config = { + .reg_bits = 8, + .val_bits = 32, + .max_register = 0xff, + .reg_read = tas571x_reg_read, + .reg_write = tas571x_reg_write, + .reg_defaults = tas5733_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tas5733_reg_defaults), + .cache_type = REGCACHE_RBTREE, + .wr_table = &tas571x_write_regs, + .volatile_table = &tas571x_volatile_regs, +}; + +static const struct tas571x_chip tas5733_chip = { + .supply_names = tas5733_supply_names, + .num_supply_names = ARRAY_SIZE(tas5733_supply_names), + .controls = tas5717_controls, + .num_controls = ARRAY_SIZE(tas5717_controls), + .regmap_config = &tas5733_regmap_config, + .vol_reg_size = 2, +}; static const struct tas571x_chip tas5721_chip = { .supply_names = tas5721_supply_names, @@ -897,6 +954,7 @@ static const struct of_device_id tas571x_of_match[] __maybe_unused = { { .compatible = "ti,tas5717", .data = &tas5717_chip, }, { .compatible = "ti,tas5719", .data = &tas5717_chip, }, { .compatible = "ti,tas5721", .data = &tas5721_chip, }, + { .compatible = "ti,tas5733", .data = &tas5733_chip, }, { } }; MODULE_DEVICE_TABLE(of, tas571x_of_match); @@ -907,6 +965,7 @@ static const struct i2c_device_id tas571x_i2c_id[] = { { "tas5717", (kernel_ulong_t) &tas5717_chip }, { "tas5719", (kernel_ulong_t) &tas5717_chip }, { "tas5721", (kernel_ulong_t) &tas5721_chip }, + { "tas5733", (kernel_ulong_t) &tas5733_chip }, { } }; MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id); -- cgit From 075c7125b11c72e7933401d73000d6d151196072 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 17 Feb 2023 15:56:44 +0100 Subject: ASoC: fsl: Add support for QMC audio The QMC audio is an ASoC component which provides DAIs that use the QMC (QUICC Multichannel Controller) to transfer the audio data. It provides as many DAIs as the number of QMC channels it references. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Tested-by: Christophe Leroy Link: https://lore.kernel.org/r/20230217145645.1768659-10-herve.codina@bootlin.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 9 + sound/soc/fsl/Makefile | 2 + sound/soc/fsl/fsl_qmc_audio.c | 735 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 746 insertions(+) create mode 100644 sound/soc/fsl/fsl_qmc_audio.c (limited to 'sound') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 614eceda6b9e..17db29c25d96 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -172,6 +172,15 @@ config SND_MPC52xx_DMA config SND_SOC_POWERPC_DMA tristate +config SND_SOC_POWERPC_QMC_AUDIO + tristate "QMC ALSA SoC support" + depends on CPM_QMC + help + ALSA SoC Audio support using the Freescale QUICC Multichannel + Controller (QMC). + Say Y or M if you want to add support for SoC audio using Freescale + QMC. + comment "SoC Audio support for Freescale PPC boards:" config SND_SOC_MPC8610_HPCD diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index b54beb1a66fa..8db7e97d0bd5 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -28,6 +28,7 @@ snd-soc-fsl-easrc-objs := fsl_easrc.o snd-soc-fsl-xcvr-objs := fsl_xcvr.o snd-soc-fsl-aud2htx-objs := fsl_aud2htx.o snd-soc-fsl-rpmsg-objs := fsl_rpmsg.o +snd-soc-fsl-qmc-audio-objs := fsl_qmc_audio.o obj-$(CONFIG_SND_SOC_FSL_AUDMIX) += snd-soc-fsl-audmix.o obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o @@ -44,6 +45,7 @@ obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o obj-$(CONFIG_SND_SOC_FSL_XCVR) += snd-soc-fsl-xcvr.o obj-$(CONFIG_SND_SOC_FSL_AUD2HTX) += snd-soc-fsl-aud2htx.o obj-$(CONFIG_SND_SOC_FSL_RPMSG) += snd-soc-fsl-rpmsg.o +obj-$(CONFIG_SND_SOC_POWERPC_QMC_AUDIO) += snd-soc-fsl-qmc-audio.o # MPC5200 Platform Support obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c new file mode 100644 index 000000000000..7cbb8e4758cc --- /dev/null +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -0,0 +1,735 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ALSA SoC using the QUICC Multichannel Controller (QMC) + * + * Copyright 2022 CS GROUP France + * + * Author: Herve Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct qmc_dai { + char *name; + int id; + struct device *dev; + struct qmc_chan *qmc_chan; + unsigned int nb_tx_ts; + unsigned int nb_rx_ts; +}; + +struct qmc_audio { + struct device *dev; + unsigned int num_dais; + struct qmc_dai *dais; + struct snd_soc_dai_driver *dai_drivers; +}; + +struct qmc_dai_prtd { + struct qmc_dai *qmc_dai; + dma_addr_t dma_buffer_start; + dma_addr_t period_ptr_submitted; + dma_addr_t period_ptr_ended; + dma_addr_t dma_buffer_end; + size_t period_size; + struct snd_pcm_substream *substream; +}; + +static int qmc_audio_pcm_construct(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct snd_card *card = rtd->card->snd_card; + int ret; + + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev, + 64*1024, 64*1024); + return 0; +} + +static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + + prtd->dma_buffer_start = runtime->dma_addr; + prtd->dma_buffer_end = runtime->dma_addr + params_buffer_bytes(params); + prtd->period_size = params_period_bytes(params); + prtd->period_ptr_submitted = prtd->dma_buffer_start; + prtd->period_ptr_ended = prtd->dma_buffer_start; + prtd->substream = substream; + + return 0; +} + +static void qmc_audio_pcm_write_complete(void *context) +{ + struct qmc_dai_prtd *prtd = context; + int ret; + + prtd->period_ptr_ended += prtd->period_size; + if (prtd->period_ptr_ended >= prtd->dma_buffer_end) + prtd->period_ptr_ended = prtd->dma_buffer_start; + + prtd->period_ptr_submitted += prtd->period_size; + if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) + prtd->period_ptr_submitted = prtd->dma_buffer_start; + + ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); + if (ret) { + dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", + ret); + } + + snd_pcm_period_elapsed(prtd->substream); +} + +static void qmc_audio_pcm_read_complete(void *context, size_t length) +{ + struct qmc_dai_prtd *prtd = context; + int ret; + + if (length != prtd->period_size) { + dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n", + length, prtd->period_size); + } + + prtd->period_ptr_ended += prtd->period_size; + if (prtd->period_ptr_ended >= prtd->dma_buffer_end) + prtd->period_ptr_ended = prtd->dma_buffer_start; + + prtd->period_ptr_submitted += prtd->period_size; + if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) + prtd->period_ptr_submitted = prtd->dma_buffer_start; + + ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_read_complete, prtd); + if (ret) { + dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", + ret); + } + + snd_pcm_period_elapsed(prtd->substream); +} + +static int qmc_audio_pcm_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int cmd) +{ + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + int ret; + + if (!prtd->qmc_dai) { + dev_err(component->dev, "qmc_dai is not set\n"); + return -EINVAL; + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + /* Submit first chunk ... */ + ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); + if (ret) { + dev_err(component->dev, "write_submit failed %d\n", + ret); + return ret; + } + + /* ... prepare next one ... */ + prtd->period_ptr_submitted += prtd->period_size; + if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) + prtd->period_ptr_submitted = prtd->dma_buffer_start; + + /* ... and send it */ + ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); + if (ret) { + dev_err(component->dev, "write_submit failed %d\n", + ret); + return ret; + } + } else { + /* Submit first chunk ... */ + ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_read_complete, prtd); + if (ret) { + dev_err(component->dev, "read_submit failed %d\n", + ret); + return ret; + } + + /* ... prepare next one ... */ + prtd->period_ptr_submitted += prtd->period_size; + if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) + prtd->period_ptr_submitted = prtd->dma_buffer_start; + + /* ... and send it */ + ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_read_complete, prtd); + if (ret) { + dev_err(component->dev, "write_submit failed %d\n", + ret); + return ret; + } + } + break; + + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + break; + + default: + return -EINVAL; + } + + return 0; +} + +static snd_pcm_uframes_t qmc_audio_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + + return bytes_to_frames(substream->runtime, + prtd->period_ptr_ended - prtd->dma_buffer_start); +} + +static int qmc_audio_of_xlate_dai_name(struct snd_soc_component *component, + const struct of_phandle_args *args, + const char **dai_name) +{ + struct qmc_audio *qmc_audio = dev_get_drvdata(component->dev); + struct snd_soc_dai_driver *dai_driver; + int id = args->args[0]; + int i; + + for (i = 0; i < qmc_audio->num_dais; i++) { + dai_driver = qmc_audio->dai_drivers + i; + if (dai_driver->id == id) { + *dai_name = dai_driver->name; + return 0; + } + } + + return -EINVAL; +} + +static const struct snd_pcm_hardware qmc_audio_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE, + .period_bytes_min = 32, + .period_bytes_max = 64*1024, + .periods_min = 2, + .periods_max = 2*1024, + .buffer_bytes_max = 64*1024, +}; + +static int qmc_audio_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct qmc_dai_prtd *prtd; + int ret; + + snd_soc_set_runtime_hwparams(substream, &qmc_audio_pcm_hardware); + + /* ensure that buffer size is a multiple of period size */ + ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); + if (prtd == NULL) + return -ENOMEM; + + runtime->private_data = prtd; + + return 0; +} + +static int qmc_audio_pcm_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + + kfree(prtd); + return 0; +} + +static const struct snd_soc_component_driver qmc_audio_soc_platform = { + .open = qmc_audio_pcm_open, + .close = qmc_audio_pcm_close, + .hw_params = qmc_audio_pcm_hw_params, + .trigger = qmc_audio_pcm_trigger, + .pointer = qmc_audio_pcm_pointer, + .pcm_construct = qmc_audio_pcm_construct, + .of_xlate_dai_name = qmc_audio_of_xlate_dai_name, +}; + +static unsigned int qmc_dai_get_index(struct snd_soc_dai *dai) +{ + struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai); + + return dai->driver - qmc_audio->dai_drivers; +} + +static struct qmc_dai *qmc_dai_get_data(struct snd_soc_dai *dai) +{ + struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai); + unsigned int index; + + index = qmc_dai_get_index(dai); + if (index > qmc_audio->num_dais) + return NULL; + + return qmc_audio->dais + index; +} + +/* + * The constraints for format/channel is to match with the number of 8bit + * time-slots available. + */ +static int qmc_dai_hw_rule_channels_by_format(struct qmc_dai *qmc_dai, + struct snd_pcm_hw_params *params, + unsigned int nb_ts) +{ + struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + snd_pcm_format_t format = params_format(params); + struct snd_interval ch = {0}; + + switch (snd_pcm_format_physical_width(format)) { + case 8: + ch.max = nb_ts; + break; + case 16: + ch.max = nb_ts/2; + break; + case 32: + ch.max = nb_ts/4; + break; + case 64: + ch.max = nb_ts/8; + break; + default: + dev_err(qmc_dai->dev, "format physical width %u not supported\n", + snd_pcm_format_physical_width(format)); + return -EINVAL; + } + + ch.min = ch.max ? 1 : 0; + + return snd_interval_refine(c, &ch); +} + +static int qmc_dai_hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct qmc_dai *qmc_dai = rule->private; + + return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_tx_ts); +} + +static int qmc_dai_hw_rule_capture_channels_by_format( + struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct qmc_dai *qmc_dai = rule->private; + + return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_rx_ts); +} + +static int qmc_dai_hw_rule_format_by_channels(struct qmc_dai *qmc_dai, + struct snd_pcm_hw_params *params, + unsigned int nb_ts) +{ + struct snd_mask *f_old = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + unsigned int channels = params_channels(params); + unsigned int slot_width; + struct snd_mask f_new; + unsigned int i; + + if (!channels || channels > nb_ts) { + dev_err(qmc_dai->dev, "channels %u not supported\n", + nb_ts); + return -EINVAL; + } + + slot_width = (nb_ts / channels) * 8; + + snd_mask_none(&f_new); + for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { + if (snd_mask_test(f_old, i)) { + if (snd_pcm_format_physical_width(i) <= slot_width) + snd_mask_set(&f_new, i); + } + } + + return snd_mask_refine(f_old, &f_new); +} + +static int qmc_dai_hw_rule_playback_format_by_channels( + struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct qmc_dai *qmc_dai = rule->private; + + return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_tx_ts); +} + +static int qmc_dai_hw_rule_capture_format_by_channels( + struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct qmc_dai *qmc_dai = rule->private; + + return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_rx_ts); +} + +static int qmc_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + snd_pcm_hw_rule_func_t hw_rule_channels_by_format; + snd_pcm_hw_rule_func_t hw_rule_format_by_channels; + struct qmc_dai *qmc_dai; + unsigned int frame_bits; + int ret; + + qmc_dai = qmc_dai_get_data(dai); + if (!qmc_dai) { + dev_err(dai->dev, "Invalid dai\n"); + return -EINVAL; + } + + prtd->qmc_dai = qmc_dai; + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + hw_rule_channels_by_format = qmc_dai_hw_rule_capture_channels_by_format; + hw_rule_format_by_channels = qmc_dai_hw_rule_capture_format_by_channels; + frame_bits = qmc_dai->nb_rx_ts * 8; + } else { + hw_rule_channels_by_format = qmc_dai_hw_rule_playback_channels_by_format; + hw_rule_format_by_channels = qmc_dai_hw_rule_playback_format_by_channels; + frame_bits = qmc_dai->nb_tx_ts * 8; + } + + ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + hw_rule_channels_by_format, qmc_dai, + SNDRV_PCM_HW_PARAM_FORMAT, -1); + if (ret) { + dev_err(dai->dev, "Failed to add channels rule (%d)\n", ret); + return ret; + } + + ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, + hw_rule_format_by_channels, qmc_dai, + SNDRV_PCM_HW_PARAM_CHANNELS, -1); + if (ret) { + dev_err(dai->dev, "Failed to add format rule (%d)\n", ret); + return ret; + } + + ret = snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_FRAME_BITS, + frame_bits); + if (ret < 0) { + dev_err(dai->dev, "Failed to add frame_bits constraint (%d)\n", ret); + return ret; + } + + return 0; +} + +static int qmc_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct qmc_chan_param chan_param = {0}; + struct qmc_dai *qmc_dai; + int ret; + + qmc_dai = qmc_dai_get_data(dai); + if (!qmc_dai) { + dev_err(dai->dev, "Invalid dai\n"); + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + chan_param.mode = QMC_TRANSPARENT; + chan_param.transp.max_rx_buf_size = params_period_bytes(params); + ret = qmc_chan_set_param(qmc_dai->qmc_chan, &chan_param); + if (ret) { + dev_err(dai->dev, "set param failed %d\n", + ret); + return ret; + } + } + + return 0; +} + +static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct qmc_dai *qmc_dai; + int direction; + int ret; + + qmc_dai = qmc_dai_get_data(dai); + if (!qmc_dai) { + dev_err(dai->dev, "Invalid dai\n"); + return -EINVAL; + } + + direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + QMC_CHAN_WRITE : QMC_CHAN_READ; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = qmc_chan_start(qmc_dai->qmc_chan, direction); + if (ret) + return ret; + break; + + case SNDRV_PCM_TRIGGER_STOP: + ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); + if (ret) + return ret; + ret = qmc_chan_reset(qmc_dai->qmc_chan, direction); + if (ret) + return ret; + break; + + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); + if (ret) + return ret; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_dai_ops qmc_dai_ops = { + .startup = qmc_dai_startup, + .trigger = qmc_dai_trigger, + .hw_params = qmc_dai_hw_params, +}; + +static u64 qmc_audio_formats(u8 nb_ts) +{ + u64 formats; + unsigned int chan_width; + unsigned int format_width; + int i; + + if (!nb_ts) + return 0; + + formats = 0; + chan_width = nb_ts * 8; + for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { + /* + * Support format other than little-endian (ie big-endian or + * without endianness such as 8bit formats) + */ + if (snd_pcm_format_little_endian(i) == 1) + continue; + + /* Support physical width multiple of 8bit */ + format_width = snd_pcm_format_physical_width(i); + if (format_width == 0 || format_width % 8) + continue; + + /* + * And support physical width that can fit N times in the + * channel + */ + if (format_width > chan_width || chan_width % format_width) + continue; + + formats |= (1ULL << i); + } + return formats; +} + +static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *np, + struct qmc_dai *qmc_dai, struct snd_soc_dai_driver *qmc_soc_dai_driver) +{ + struct qmc_chan_info info; + u32 val; + int ret; + + qmc_dai->dev = qmc_audio->dev; + + ret = of_property_read_u32(np, "reg", &val); + if (ret) { + dev_err(qmc_audio->dev, "%pOF: failed to read reg\n", np); + return ret; + } + qmc_dai->id = val; + + qmc_dai->name = devm_kasprintf(qmc_audio->dev, GFP_KERNEL, "%s.%d", + np->parent->name, qmc_dai->id); + + qmc_dai->qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np, + "fsl,qmc-chan"); + if (IS_ERR(qmc_dai->qmc_chan)) { + ret = PTR_ERR(qmc_dai->qmc_chan); + return dev_err_probe(qmc_audio->dev, ret, + "dai %d get QMC channel failed\n", qmc_dai->id); + } + + qmc_soc_dai_driver->id = qmc_dai->id; + qmc_soc_dai_driver->name = qmc_dai->name; + + ret = qmc_chan_get_info(qmc_dai->qmc_chan, &info); + if (ret) { + dev_err(qmc_audio->dev, "dai %d get QMC channel info failed %d\n", + qmc_dai->id, ret); + return ret; + } + dev_info(qmc_audio->dev, "dai %d QMC channel mode %d, nb_tx_ts %u, nb_rx_ts %u\n", + qmc_dai->id, info.mode, info.nb_tx_ts, info.nb_rx_ts); + + if (info.mode != QMC_TRANSPARENT) { + dev_err(qmc_audio->dev, "dai %d QMC chan mode %d is not QMC_TRANSPARENT\n", + qmc_dai->id, info.mode); + return -EINVAL; + } + qmc_dai->nb_tx_ts = info.nb_tx_ts; + qmc_dai->nb_rx_ts = info.nb_rx_ts; + + qmc_soc_dai_driver->playback.channels_min = 0; + qmc_soc_dai_driver->playback.channels_max = 0; + if (qmc_dai->nb_tx_ts) { + qmc_soc_dai_driver->playback.channels_min = 1; + qmc_soc_dai_driver->playback.channels_max = qmc_dai->nb_tx_ts; + } + qmc_soc_dai_driver->playback.formats = qmc_audio_formats(qmc_dai->nb_tx_ts); + + qmc_soc_dai_driver->capture.channels_min = 0; + qmc_soc_dai_driver->capture.channels_max = 0; + if (qmc_dai->nb_rx_ts) { + qmc_soc_dai_driver->capture.channels_min = 1; + qmc_soc_dai_driver->capture.channels_max = qmc_dai->nb_rx_ts; + } + qmc_soc_dai_driver->capture.formats = qmc_audio_formats(qmc_dai->nb_rx_ts); + + qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(info.tx_fs_rate); + qmc_soc_dai_driver->playback.rate_min = info.tx_fs_rate; + qmc_soc_dai_driver->playback.rate_max = info.tx_fs_rate; + qmc_soc_dai_driver->capture.rates = snd_pcm_rate_to_rate_bit(info.rx_fs_rate); + qmc_soc_dai_driver->capture.rate_min = info.rx_fs_rate; + qmc_soc_dai_driver->capture.rate_max = info.rx_fs_rate; + + qmc_soc_dai_driver->ops = &qmc_dai_ops; + + return 0; +} + +static int qmc_audio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct qmc_audio *qmc_audio; + struct device_node *child; + unsigned int i; + int ret; + + qmc_audio = devm_kzalloc(&pdev->dev, sizeof(*qmc_audio), GFP_KERNEL); + if (!qmc_audio) + return -ENOMEM; + + qmc_audio->dev = &pdev->dev; + + qmc_audio->num_dais = of_get_available_child_count(np); + if (qmc_audio->num_dais) { + qmc_audio->dais = devm_kcalloc(&pdev->dev, qmc_audio->num_dais, + sizeof(*qmc_audio->dais), + GFP_KERNEL); + if (!qmc_audio->dais) + return -ENOMEM; + + qmc_audio->dai_drivers = devm_kcalloc(&pdev->dev, qmc_audio->num_dais, + sizeof(*qmc_audio->dai_drivers), + GFP_KERNEL); + if (!qmc_audio->dai_drivers) + return -ENOMEM; + } + + i = 0; + for_each_available_child_of_node(np, child) { + ret = qmc_audio_dai_parse(qmc_audio, child, + qmc_audio->dais + i, + qmc_audio->dai_drivers + i); + if (ret) { + of_node_put(child); + return ret; + } + i++; + } + + + platform_set_drvdata(pdev, qmc_audio); + + ret = devm_snd_soc_register_component(qmc_audio->dev, + &qmc_audio_soc_platform, + qmc_audio->dai_drivers, + qmc_audio->num_dais); + if (ret) + return ret; + + return 0; +} + +static const struct of_device_id qmc_audio_id_table[] = { + { .compatible = "fsl,qmc-audio" }, + {} /* sentinel */ +}; +MODULE_DEVICE_TABLE(of, qmc_audio_id_table); + +static struct platform_driver qmc_audio_driver = { + .driver = { + .name = "fsl-qmc-audio", + .of_match_table = of_match_ptr(qmc_audio_id_table), + }, + .probe = qmc_audio_probe, +}; +module_platform_driver(qmc_audio_driver); + +MODULE_AUTHOR("Herve Codina "); +MODULE_DESCRIPTION("CPM/QE QMC audio driver"); +MODULE_LICENSE("GPL"); -- cgit From 00d612909e12827f77891a0bd7802855fae330da Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:42 +0000 Subject: ASoC: amd: vangogh: Remove unnecessary init function Remove empty acp5x_cs35l41_init function Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-2-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index eebf2650ad27..5bd9418919a0 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -73,11 +73,6 @@ static int acp5x_8821_init(struct snd_soc_pcm_runtime *rtd) return ret; } -static int acp5x_cs35l41_init(struct snd_soc_pcm_runtime *rtd) -{ - return 0; -} - static const unsigned int rates[] = { 48000, }; @@ -258,7 +253,6 @@ static struct snd_soc_dai_link acp5x_dai[] = { .dpcm_playback = 1, .playback_only = 1, .ops = &acp5x_cs35l41_play_ops, - .init = acp5x_cs35l41_init, SND_SOC_DAILINK_REG(acp5x_bt, cs35l41, platform), }, }; -- cgit From ddd42a12a33eb4d6e9f90a75c50e5044c83b99cf Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:43 +0000 Subject: ASoC: amd: vangogh: Small code refactor Small refactor of the code: - sort includes in alphabetical order - sort variables declarations by line length - remove unnecessary "struct snd_soc_card *card" lines - insert blank lines before return - break/unbreak some lines for better read - align defines Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-3-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 145 ++++++++++++++++--------------------- 1 file changed, 64 insertions(+), 81 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index 5bd9418919a0..f914f6327cda 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -5,34 +5,31 @@ * * Copyright 2021 Advanced Micro Devices, Inc. */ - -#include -#include -#include -#include -#include -#include - -#include +#include #include +#include #include #include +#include #include #include -#include -#include +#include +#include +#include +#include +#include +#include #include "../../codecs/nau8821.h" #include "../../codecs/cs35l41.h" - #include "acp5x.h" -#define DRV_NAME "acp5x_mach" -#define DUAL_CHANNEL 2 -#define ACP5X_NUVOTON_CODEC_DAI "nau8821-hifi" -#define VG_JUPITER 1 -#define ACP5X_NUVOTON_BCLK 3072000 -#define ACP5X_NAU8821_FREQ_OUT 12288000 +#define DRV_NAME "acp5x_mach" +#define DUAL_CHANNEL 2 +#define ACP5X_NUVOTON_CODEC_DAI "nau8821-hifi" +#define VG_JUPITER 1 +#define ACP5X_NUVOTON_BCLK 3072000 +#define ACP5X_NAU8821_FREQ_OUT 12288000 static unsigned long acp5x_machine_id; static struct snd_soc_jack vg_headset; @@ -50,16 +47,14 @@ static struct snd_soc_jack_pin acp5x_nau8821_jack_pins[] = { static int acp5x_8821_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; int ret; - struct snd_soc_card *card = rtd->card; - struct snd_soc_component *component = - asoc_rtd_to_codec(rtd, 0)->component; /* * Headset buttons map to the google Reference headset. * These can be configured by userspace. */ - ret = snd_soc_card_jack_new_pins(card, "Headset Jack", + ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", SND_JACK_HEADSET | SND_JACK_BTN_0, &vg_headset, acp5x_nau8821_jack_pins, ARRAY_SIZE(acp5x_nau8821_jack_pins)); @@ -70,6 +65,7 @@ static int acp5x_8821_init(struct snd_soc_pcm_runtime *rtd) snd_jack_set_key(vg_headset.jack, SND_JACK_BTN_0, KEY_MEDIA); nau8821_enable_jack_detect(component, &vg_headset); + return ret; } @@ -104,8 +100,7 @@ static int acp5x_8821_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_card *card = rtd->card; - struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(card); + struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(rtd->card); machine->play_i2s_instance = I2S_SP_INSTANCE; machine->cap_i2s_instance = I2S_SP_INSTANCE; @@ -118,6 +113,7 @@ static int acp5x_8821_startup(struct snd_pcm_substream *substream) snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, &constraints_sample_bits); + return 0; } @@ -126,16 +122,13 @@ static int acp5x_nau8821_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *codec_dai = - snd_soc_card_get_codec_dai(card, - ACP5X_NUVOTON_CODEC_DAI); + struct snd_soc_dai *dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); int ret; - ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_FLL_BLK, 0, - SND_SOC_CLOCK_IN); + ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); if (ret < 0) dev_err(card->dev, "can't set FS clock %d\n", ret); - ret = snd_soc_dai_set_pll(codec_dai, 0, 0, snd_soc_params_to_bclk(params), + ret = snd_soc_dai_set_pll(dai, 0, 0, snd_soc_params_to_bclk(params), params_rate(params) * 256); if (ret < 0) dev_err(card->dev, "can't set FLL: %d\n", ret); @@ -145,10 +138,9 @@ static int acp5x_nau8821_hw_params(struct snd_pcm_substream *substream, static int acp5x_cs35l41_startup(struct snd_pcm_substream *substream) { - struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_card *card = rtd->card; - struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(card); + struct acp5x_platform_info *machine = snd_soc_card_get_drvdata(rtd->card); + struct snd_pcm_runtime *runtime = substream->runtime; machine->play_i2s_instance = I2S_HS_INSTANCE; @@ -157,6 +149,7 @@ static int acp5x_cs35l41_startup(struct snd_pcm_substream *substream) &constraints_channels); snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); + return 0; } @@ -164,16 +157,16 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *codec_dai; - int ret, i; unsigned int num_codecs = rtd->dai_link->num_codecs; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *dai; unsigned int bclk_val; + int ret, i; ret = 0; for (i = 0; i < num_codecs; i++) { - codec_dai = asoc_rtd_to_codec(rtd, i); - if (strcmp(codec_dai->name, "cs35l41-pcm") == 0) { + dai = asoc_rtd_to_codec(rtd, i); + if (strcmp(dai->name, "cs35l41-pcm") == 0) { switch (params_rate(params)) { case 48000: bclk_val = 1536000; @@ -183,8 +176,8 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream, params_rate(params)); return -EINVAL; } - ret = snd_soc_component_set_sysclk(codec_dai->component, - 0, 0, bclk_val, SND_SOC_CLOCK_IN); + ret = snd_soc_component_set_sysclk(dai->component, 0, 0, + bclk_val, SND_SOC_CLOCK_IN); if (ret < 0) { dev_err(card->dev, "failed to set sysclk for CS35l41 dai\n"); return ret; @@ -216,28 +209,19 @@ static struct snd_soc_codec_conf cs35l41_conf[] = { }, }; -SND_SOC_DAILINK_DEF(acp5x_i2s, - DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.0"))); - -SND_SOC_DAILINK_DEF(acp5x_bt, - DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.1"))); - -SND_SOC_DAILINK_DEF(nau8821, - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00", - "nau8821-hifi"))); - -SND_SOC_DAILINK_DEF(cs35l41, - DAILINK_COMP_ARRAY(COMP_CODEC("spi-VLV1776:00", "cs35l41-pcm"), - COMP_CODEC("spi-VLV1776:01", "cs35l41-pcm"))); - -SND_SOC_DAILINK_DEF(platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("acp5x_i2s_dma.0"))); +SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("acp5x_i2s_dma.0"))); +SND_SOC_DAILINK_DEF(acp5x_i2s, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.0"))); +SND_SOC_DAILINK_DEF(acp5x_bt, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.1"))); +SND_SOC_DAILINK_DEF(nau8821, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00", "nau8821-hifi"))); +SND_SOC_DAILINK_DEF(cs35l41, DAILINK_COMP_ARRAY(COMP_CODEC("spi-VLV1776:00", "cs35l41-pcm"), + COMP_CODEC("spi-VLV1776:01", "cs35l41-pcm"))); static struct snd_soc_dai_link acp5x_dai[] = { { .name = "acp5x-8821-play", .stream_name = "Playback/Capture", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, .dpcm_playback = 1, .dpcm_capture = 1, @@ -248,7 +232,8 @@ static struct snd_soc_dai_link acp5x_dai[] = { { .name = "acp5x-CS35L41-Stereo", .stream_name = "CS35L41 Stereo Playback", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, .dpcm_playback = 1, .playback_only = 1, @@ -258,36 +243,34 @@ static struct snd_soc_dai_link acp5x_dai[] = { }; static int platform_clock_control(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) + struct snd_kcontrol *k, int event) { struct snd_soc_dapm_context *dapm = w->dapm; struct snd_soc_card *card = dapm->card; - struct snd_soc_dai *codec_dai; + struct snd_soc_dai *dai; int ret = 0; - codec_dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); - if (!codec_dai) { + dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); + if (!dai) { dev_err(card->dev, "Codec dai not found\n"); return -EIO; } if (SND_SOC_DAPM_EVENT_OFF(event)) { - ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_INTERNAL, - 0, SND_SOC_CLOCK_IN); + ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); if (ret < 0) { dev_err(card->dev, "set sysclk err = %d\n", ret); return -EIO; } } else { - ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_FLL_BLK, 0, - SND_SOC_CLOCK_IN); + ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); if (ret < 0) - dev_err(codec_dai->dev, "can't set BLK clock %d\n", ret); - ret = snd_soc_dai_set_pll(codec_dai, 0, 0, ACP5X_NUVOTON_BCLK, - ACP5X_NAU8821_FREQ_OUT); + dev_err(dai->dev, "can't set BLK clock %d\n", ret); + ret = snd_soc_dai_set_pll(dai, 0, 0, ACP5X_NUVOTON_BCLK, ACP5X_NAU8821_FREQ_OUT); if (ret < 0) - dev_err(codec_dai->dev, "can't set FLL: %d\n", ret); + dev_err(dai->dev, "can't set FLL: %d\n", ret); } + return ret; } @@ -302,7 +285,8 @@ static const struct snd_soc_dapm_widget acp5x_8821_widgets[] = { SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_MIC("Int Mic", NULL), SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, - platform_clock_control, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + platform_clock_control, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), }; static const struct snd_soc_dapm_route acp5x_8821_audio_route[] = { @@ -336,6 +320,7 @@ static struct snd_soc_card acp5x_card = { static int acp5x_vg_quirk_cb(const struct dmi_system_id *id) { acp5x_machine_id = VG_JUPITER; + return 1; } @@ -352,12 +337,12 @@ static const struct dmi_system_id acp5x_vg_quirk_table[] = { static int acp5x_probe(struct platform_device *pdev) { - int ret; struct acp5x_platform_info *machine; + struct device *dev = &pdev->dev; struct snd_soc_card *card; + int ret; - machine = devm_kzalloc(&pdev->dev, sizeof(struct acp5x_platform_info), - GFP_KERNEL); + machine = devm_kzalloc(dev, sizeof(struct acp5x_platform_info), GFP_KERNEL); if (!machine) return -ENOMEM; @@ -365,20 +350,18 @@ static int acp5x_probe(struct platform_device *pdev) switch (acp5x_machine_id) { case VG_JUPITER: card = &acp5x_card; - acp5x_card.dev = &pdev->dev; break; default: return -ENODEV; } + card->dev = dev; platform_set_drvdata(pdev, card); snd_soc_card_set_drvdata(card, machine); - ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) { - return dev_err_probe(&pdev->dev, ret, - "snd_soc_register_card(%s) failed\n", - acp5x_card.name); - } + ret = devm_snd_soc_register_card(dev, card); + if (ret) + return dev_err_probe(dev, ret, "Register card (%s) failed\n", card->name); + return 0; } -- cgit From 50e81116ef576b58384c8829bd767b5decbc2968 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:44 +0000 Subject: ASoC: amd: vangogh: use sizeof of variable instead of struct type Use sizeof(*machine) instead of sizeof(struct acp5x_platform_info) There is a possibility of bug when variable type has changed but corresponding struct passed to the sizeof has not. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-4-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index f914f6327cda..43c80103d138 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -342,7 +342,7 @@ static int acp5x_probe(struct platform_device *pdev) struct snd_soc_card *card; int ret; - machine = devm_kzalloc(dev, sizeof(struct acp5x_platform_info), GFP_KERNEL); + machine = devm_kzalloc(dev, sizeof(*machine), GFP_KERNEL); if (!machine) return -ENOMEM; -- cgit From 88f5870dd360e6604dceff808bf960bf6ddf0377 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:45 +0000 Subject: ASoC: amd: vangogh: remove unnecessarily included headers Remove unused includes and replace by Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-5-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index 43c80103d138..a1cd52e58574 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -5,23 +5,19 @@ * * Copyright 2021 Advanced Micro Devices, Inc. */ + #include -#include #include -#include #include -#include #include -#include +#include #include #include -#include #include #include #include #include "../../codecs/nau8821.h" -#include "../../codecs/cs35l41.h" #include "acp5x.h" #define DRV_NAME "acp5x_mach" -- cgit From a719afe679b1c84413a70132a2de69c36b469144 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:46 +0000 Subject: ASoC: amd: vangogh: use for_each_rtd_components instead of for To iterate over components use for_each_rtd_components And compare to component name, so asoc_rtd_to_codec and the dai code can be removed Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-6-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 42 ++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index a1cd52e58574..e7183d8ac3a2 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -153,35 +153,37 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - unsigned int num_codecs = rtd->dai_link->num_codecs; - struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *dai; - unsigned int bclk_val; + unsigned int bclk, rate = params_rate(params); + struct snd_soc_component *comp; int ret, i; - ret = 0; - for (i = 0; i < num_codecs; i++) { - dai = asoc_rtd_to_codec(rtd, i); - if (strcmp(dai->name, "cs35l41-pcm") == 0) { - switch (params_rate(params)) { - case 48000: - bclk_val = 1536000; - break; - default: - dev_err(card->dev, "Invalid Samplerate:0x%x\n", - params_rate(params)); + switch (rate) { + case 48000: + bclk = 1536000; + break; + default: + bclk = 0; + break; + } + + for_each_rtd_components(rtd, i, comp) { + if (!(strcmp(comp->name, "spi-VLV1776:00")) || + !(strcmp(comp->name, "spi-VLV1776:01"))) { + if (!bclk) { + dev_err(comp->dev, "Invalid sample rate: 0x%x\n", rate); return -EINVAL; } - ret = snd_soc_component_set_sysclk(dai->component, 0, 0, - bclk_val, SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(card->dev, "failed to set sysclk for CS35l41 dai\n"); + + ret = snd_soc_component_set_sysclk(comp, 0, 0, bclk, SND_SOC_CLOCK_IN); + if (ret) { + dev_err(comp->dev, "failed to set SYSCLK: %d\n", ret); return ret; } } } - return ret; + return 0; + } static const struct snd_soc_ops acp5x_8821_ops = { -- cgit From 9490fbb85be830b9f4078775d678426335e36a64 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:47 +0000 Subject: ASoC: amd: vangogh: Check Bit Clock rate before snd_soc_dai_set_pll Check bit clock is valid before setting it with snd_soc_dai_set_pll Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-7-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index e7183d8ac3a2..c746605b63a1 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -119,13 +119,19 @@ static int acp5x_nau8821_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct snd_soc_dai *dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); - int ret; + int ret, bclk; ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); if (ret < 0) dev_err(card->dev, "can't set FS clock %d\n", ret); - ret = snd_soc_dai_set_pll(dai, 0, 0, snd_soc_params_to_bclk(params), - params_rate(params) * 256); + + bclk = snd_soc_params_to_bclk(params); + if (bclk < 0) { + dev_err(dai->dev, "Fail to get BCLK rate: %d\n", bclk); + return bclk; + } + + ret = snd_soc_dai_set_pll(dai, 0, 0, bclk, params_rate(params) * 256); if (ret < 0) dev_err(card->dev, "can't set FLL: %d\n", ret); -- cgit From ab89aa0d3bdef8cea6002c237c669f980a13b0e4 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:48 +0000 Subject: ASoC: amd: vangogh: Move nau8821 and CPU side code up for future platform Move nau8821 and CPU side code up in the source so future platforms can be added. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-8-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 97 ++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 47 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index c746605b63a1..153ce9e84a23 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -30,6 +30,11 @@ static unsigned long acp5x_machine_id; static struct snd_soc_jack vg_headset; +SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("acp5x_i2s_dma.0"))); +SND_SOC_DAILINK_DEF(acp5x_i2s, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.0"))); +SND_SOC_DAILINK_DEF(acp5x_bt, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.1"))); +SND_SOC_DAILINK_DEF(nau8821, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00", "nau8821-hifi"))); + static struct snd_soc_jack_pin acp5x_nau8821_jack_pins[] = { { .pin = "Headphone", @@ -41,6 +46,44 @@ static struct snd_soc_jack_pin acp5x_nau8821_jack_pins[] = { }, }; +static const struct snd_kcontrol_new acp5x_8821_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Int Mic"), +}; + +static int platform_clock_control(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct snd_soc_dai *dai; + int ret = 0; + + dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); + if (!dai) { + dev_err(card->dev, "Codec dai not found\n"); + return -EIO; + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(card->dev, "set sysclk err = %d\n", ret); + return -EIO; + } + } else { + ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(dai->dev, "can't set BLK clock %d\n", ret); + ret = snd_soc_dai_set_pll(dai, 0, 0, ACP5X_NUVOTON_BCLK, ACP5X_NAU8821_FREQ_OUT); + if (ret < 0) + dev_err(dai->dev, "can't set FLL: %d\n", ret); + } + + return ret; +} + static int acp5x_8821_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; @@ -138,6 +181,11 @@ static int acp5x_nau8821_hw_params(struct snd_pcm_substream *substream, return ret; } +static const struct snd_soc_ops acp5x_8821_ops = { + .startup = acp5x_8821_startup, + .hw_params = acp5x_nau8821_hw_params, +}; + static int acp5x_cs35l41_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); @@ -192,11 +240,6 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream, } -static const struct snd_soc_ops acp5x_8821_ops = { - .startup = acp5x_8821_startup, - .hw_params = acp5x_nau8821_hw_params, -}; - static const struct snd_soc_ops acp5x_cs35l41_play_ops = { .startup = acp5x_cs35l41_startup, .hw_params = acp5x_cs35l41_hw_params, @@ -213,12 +256,8 @@ static struct snd_soc_codec_conf cs35l41_conf[] = { }, }; -SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("acp5x_i2s_dma.0"))); -SND_SOC_DAILINK_DEF(acp5x_i2s, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.0"))); -SND_SOC_DAILINK_DEF(acp5x_bt, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.1"))); -SND_SOC_DAILINK_DEF(nau8821, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00", "nau8821-hifi"))); -SND_SOC_DAILINK_DEF(cs35l41, DAILINK_COMP_ARRAY(COMP_CODEC("spi-VLV1776:00", "cs35l41-pcm"), - COMP_CODEC("spi-VLV1776:01", "cs35l41-pcm"))); +SND_SOC_DAILINK_DEF(cs35l41, DAILINK_COMP_ARRAY(COMP_CODEC("spi-VLV1776:00", "cs35l41-pcm"), + COMP_CODEC("spi-VLV1776:01", "cs35l41-pcm"))); static struct snd_soc_dai_link acp5x_dai[] = { { @@ -246,43 +285,7 @@ static struct snd_soc_dai_link acp5x_dai[] = { }, }; -static int platform_clock_control(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_dapm_context *dapm = w->dapm; - struct snd_soc_card *card = dapm->card; - struct snd_soc_dai *dai; - int ret = 0; - - dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); - if (!dai) { - dev_err(card->dev, "Codec dai not found\n"); - return -EIO; - } - - if (SND_SOC_DAPM_EVENT_OFF(event)) { - ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(card->dev, "set sysclk err = %d\n", ret); - return -EIO; - } - } else { - ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); - if (ret < 0) - dev_err(dai->dev, "can't set BLK clock %d\n", ret); - ret = snd_soc_dai_set_pll(dai, 0, 0, ACP5X_NUVOTON_BCLK, ACP5X_NAU8821_FREQ_OUT); - if (ret < 0) - dev_err(dai->dev, "can't set FLL: %d\n", ret); - } - - return ret; -} -static const struct snd_kcontrol_new acp5x_8821_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Int Mic"), -}; static const struct snd_soc_dapm_widget acp5x_8821_widgets[] = { SND_SOC_DAPM_HP("Headphone", NULL), -- cgit From c10955e4bf28b058862e4f82c7eb8d6f315d8a52 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:49 +0000 Subject: ASoC: amd: vangogh: Centralize strings definition Replace occurrences of strings by their definition, avoiding bugs where the string changed, but not all places have been modified. While at it rename defines to use NAU8821 codec name instead of NUVOTON and align with the other defines. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-9-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index 153ce9e84a23..367570e5c60f 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -22,10 +22,14 @@ #define DRV_NAME "acp5x_mach" #define DUAL_CHANNEL 2 -#define ACP5X_NUVOTON_CODEC_DAI "nau8821-hifi" #define VG_JUPITER 1 -#define ACP5X_NUVOTON_BCLK 3072000 +#define ACP5X_NAU8821_BCLK 3072000 #define ACP5X_NAU8821_FREQ_OUT 12288000 +#define ACP5X_NAU8821_COMP_NAME "i2c-NVTN2020:00" +#define ACP5X_NAU8821_DAI_NAME "nau8821-hifi" +#define ACP5X_CS35L41_COMP_LNAME "spi-VLV1776:00" +#define ACP5X_CS35L41_COMP_RNAME "spi-VLV1776:01" +#define ACP5X_CS35L41_DAI_NAME "cs35l41-pcm" static unsigned long acp5x_machine_id; static struct snd_soc_jack vg_headset; @@ -33,7 +37,8 @@ static struct snd_soc_jack vg_headset; SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("acp5x_i2s_dma.0"))); SND_SOC_DAILINK_DEF(acp5x_i2s, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.0"))); SND_SOC_DAILINK_DEF(acp5x_bt, DAILINK_COMP_ARRAY(COMP_CPU("acp5x_i2s_playcap.1"))); -SND_SOC_DAILINK_DEF(nau8821, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00", "nau8821-hifi"))); +SND_SOC_DAILINK_DEF(nau8821, DAILINK_COMP_ARRAY(COMP_CODEC(ACP5X_NAU8821_COMP_NAME, + ACP5X_NAU8821_DAI_NAME))); static struct snd_soc_jack_pin acp5x_nau8821_jack_pins[] = { { @@ -60,7 +65,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, struct snd_soc_dai *dai; int ret = 0; - dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); + dai = snd_soc_card_get_codec_dai(card, ACP5X_NAU8821_DAI_NAME); if (!dai) { dev_err(card->dev, "Codec dai not found\n"); return -EIO; @@ -76,7 +81,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); if (ret < 0) dev_err(dai->dev, "can't set BLK clock %d\n", ret); - ret = snd_soc_dai_set_pll(dai, 0, 0, ACP5X_NUVOTON_BCLK, ACP5X_NAU8821_FREQ_OUT); + ret = snd_soc_dai_set_pll(dai, 0, 0, ACP5X_NAU8821_BCLK, ACP5X_NAU8821_FREQ_OUT); if (ret < 0) dev_err(dai->dev, "can't set FLL: %d\n", ret); } @@ -161,7 +166,7 @@ static int acp5x_nau8821_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *dai = snd_soc_card_get_codec_dai(card, ACP5X_NUVOTON_CODEC_DAI); + struct snd_soc_dai *dai = snd_soc_card_get_codec_dai(card, ACP5X_NAU8821_DAI_NAME); int ret, bclk; ret = snd_soc_dai_set_sysclk(dai, NAU8821_CLK_FLL_BLK, 0, SND_SOC_CLOCK_IN); @@ -221,8 +226,8 @@ static int acp5x_cs35l41_hw_params(struct snd_pcm_substream *substream, } for_each_rtd_components(rtd, i, comp) { - if (!(strcmp(comp->name, "spi-VLV1776:00")) || - !(strcmp(comp->name, "spi-VLV1776:01"))) { + if (!(strcmp(comp->name, ACP5X_CS35L41_COMP_LNAME)) || + !(strcmp(comp->name, ACP5X_CS35L41_COMP_RNAME))) { if (!bclk) { dev_err(comp->dev, "Invalid sample rate: 0x%x\n", rate); return -EINVAL; @@ -247,17 +252,19 @@ static const struct snd_soc_ops acp5x_cs35l41_play_ops = { static struct snd_soc_codec_conf cs35l41_conf[] = { { - .dlc = COMP_CODEC_CONF("spi-VLV1776:00"), + .dlc = COMP_CODEC_CONF(ACP5X_CS35L41_COMP_LNAME), .name_prefix = "Left", }, { - .dlc = COMP_CODEC_CONF("spi-VLV1776:01"), + .dlc = COMP_CODEC_CONF(ACP5X_CS35L41_COMP_RNAME), .name_prefix = "Right", }, }; -SND_SOC_DAILINK_DEF(cs35l41, DAILINK_COMP_ARRAY(COMP_CODEC("spi-VLV1776:00", "cs35l41-pcm"), - COMP_CODEC("spi-VLV1776:01", "cs35l41-pcm"))); +SND_SOC_DAILINK_DEF(cs35l41, DAILINK_COMP_ARRAY(COMP_CODEC(ACP5X_CS35L41_COMP_LNAME, + ACP5X_CS35L41_DAI_NAME), + COMP_CODEC(ACP5X_CS35L41_COMP_RNAME, + ACP5X_CS35L41_DAI_NAME))); static struct snd_soc_dai_link acp5x_dai[] = { { -- cgit From e902324826ec276e50140a462c991c37b04cd392 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 17 Feb 2023 11:08:50 +0000 Subject: ASoC: amd: vangogh: Add components prefix in structs and function names Add prefixes 8821/35l41 in structs and function names so future platforms can be added and reference the correct sound card. Also include acp5x prefix to cs35l41_conf. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20230217110850.1045250-10-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-mach.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/vangogh/acp5x-mach.c b/sound/soc/amd/vangogh/acp5x-mach.c index 367570e5c60f..e5bcd1e6eb73 100644 --- a/sound/soc/amd/vangogh/acp5x-mach.c +++ b/sound/soc/amd/vangogh/acp5x-mach.c @@ -250,7 +250,7 @@ static const struct snd_soc_ops acp5x_cs35l41_play_ops = { .hw_params = acp5x_cs35l41_hw_params, }; -static struct snd_soc_codec_conf cs35l41_conf[] = { +static struct snd_soc_codec_conf acp5x_cs35l41_conf[] = { { .dlc = COMP_CODEC_CONF(ACP5X_CS35L41_COMP_LNAME), .name_prefix = "Left", @@ -266,7 +266,7 @@ SND_SOC_DAILINK_DEF(cs35l41, DAILINK_COMP_ARRAY(COMP_CODEC(ACP5X_CS35L41_COMP_LN COMP_CODEC(ACP5X_CS35L41_COMP_RNAME, ACP5X_CS35L41_DAI_NAME))); -static struct snd_soc_dai_link acp5x_dai[] = { +static struct snd_soc_dai_link acp5x_8821_35l41_dai[] = { { .name = "acp5x-8821-play", .stream_name = "Playback/Capture", @@ -294,7 +294,7 @@ static struct snd_soc_dai_link acp5x_dai[] = { -static const struct snd_soc_dapm_widget acp5x_8821_widgets[] = { +static const struct snd_soc_dapm_widget acp5x_8821_35l41_widgets[] = { SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_MIC("Int Mic", NULL), @@ -303,7 +303,7 @@ static const struct snd_soc_dapm_widget acp5x_8821_widgets[] = { SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), }; -static const struct snd_soc_dapm_route acp5x_8821_audio_route[] = { +static const struct snd_soc_dapm_route acp5x_8821_35l41_audio_route[] = { /* HP jack connectors - unknown if we have jack detection */ { "Headphone", NULL, "HPOL" }, { "Headphone", NULL, "HPOR" }, @@ -316,17 +316,17 @@ static const struct snd_soc_dapm_route acp5x_8821_audio_route[] = { { "Int Mic", NULL, "Platform Clock" }, }; -static struct snd_soc_card acp5x_card = { +static struct snd_soc_card acp5x_8821_35l41_card = { .name = "acp5x", .owner = THIS_MODULE, - .dai_link = acp5x_dai, - .num_links = ARRAY_SIZE(acp5x_dai), - .dapm_widgets = acp5x_8821_widgets, - .num_dapm_widgets = ARRAY_SIZE(acp5x_8821_widgets), - .dapm_routes = acp5x_8821_audio_route, - .num_dapm_routes = ARRAY_SIZE(acp5x_8821_audio_route), - .codec_conf = cs35l41_conf, - .num_configs = ARRAY_SIZE(cs35l41_conf), + .dai_link = acp5x_8821_35l41_dai, + .num_links = ARRAY_SIZE(acp5x_8821_35l41_dai), + .dapm_widgets = acp5x_8821_35l41_widgets, + .num_dapm_widgets = ARRAY_SIZE(acp5x_8821_35l41_widgets), + .dapm_routes = acp5x_8821_35l41_audio_route, + .num_dapm_routes = ARRAY_SIZE(acp5x_8821_35l41_audio_route), + .codec_conf = acp5x_cs35l41_conf, + .num_configs = ARRAY_SIZE(acp5x_cs35l41_conf), .controls = acp5x_8821_controls, .num_controls = ARRAY_SIZE(acp5x_8821_controls), }; @@ -363,7 +363,7 @@ static int acp5x_probe(struct platform_device *pdev) dmi_check_system(acp5x_vg_quirk_table); switch (acp5x_machine_id) { case VG_JUPITER: - card = &acp5x_card; + card = &acp5x_8821_35l41_card; break; default: return -ENODEV; -- cgit From ae9db908517717888c4d618fdb90c02ec3fa1b3d Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 20 Feb 2023 09:58:02 +0200 Subject: ASoC: SOF: Intel: hda: Do not re-enable L1 if disabled before suspend We have a workaround in place to address a known issue with host DMA running into xruns when capture streams are running. But when resuming from Sx, we unconditionally re-enable DMI L1 without taking the workaround into account and this could lead to xruns when a suspended capture stream is restarted. To fix this rename the flag l1_support_enabled to l1_disabled in struct sof_intel_hda_dev to save the L1 disabled status which can be set/cleared when we get/put a stream and use the flag to determine if DMI L1 should enabled or not during the post_fw_run op. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230220075804.4829-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ctrl.c | 8 +++++--- sound/soc/sof/intel/hda-dsp.c | 10 ++++------ sound/soc/sof/intel/hda-stream.c | 10 ++++++++-- sound/soc/sof/intel/hda.h | 2 +- 4 files changed, 18 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 3aea36c077c9..a1037512da1f 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -158,16 +158,18 @@ void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable) */ int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; u32 val; /* enable/disable audio dsp clock gating */ val = enable ? PCI_CGCTL_ADSPDCGE : 0; snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_ADSPDCGE, val); - /* enable/disable DMI Link L1 support */ + /* disable the DMI link when requested. But enable only if it wasn't disabled previously */ val = enable ? HDA_VS_INTEL_EM2_L1SEN : 0; - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, - HDA_VS_INTEL_EM2_L1SEN, val); + if (!enable || !hda->l1_disabled) + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, + HDA_VS_INTEL_EM2_L1SEN, val); /* enable/disable audio dsp power gating */ val = enable ? 0 : PCI_PGCTL_ADSPPGD; diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 68eb06f13a1f..e3b69dbc1308 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -776,7 +776,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) } /* restore L1SEN bit */ - if (hda->l1_support_changed) + if (hda->l1_disabled) snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, HDA_VS_INTEL_EM2_L1SEN, 0); @@ -868,11 +868,9 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) } /* enable L1SEN to make sure the system can enter S0Ix */ - hda->l1_support_changed = - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - HDA_VS_INTEL_EM2, - HDA_VS_INTEL_EM2_L1SEN, - HDA_VS_INTEL_EM2_L1SEN); + if (hda->l1_disabled) + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, + HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN); /* stop the CORB/RIRB DMA if it is On */ hda_codec_suspend_cmd_io(sdev); diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 7f0fd05a96e6..d96d9cd9e62f 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -182,6 +182,7 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, struct hdac_ext_stream * hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct hdac_bus *bus = sof_to_bus(sdev); struct sof_intel_hda_stream *hda_stream; struct hdac_ext_stream *hext_stream = NULL; @@ -222,10 +223,12 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) * Workaround to address a known issue with host DMA that results * in xruns during pause/release in capture scenarios. */ - if (!(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) + if (!(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) { snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, HDA_VS_INTEL_EM2_L1SEN, 0); + hda->l1_disabled = true; + } return hext_stream; } @@ -233,6 +236,7 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) /* free a stream */ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct hdac_bus *bus = sof_to_bus(sdev); struct sof_intel_hda_stream *hda_stream; struct hdac_ext_stream *hext_stream; @@ -264,9 +268,11 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) spin_unlock_irq(&bus->reg_lock); /* Enable DMI L1 if permitted */ - if (dmi_l1_enable) + if (dmi_l1_enable) { snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN); + hda->l1_disabled = false; + } if (!found) { dev_err(sdev->dev, "%s: stream_tag %d not opened!\n", diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 45f9d4248f14..0679bebe4ad7 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -502,7 +502,7 @@ struct sof_intel_hda_dev { u32 stream_max; /* PM related */ - bool l1_support_changed;/* during suspend, is L1SEN changed or not */ + bool l1_disabled;/* is DMI link L1 disabled? */ /* DMIC device */ struct platform_device *dmic_dev; -- cgit From 1133a9aaf36510ffbb83573b8982239b5a2dbee0 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 20 Feb 2023 09:58:03 +0200 Subject: ASoC: SOF: Intel: hda: Restrict DMI L1 disable workaround The workaround to disable DMI L1 should be restricted to only the CAVS IP's. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230220075804.4829-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index d96d9cd9e62f..c37ef581637f 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -182,6 +182,7 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, struct hdac_ext_stream * hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) { + const struct sof_intel_dsp_desc *chip_info = get_chip_info(sdev->pdata); struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct hdac_bus *bus = sof_to_bus(sdev); struct sof_intel_hda_stream *hda_stream; @@ -221,9 +222,10 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) /* * Prevent DMI Link L1 entry for streams that don't support it. * Workaround to address a known issue with host DMA that results - * in xruns during pause/release in capture scenarios. + * in xruns during pause/release in capture scenarios. This is not needed for the ACE IP. */ - if (!(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) { + if (chip_info->hw_ip_version < SOF_INTEL_ACE_1_0 && + !(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) { snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, HDA_VS_INTEL_EM2_L1SEN, 0); @@ -236,6 +238,7 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) /* free a stream */ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) { + const struct sof_intel_dsp_desc *chip_info = get_chip_info(sdev->pdata); struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct hdac_bus *bus = sof_to_bus(sdev); struct sof_intel_hda_stream *hda_stream; @@ -268,7 +271,7 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) spin_unlock_irq(&bus->reg_lock); /* Enable DMI L1 if permitted */ - if (dmi_l1_enable) { + if (chip_info->hw_ip_version < SOF_INTEL_ACE_1_0 && dmi_l1_enable) { snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN); hda->l1_disabled = false; -- cgit From 2b5a30cafb2eff4e6a34bc80b1d16ed6ca5c2c71 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 20 Feb 2023 09:58:04 +0200 Subject: ASoC: SOF: Intel: MTL: Enable DMI L1 DMI L1 should be enabled unconditionally after FW boot is complete. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230220075804.4829-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 3 +++ sound/soc/sof/intel/mtl.h | 2 ++ 2 files changed, 5 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 307faad2ecf4..216fd07a3a93 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -280,6 +280,9 @@ static int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev) } hda_sdw_int_enable(sdev, true); + + /* enable DMI L1 */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, MTL_EM2, MTL_EM2_L1SEN, MTL_EM2_L1SEN); return 0; } diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h index 26418fb08807..ddc05304a9d5 100644 --- a/sound/soc/sof/intel/mtl.h +++ b/sound/soc/sof/intel/mtl.h @@ -28,6 +28,8 @@ #define MTL_HFINTIPPTR_PTR_MASK GENMASK(20, 0) #define MTL_HDA_VS_D0I3C 0x1D4A +#define MTL_EM2 0x1c44 +#define MTL_EM2_L1SEN BIT(13) #define MTL_DSP2CXCAP_PRIMARY_CORE 0x178D00 #define MTL_DSP2CXCTL_PRIMARY_CORE 0x178D04 -- cgit From 448b06ba107d925d59d02781acdd2e4ad12dda0b Mon Sep 17 00:00:00 2001 From: Benjamin Bara Date: Fri, 3 Mar 2023 11:04:03 +0100 Subject: ASoC: maxim,max9867: add "mclk" support Add basic support for the codecs' mclk. Enable it on SND_SOC_BIAS_ON, disable it on SND_SOC_BIAS_OFF. Signed-off-by: Benjamin Bara Signed-off-by: Richard Leitner Link: https://lore.kernel.org/r/20230302-max9867-v2-3-fd2036d5e825@skidata.com Signed-off-by: Mark Brown --- sound/soc/codecs/max9867.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index e161ab037bf7..ae552d72beec 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -6,6 +6,7 @@ // Copyright 2018 Ladislav Michl // +#include #include #include #include @@ -16,6 +17,7 @@ #include "max9867.h" struct max9867_priv { + struct clk *mclk; struct regmap *regmap; const struct snd_pcm_hw_constraint_list *constraints; unsigned int sysclk, pclk; @@ -577,6 +579,11 @@ static int max9867_set_bias_level(struct snd_soc_component *component, struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component); switch (level) { + case SND_SOC_BIAS_ON: + err = clk_prepare_enable(max9867->mclk); + if (err) + return err; + break; case SND_SOC_BIAS_STANDBY: if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { err = regcache_sync(max9867->regmap); @@ -595,6 +602,7 @@ static int max9867_set_bias_level(struct snd_soc_component *component, return err; regcache_mark_dirty(max9867->regmap); + clk_disable_unprepare(max9867->mclk); break; default: break; @@ -663,9 +671,16 @@ static int max9867_i2c_probe(struct i2c_client *i2c) dev_info(&i2c->dev, "device revision: %x\n", reg); ret = devm_snd_soc_register_component(&i2c->dev, &max9867_component, max9867_dai, ARRAY_SIZE(max9867_dai)); - if (ret < 0) + if (ret < 0) { dev_err(&i2c->dev, "Failed to register component: %d\n", ret); - return ret; + return ret; + } + + max9867->mclk = devm_clk_get(&i2c->dev, NULL); + if (IS_ERR(max9867->mclk)) + return PTR_ERR(max9867->mclk); + + return 0; } static const struct i2c_device_id max9867_i2c_id[] = { -- cgit From 28ce5698456ab53540093836c6fee15119cf1821 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 1 Mar 2023 13:38:00 +0200 Subject: ASoC: mchp-spdiftx: use FIELD_PREP() where possible Use directly FIELD_PREP() marco where possible. There is no need for the extra wrappers. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20230301113807.24036-2-claudiu.beznea@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-spdiftx.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c index 20d135c718b0..bf4252412f9f 100644 --- a/sound/soc/atmel/mchp-spdiftx.c +++ b/sound/soc/atmel/mchp-spdiftx.c @@ -72,11 +72,9 @@ /* Valid Bits per Sample */ #define SPDIFTX_MR_VBPS_MASK GENMASK(13, 8) -#define SPDIFTX_MR_VBPS(bps) FIELD_PREP(SPDIFTX_MR_VBPS_MASK, bps) /* Chunk Size */ #define SPDIFTX_MR_CHUNK_MASK GENMASK(19, 16) -#define SPDIFTX_MR_CHUNK(size) FIELD_PREP(SPDIFTX_MR_CHUNK_MASK, size) /* Validity Bits for Channels 1 and 2 */ #define SPDIFTX_MR_VALID1 BIT(24) @@ -89,7 +87,6 @@ /* Bytes per Sample */ #define SPDIFTX_MR_BPS_MASK GENMASK(29, 28) -#define SPDIFTX_MR_BPS(bytes) FIELD_PREP(SPDIFTX_MR_BPS_MASK, (bytes - 1)) /* * ---- Interrupt Enable/Disable/Mask/Status Register (Write/Read-only) ---- @@ -402,47 +399,47 @@ static int mchp_spdiftx_hw_params(struct snd_pcm_substream *substream, params_channels(params)); return -EINVAL; } - mr |= SPDIFTX_MR_CHUNK(dev->playback.maxburst); + mr |= FIELD_PREP(SPDIFTX_MR_CHUNK_MASK, dev->playback.maxburst); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: - mr |= SPDIFTX_MR_VBPS(8); + mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 8); break; case SNDRV_PCM_FORMAT_S16_BE: mr |= SPDIFTX_MR_ENDIAN_BIG; fallthrough; case SNDRV_PCM_FORMAT_S16_LE: - mr |= SPDIFTX_MR_VBPS(16); + mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 16); break; case SNDRV_PCM_FORMAT_S18_3BE: mr |= SPDIFTX_MR_ENDIAN_BIG; fallthrough; case SNDRV_PCM_FORMAT_S18_3LE: - mr |= SPDIFTX_MR_VBPS(18); + mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 18); break; case SNDRV_PCM_FORMAT_S20_3BE: mr |= SPDIFTX_MR_ENDIAN_BIG; fallthrough; case SNDRV_PCM_FORMAT_S20_3LE: - mr |= SPDIFTX_MR_VBPS(20); + mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 20); break; case SNDRV_PCM_FORMAT_S24_3BE: mr |= SPDIFTX_MR_ENDIAN_BIG; fallthrough; case SNDRV_PCM_FORMAT_S24_3LE: - mr |= SPDIFTX_MR_VBPS(24); + mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 24); break; case SNDRV_PCM_FORMAT_S24_BE: mr |= SPDIFTX_MR_ENDIAN_BIG; fallthrough; case SNDRV_PCM_FORMAT_S24_LE: - mr |= SPDIFTX_MR_VBPS(24); + mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 24); break; case SNDRV_PCM_FORMAT_S32_BE: mr |= SPDIFTX_MR_ENDIAN_BIG; fallthrough; case SNDRV_PCM_FORMAT_S32_LE: - mr |= SPDIFTX_MR_VBPS(32); + mr |= FIELD_PREP(SPDIFTX_MR_VBPS_MASK, 32); break; default: dev_err(dev->dev, "unsupported PCM format: %d\n", @@ -450,7 +447,7 @@ static int mchp_spdiftx_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - mr |= SPDIFTX_MR_BPS(bps); + mr |= FIELD_PREP(SPDIFTX_MR_BPS_MASK, bps - 1); switch (params_rate(params)) { case 22050: -- cgit From 0ab4bd5bf277349262065e88eb2feaaabf53584c Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 1 Mar 2023 13:38:01 +0200 Subject: ASoC: mchp-spdiftx: use regmap_update_bits() Use regmap_update_bits() instead of regmap_read(), running variable, regmap_write(). There is no need for extra variables and checks around it as regmap_update_bits() already does this. With this code becomes simpler. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20230301113807.24036-3-claudiu.beznea@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-spdiftx.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c index bf4252412f9f..e7241d819748 100644 --- a/sound/soc/atmel/mchp-spdiftx.c +++ b/sound/soc/atmel/mchp-spdiftx.c @@ -306,15 +306,10 @@ static int mchp_spdiftx_trigger(struct snd_pcm_substream *substream, int cmd, { struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai); struct mchp_spdiftx_mixer_control *ctrl = &dev->control; - u32 mr; - int running; int ret; /* do not start/stop while channel status or user data is updated */ spin_lock(&ctrl->lock); - regmap_read(dev->regmap, SPDIFTX_MR, &mr); - running = !!(mr & SPDIFTX_MR_TXEN_ENABLE); - switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_START: @@ -323,10 +318,8 @@ static int mchp_spdiftx_trigger(struct snd_pcm_substream *substream, int cmd, dev->suspend_irq = 0; fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!running) { - mr &= ~SPDIFTX_MR_TXEN_MASK; - mr |= SPDIFTX_MR_TXEN_ENABLE; - } + ret = regmap_update_bits(dev->regmap, SPDIFTX_MR, SPDIFTX_MR_TXEN_MASK, + SPDIFTX_MR_TXEN_ENABLE); break; case SNDRV_PCM_TRIGGER_SUSPEND: regmap_read(dev->regmap, SPDIFTX_IMR, &dev->suspend_irq); @@ -336,17 +329,12 @@ static int mchp_spdiftx_trigger(struct snd_pcm_substream *substream, int cmd, SPDIFTX_IR_TXUDR | SPDIFTX_IR_TXOVR); fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (running) { - mr &= ~SPDIFTX_MR_TXEN_MASK; - mr |= SPDIFTX_MR_TXEN_DISABLE; - } + ret = regmap_update_bits(dev->regmap, SPDIFTX_MR, SPDIFTX_MR_TXEN_MASK, + SPDIFTX_MR_TXEN_DISABLE); break; default: - spin_unlock(&ctrl->lock); - return -EINVAL; + ret = -EINVAL; } - - ret = regmap_write(dev->regmap, SPDIFTX_MR, mr); spin_unlock(&ctrl->lock); if (ret) dev_err(dev->dev, "unable to disable TX: %d\n", ret); -- cgit From 2d8dad4dc4d4a12afa3c31e72b60727d4c133b99 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 1 Mar 2023 13:38:02 +0200 Subject: ASoC: mchp-spdiftx: update debug message Previous debug message states that there was a failure and tx was not disabled. Which is not true as the TX in this function could also be enabled. Thus improve a bit the debug message by s/disable/start\/stop/. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20230301113807.24036-4-claudiu.beznea@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-spdiftx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c index e7241d819748..02a2fa7a42dd 100644 --- a/sound/soc/atmel/mchp-spdiftx.c +++ b/sound/soc/atmel/mchp-spdiftx.c @@ -337,7 +337,7 @@ static int mchp_spdiftx_trigger(struct snd_pcm_substream *substream, int cmd, } spin_unlock(&ctrl->lock); if (ret) - dev_err(dev->dev, "unable to disable TX: %d\n", ret); + dev_err(dev->dev, "unable to start/stop TX: %d\n", ret); return ret; } -- cgit From 129742576dd1b972ea1e671595a085e29012f7f3 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 1 Mar 2023 13:38:03 +0200 Subject: ASoC: mchp-pdmc: use FIELD_PREP() where possible Use FIELD_PREP() macro where possible instead of driver local defined macros. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20230301113807.24036-5-claudiu.beznea@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-pdmc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c index 1aed3baa9369..6ec5324fd65e 100644 --- a/sound/soc/atmel/mchp-pdmc.c +++ b/sound/soc/atmel/mchp-pdmc.c @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -49,8 +50,6 @@ #define MCHP_PDMC_MR_OSR256 (3 << 16) #define MCHP_PDMC_MR_SINCORDER_MASK GENMASK(23, 20) -#define MCHP_PDMC_MR_SINCORDER(order) (((order) << 20) & \ - MCHP_PDMC_MR_SINCORDER_MASK) #define MCHP_PDMC_MR_SINC_OSR_MASK GENMASK(27, 24) #define MCHP_PDMC_MR_SINC_OSR_DIS (0 << 24) @@ -62,8 +61,6 @@ #define MCHP_PDMC_MR_SINC_OSR_256 (6 << 24) #define MCHP_PDMC_MR_CHUNK_MASK GENMASK(31, 28) -#define MCHP_PDMC_MR_CHUNK(chunk) (((chunk) << 28) & \ - MCHP_PDMC_MR_CHUNK_MASK) /* * ---- Configuration Register (Read/Write) ---- @@ -617,10 +614,10 @@ static int mchp_pdmc_hw_params(struct snd_pcm_substream *substream, mr_val |= mchp_pdmc_mr_set_osr(dd->audio_filter_en, osr); - mr_val |= MCHP_PDMC_MR_SINCORDER(dd->sinc_order); + mr_val |= FIELD_PREP(MCHP_PDMC_MR_SINCORDER_MASK, dd->sinc_order); dd->addr.maxburst = mchp_pdmc_period_to_maxburst(snd_pcm_lib_period_bytes(substream)); - mr_val |= MCHP_PDMC_MR_CHUNK(dd->addr.maxburst); + mr_val |= FIELD_PREP(MCHP_PDMC_MR_CHUNK_MASK, dd->addr.maxburst); dev_dbg(comp->dev, "maxburst set to %d\n", dd->addr.maxburst); snd_soc_component_update_bits(comp, MCHP_PDMC_MR, -- cgit From 51124a30308e6db8658575e5d9ec1ea3cb3ba3c3 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 1 Mar 2023 13:38:04 +0200 Subject: ASoC: mchp-pdmc: return directly ret Return directly ret instead of having different branches for error and OK paths. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20230301113807.24036-6-claudiu.beznea@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-pdmc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c index 6ec5324fd65e..853a7adfd654 100644 --- a/sound/soc/atmel/mchp-pdmc.c +++ b/sound/soc/atmel/mchp-pdmc.c @@ -759,12 +759,10 @@ static int mchp_pdmc_pcm_new(struct snd_soc_pcm_runtime *rtd, int ret; ret = mchp_pdmc_add_chmap_ctls(rtd->pcm, dd); - if (ret < 0) { + if (ret < 0) dev_err(dd->dev, "failed to add channel map controls: %d\n", ret); - return ret; - } - return 0; + return ret; } static struct snd_soc_dai_driver mchp_pdmc_dai = { -- cgit From cb72b29cd5cfac20894a040e411dec70bb75097c Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 1 Mar 2023 13:38:05 +0200 Subject: ASoC: mchp-pdmc: avoid casting to/from void pointer Do not cast to and from void pointer. There is no need for this. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20230301113807.24036-7-claudiu.beznea@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-pdmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c index 853a7adfd654..81bfa98fd516 100644 --- a/sound/soc/atmel/mchp-pdmc.c +++ b/sound/soc/atmel/mchp-pdmc.c @@ -783,7 +783,7 @@ static struct snd_soc_dai_driver mchp_pdmc_dai = { /* PDMC interrupt handler */ static irqreturn_t mchp_pdmc_interrupt(int irq, void *dev_id) { - struct mchp_pdmc *dd = (struct mchp_pdmc *)dev_id; + struct mchp_pdmc *dd = dev_id; u32 isr, msr, pending; irqreturn_t ret = IRQ_NONE; @@ -1077,7 +1077,7 @@ static int mchp_pdmc_probe(struct platform_device *pdev) } ret = devm_request_irq(dev, irq, mchp_pdmc_interrupt, 0, - dev_name(&pdev->dev), (void *)dd); + dev_name(&pdev->dev), dd); if (ret < 0) { dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n", irq, ret); -- cgit From c9ef0fee3bdf8197538aadc728e475fceba113bb Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 3 Mar 2023 10:04:57 -0800 Subject: ASoC: Intel: avs: Use struct_size for struct avs_modcfg_ext size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The struct avs_modcfg_ext structure has a flexible array member for the pin_fmts array, and the size should be calculated using struct_size to prevent the potential for overflow with the allocation. Reviewed-by: Cezary Rojewski Reviewed-by: "Amadeusz Sławiński" Signed-off-by: Jacob Keller Link: https://lore.kernel.org/r/20230303180457.2457069-1-jacob.e.keller@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/path.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index 05302ab705ae..adbe23a47847 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -478,7 +478,7 @@ static int avs_modext_create(struct avs_dev *adev, struct avs_path_module *mod) int ret, i; num_pins = tcfg->generic.num_input_pins + tcfg->generic.num_output_pins; - cfg_size = sizeof(*cfg) + sizeof(*cfg->pin_fmts) * num_pins; + cfg_size = struct_size(cfg, pin_fmts, num_pins); cfg = kzalloc(cfg_size, GFP_KERNEL); if (!cfg) -- cgit From 4c2c935a278e53bf9a1713bb0a01ce299a994e9b Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 2 Mar 2023 10:46:16 +0000 Subject: ASoC: qcom: common: add kcontrol to jack pins Add Kcontrol to jack pins so that device switch in ucm can be done correctly. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230302104616.26318-1-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/common.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index 96fe80241fb4..c1f24af17506 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -180,6 +180,18 @@ err_put_np: } EXPORT_SYMBOL_GPL(qcom_snd_parse_of); +static struct snd_soc_jack_pin qcom_headset_jack_pins[] = { + /* Headset */ + { + .pin = "Mic Jack", + .mask = SND_JACK_MICROPHONE, + }, + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, +}; + int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, struct snd_soc_jack *jack, bool *jack_setup) { @@ -189,13 +201,14 @@ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, int rval, i; if (!*jack_setup) { - rval = snd_soc_card_jack_new(card, "Headset Jack", + rval = snd_soc_card_jack_new_pins(card, "Headset Jack", SND_JACK_HEADSET | SND_JACK_LINEOUT | SND_JACK_MECHANICAL | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_BTN_4 | SND_JACK_BTN_5, - jack); + jack, qcom_headset_jack_pins, + ARRAY_SIZE(qcom_headset_jack_pins)); if (rval < 0) { dev_err(card->dev, "Unable to add Headphone Jack\n"); -- cgit From cd01b5f090434e7b2661aee208745539c552f5d2 Mon Sep 17 00:00:00 2001 From: Seven Lee Date: Fri, 17 Feb 2023 17:25:23 +0800 Subject: ASoC: nau8821: Implement DRC controls This patch is support dynamic range compression controls. Signed-off-by: Seven Lee Signed-off-by: Seven Lee Link: https://lore.kernel.org/r/20230217092523.357142-1-wtli@nuvoton.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8821.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/nau8821.h | 23 +++++++++++ 2 files changed, 119 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/nau8821.c b/sound/soc/codecs/nau8821.c index 4a72b94e8410..fee970427a24 100644 --- a/sound/soc/codecs/nau8821.c +++ b/sound/soc/codecs/nau8821.c @@ -322,12 +322,92 @@ static const struct soc_enum nau8821_dac_oversampl_enum = SOC_ENUM_SINGLE(NAU8821_R2C_DAC_CTRL1, NAU8821_DAC_OVERSAMPLE_SFT, ARRAY_SIZE(nau8821_dac_oversampl), nau8821_dac_oversampl); +static const char * const nau8821_adc_drc_noise_gate[] = { + "1:1", "2:1", "4:1", "8:1" }; + +static const struct soc_enum nau8821_adc_drc_noise_gate_enum = + SOC_ENUM_SINGLE(NAU8821_R38_ADC_DRC_SLOPES, NAU8821_DRC_NG_SLP_ADC_SFT, + ARRAY_SIZE(nau8821_adc_drc_noise_gate), + nau8821_adc_drc_noise_gate); + +static const char * const nau8821_adc_drc_expansion_slope[] = { + "1:1", "2:1", "4:1" }; + +static const struct soc_enum nau8821_adc_drc_expansion_slope_enum = + SOC_ENUM_SINGLE(NAU8821_R38_ADC_DRC_SLOPES, NAU8821_DRC_EXP_SLP_ADC_SFT, + ARRAY_SIZE(nau8821_adc_drc_expansion_slope), + nau8821_adc_drc_expansion_slope); + +static const char * const nau8821_adc_drc_lower_region[] = { + "0", "1:2", "1:4", "1:8", "1:16", "", "", "1:1" }; + +static const struct soc_enum nau8821_adc_drc_lower_region_enum = + SOC_ENUM_SINGLE(NAU8821_R38_ADC_DRC_SLOPES, + NAU8821_DRC_CMP2_SLP_ADC_SFT, + ARRAY_SIZE(nau8821_adc_drc_lower_region), + nau8821_adc_drc_lower_region); + +static const char * const nau8821_higher_region[] = { + "0", "1:2", "1:4", "1:8", "1:16", "", "", "1:1" }; + +static const struct soc_enum nau8821_higher_region_enum = + SOC_ENUM_SINGLE(NAU8821_R38_ADC_DRC_SLOPES, + NAU8821_DRC_CMP1_SLP_ADC_SFT, + ARRAY_SIZE(nau8821_higher_region), + nau8821_higher_region); + +static const char * const nau8821_limiter_slope[] = { + "0", "1:2", "1:4", "1:8", "1:16", "1:32", "1:64", "1:1" }; + +static const struct soc_enum nau8821_limiter_slope_enum = + SOC_ENUM_SINGLE(NAU8821_R38_ADC_DRC_SLOPES, + NAU8821_DRC_LMT_SLP_ADC_SFT, ARRAY_SIZE(nau8821_limiter_slope), + nau8821_limiter_slope); + +static const char * const nau8821_detection_attack_time[] = { + "Ts", "3Ts", "7Ts", "15Ts", "31Ts", "63Ts", "127Ts", "255Ts", + "", "511Ts" }; + +static const struct soc_enum nau8821_detection_attack_time_enum = + SOC_ENUM_SINGLE(NAU8821_R39_ADC_DRC_ATKDCY, + NAU8821_DRC_PK_COEF1_ADC_SFT, + ARRAY_SIZE(nau8821_detection_attack_time), + nau8821_detection_attack_time); + +static const char * const nau8821_detection_release_time[] = { + "63Ts", "127Ts", "255Ts", "511Ts", "1023Ts", "2047Ts", "4095Ts", + "8191Ts", "", "16383Ts" }; + +static const struct soc_enum nau8821_detection_release_time_enum = + SOC_ENUM_SINGLE(NAU8821_R39_ADC_DRC_ATKDCY, + NAU8821_DRC_PK_COEF2_ADC_SFT, + ARRAY_SIZE(nau8821_detection_release_time), + nau8821_detection_release_time); + +static const char * const nau8821_attack_time[] = { + "Ts", "3Ts", "7Ts", "15Ts", "31Ts", "63Ts", "127Ts", "255Ts", + "511Ts", "1023Ts", "2047Ts", "4095Ts", "8191Ts" }; + +static const struct soc_enum nau8821_attack_time_enum = + SOC_ENUM_SINGLE(NAU8821_R39_ADC_DRC_ATKDCY, NAU8821_DRC_ATK_ADC_SFT, + ARRAY_SIZE(nau8821_attack_time), nau8821_attack_time); + +static const char * const nau8821_decay_time[] = { + "63Ts", "127Ts", "255Ts", "511Ts", "1023Ts", "2047Ts", "4095Ts", + "8191Ts", "16383Ts", "32757Ts", "65535Ts" }; + +static const struct soc_enum nau8821_decay_time_enum = + SOC_ENUM_SINGLE(NAU8821_R39_ADC_DRC_ATKDCY, NAU8821_DRC_DCY_ADC_SFT, + ARRAY_SIZE(nau8821_decay_time), nau8821_decay_time); + static const DECLARE_TLV_DB_MINMAX_MUTE(adc_vol_tlv, -6600, 2400); static const DECLARE_TLV_DB_MINMAX_MUTE(sidetone_vol_tlv, -4200, 0); static const DECLARE_TLV_DB_MINMAX(hp_vol_tlv, -900, 0); static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -6600, 50, 1); static const DECLARE_TLV_DB_MINMAX(fepga_gain_tlv, -100, 3600); static const DECLARE_TLV_DB_MINMAX_MUTE(crosstalk_vol_tlv, -7000, 2400); +static const DECLARE_TLV_DB_MINMAX(drc_knee4_tlv, -9800, -3500); +static const DECLARE_TLV_DB_MINMAX(drc_knee3_tlv, -8100, -1800); static const struct snd_kcontrol_new nau8821_controls[] = { SOC_DOUBLE_TLV("Mic Volume", NAU8821_R35_ADC_DGAIN_CTRL1, @@ -346,6 +426,22 @@ static const struct snd_kcontrol_new nau8821_controls[] = { SOC_DOUBLE_TLV("Headphone Crosstalk Volume", NAU8821_R2F_DAC_DGAIN_CTRL, 0, 8, 0xff, 0, crosstalk_vol_tlv), + SOC_SINGLE_TLV("ADC DRC KNEE4", NAU8821_R37_ADC_DRC_KNEE_IP34, + NAU8821_DRC_KNEE4_IP_ADC_SFT, 0x3f, 1, drc_knee4_tlv), + SOC_SINGLE_TLV("ADC DRC KNEE3", NAU8821_R37_ADC_DRC_KNEE_IP34, + NAU8821_DRC_KNEE3_IP_ADC_SFT, 0x3f, 1, drc_knee3_tlv), + + SOC_ENUM("ADC DRC Noise Gate", nau8821_adc_drc_noise_gate_enum), + SOC_ENUM("ADC DRC Expansion Slope", nau8821_adc_drc_expansion_slope_enum), + SOC_ENUM("ADC DRC Lower Region", nau8821_adc_drc_lower_region_enum), + SOC_ENUM("ADC DRC Higher Region", nau8821_higher_region_enum), + SOC_ENUM("ADC DRC Limiter Slope", nau8821_limiter_slope_enum), + SOC_ENUM("ADC DRC Peak Detection Attack Time", nau8821_detection_attack_time_enum), + SOC_ENUM("ADC DRC Peak Detection Release Time", nau8821_detection_release_time_enum), + SOC_ENUM("ADC DRC Attack Time", nau8821_attack_time_enum), + SOC_ENUM("ADC DRC Decay Time", nau8821_decay_time_enum), + SOC_SINGLE("DRC Enable Switch", NAU8821_R36_ADC_DRC_KNEE_IP12, + NAU8821_DRC_ENA_ADC_SFT, 1, 0), SOC_ENUM("ADC Decimation Rate", nau8821_adc_decimation_enum), SOC_ENUM("DAC Oversampling Rate", nau8821_dac_oversampl_enum), diff --git a/sound/soc/codecs/nau8821.h b/sound/soc/codecs/nau8821.h index c44251f54d48..d962293c218e 100644 --- a/sound/soc/codecs/nau8821.h +++ b/sound/soc/codecs/nau8821.h @@ -350,6 +350,29 @@ #define NAU8821_ADCL_CH_VOL_SFT 0 #define NAU8821_ADCL_CH_VOL_MASK 0xff +/* ADC_DRC_KNEE_IP12 (0x36) */ +#define NAU8821_DRC_ENA_ADC_SFT 15 +#define NAU8821_DRC_ENA_ADC_EN (0x1 << NAU8821_DRC_ENA_ADC_SFT) + +/* ADC_DRC_KNEE_IP34 (0x37) */ +#define NAU8821_DRC_KNEE4_IP_ADC_SFT 8 +#define NAU8821_DRC_KNEE4_IP_ADC_MASK (0xff << NAU8821_DRC_KNEE4_IP_ADC_SFT) +#define NAU8821_DRC_KNEE3_IP_ADC_SFT 0 +#define NAU8821_DRC_KNEE3_IP_ADC_MASK 0xff + +/* ADC_DRC_SLOPES (0x38) */ +#define NAU8821_DRC_NG_SLP_ADC_SFT 12 +#define NAU8821_DRC_EXP_SLP_ADC_SFT 9 +#define NAU8821_DRC_CMP2_SLP_ADC_SFT 6 +#define NAU8821_DRC_CMP1_SLP_ADC_SFT 3 +#define NAU8821_DRC_LMT_SLP_ADC_SFT 0 + +/* ADC_DRC_ATKDCY (0x39) */ +#define NAU8821_DRC_PK_COEF1_ADC_SFT 12 +#define NAU8821_DRC_PK_COEF2_ADC_SFT 8 +#define NAU8821_DRC_ATK_ADC_SFT 4 +#define NAU8821_DRC_DCY_ADC_SFT 0 + /* BIQ1_COF10 (0x4a) */ #define NAU8821_BIQ1_DAC_EN_SFT 3 #define NAU8821_BIQ1_DAC_EN_EN (0x1 << NAU8821_BIQ1_DAC_EN_SFT) -- cgit From 587cbe99152fd735605f3502f42f640bb54f6048 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 23 Feb 2023 21:42:26 -0600 Subject: ASoC: SOF: ipc4-topology: Replace fake flexible arrays with flexible-array member MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zero-length arrays as fake flexible arrays are deprecated and we are moving towards adopting C99 flexible-array members, instead. Use the DECLARE_FLEX_ARRAY() helper macro to transform zero-length arrays in unions with flexible-array members. Address the following warnings found with GCC-13 and -fstrict-flex-arrays=3 enabled: sound/soc/sof/ipc4-control.c:176:77: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:78:29: warning: array subscript 0 is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:80:33: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:95:53: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:96:53: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:93:53: warning: array subscript 0 is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:140:58: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:141:29: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-control.c:142:29: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-topology.c:1475:36: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] sound/soc/sof/ipc4-topology.c:1476:36: warning: array subscript i is outside array bounds of ‘struct sof_ipc4_ctrl_value_chan[0]’ [-Warray-bounds=] This helps with the ongoing efforts to tighten the FORTIFY_SOURCE routines on memcpy() and help us make progress towards globally enabling -fstrict-flex-arrays=3 [1]. Link: https://github.com/KSPP/linux/issues/21 Link: https://github.com/KSPP/linux/issues/193 Link: https://github.com/KSPP/linux/issues/258 Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-October/602902.html [1] Signed-off-by: Gustavo A. R. Silva Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/Y/gyIg1qZduhigPi@work Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 72529179ac22..8507171a6e4d 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -266,8 +266,8 @@ struct sof_ipc4_control_data { int index; union { - struct sof_ipc4_ctrl_value_chan chanv[0]; - struct sof_abi_hdr data[0]; + DECLARE_FLEX_ARRAY(struct sof_ipc4_ctrl_value_chan, chanv); + DECLARE_FLEX_ARRAY(struct sof_abi_hdr, data); }; }; -- cgit From a2d4051b0bd6dffcd736888ae89a550d6f60b060 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Tue, 21 Feb 2023 20:32:03 +0200 Subject: ASoC: jack: allow multiple interrupt per gpio This feature is required for coupled hp-mic quirk used by some Nvidia Tegra 3 based devices work properly. Signed-off-by: Svyatoslav Ryhel Link: https://lore.kernel.org/r/20230221183211.21964-3-clamor95@gmail.com Signed-off-by: Mark Brown --- sound/soc/soc-jack.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index fcece5ca38c6..f951acb2ce36 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -367,6 +367,7 @@ got_gpio: ret = request_any_context_irq(gpiod_to_irq(gpios[i].desc), gpio_handler, + IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, gpios[i].name, -- cgit From 6a534cfcfdbbd69eaac6656eb8c28a8fa27bb12e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 6 Mar 2023 01:44:13 +0000 Subject: ASoC: soc-core.c: remove useless dev_dbg() soc-core.c is using dev_dbg(), but some of them are useless. It indicates many dev_dbg() at snd_soc_runtime_get_dai_fmt(), but all of them are just noise, almost no meanings. dev_dbg() on soc_probe_link_dais() indicates dai link and its loop order, but it is just noise, no information. dev_dbg() on snd_soc_register_dai() is duplicated. This patch cleanup these. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ttyy64cy.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 71b022f7edfd..2faa0d8d0d8e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1033,7 +1033,6 @@ static void snd_soc_runtime_get_dai_fmt(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai_link *dai_link = rtd->dai_link; struct snd_soc_dai *dai, *not_used; - struct device *dev = rtd->dev; u64 pos, possible_fmt; unsigned int mask = 0, dai_fmt = 0; int i, j, priority, pri, until; @@ -1075,8 +1074,6 @@ static void snd_soc_runtime_get_dai_fmt(struct snd_soc_pcm_runtime *rtd) */ until = snd_soc_dai_get_fmt_max_priority(rtd); for (priority = 1; priority <= until; priority++) { - - dev_dbg(dev, "priority = %d\n", priority); for_each_rtd_dais(rtd, j, not_used) { possible_fmt = ULLONG_MAX; @@ -1085,7 +1082,6 @@ static void snd_soc_runtime_get_dai_fmt(struct snd_soc_pcm_runtime *rtd) pri = (j >= i) ? priority : priority - 1; fmt = snd_soc_dai_get_fmt(dai, pri); - dev_dbg(dev, "%s: (pri, fmt) = (%d, %016llX)\n", dai->name, pri, fmt); possible_fmt &= fmt; } if (possible_fmt) @@ -1095,8 +1091,6 @@ static void snd_soc_runtime_get_dai_fmt(struct snd_soc_pcm_runtime *rtd) /* Not Found */ return; found: - dev_dbg(dev, "found auto selected format: %016llX\n", possible_fmt); - /* * convert POSSIBLE_DAIFMT to DAIFMT * @@ -1457,11 +1451,6 @@ static int soc_probe_link_dais(struct snd_soc_card *card) for_each_comp_order(order) { for_each_card_rtds(card, rtd) { - - dev_dbg(card->dev, - "ASoC: probe %s dai link %d late %d\n", - card->name, rtd->num, order); - /* probe all rtd connected DAIs in good order */ ret = snd_soc_pcm_dai_probe(rtd, order); if (ret) @@ -2421,8 +2410,6 @@ struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component, struct device *dev = component->dev; struct snd_soc_dai *dai; - dev_dbg(dev, "ASoC: dynamically register DAI %s\n", dev_name(dev)); - lockdep_assert_held(&client_mutex); dai = devm_kzalloc(dev, sizeof(*dai), GFP_KERNEL); -- cgit From 05ade472278a1a2fccc465ace205d6cfa9b521d5 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 7 Mar 2023 14:35:55 +0200 Subject: ASoC: SOF: ipc4-topology: Add support for core_id for pipelines Token SOF_TKN_SCHED_CORE in topology file can specify the target core for the pipeline, if it is missing it is going to be 0 (as it is right now). Firmware will double-check all information retrieved by topology and report errors if required. This will allow policy and changes in topologies without a need for a synchronized kernel change. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230307123556.31328-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 11 ++++++++--- sound/soc/sof/ipc4-topology.h | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 3e27c7a48ebd..12d8228d0828 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -24,7 +24,9 @@ static DEFINE_IDA(pipeline_ida); static const struct sof_topology_token ipc4_sched_tokens[] = { {SOF_TKN_SCHED_LP_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_pipeline, lp_mode)} + offsetof(struct sof_ipc4_pipeline, lp_mode)}, + {SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_pipeline, core_id)}, }; static const struct sof_topology_token pipeline_tokens[] = { @@ -629,6 +631,8 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) goto err; } + swidget->core = pipeline->core_id; + /* parse one set of pipeline tokens */ ret = sof_update_ipc_object(scomp, swidget, SOF_PIPELINE_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(*swidget), 1); @@ -640,9 +644,9 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) /* TODO: Get priority from topology */ pipeline->priority = 0; - dev_dbg(scomp->dev, "pipeline '%s': id %d pri %d lp mode %d\n", + dev_dbg(scomp->dev, "pipeline '%s': id %d, pri %d, core_id %u, lp mode %d\n", swidget->widget->name, swidget->pipeline_id, - pipeline->priority, pipeline->lp_mode); + pipeline->priority, pipeline->core_id, pipeline->lp_mode); swidget->private = pipeline; @@ -652,6 +656,7 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) pipeline->msg.primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_FW_GEN_MSG); pipeline->msg.extension = pipeline->lp_mode; + pipeline->msg.extension |= SOF_IPC4_GLB_PIPE_EXT_CORE_ID(pipeline->core_id); pipeline->state = SOF_IPC4_PIPE_UNINITIALIZED; return 0; diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 8507171a6e4d..7877f0638011 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -117,6 +117,7 @@ struct sof_ipc4_copier_config_set_sink_format { * @priority: Priority of this pipeline * @lp_mode: Low power mode * @mem_usage: Memory usage + * @core_id: Target core for the pipeline * @state: Pipeline state * @msg: message structure for pipeline * @skip_during_fe_trigger: skip triggering this pipeline during the FE DAI trigger @@ -125,6 +126,7 @@ struct sof_ipc4_pipeline { uint32_t priority; uint32_t lp_mode; uint32_t mem_usage; + uint32_t core_id; int state; struct sof_ipc4_msg msg; bool skip_during_fe_trigger; -- cgit From 755ddc3acd50ca70e46b032c5c4a078e7b1b7d46 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Tue, 7 Mar 2023 14:35:56 +0200 Subject: ASoC: SOF: ipc4-topology: add core token in each module extended token list Add core token in extended token list for each module to support multi-core feature. Signed-off-by: Rander Wang Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Chao Song Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307123556.31328-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 12d8228d0828..b27d85a68426 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -102,6 +102,8 @@ static const struct sof_topology_token dai_tokens[] = { static const struct sof_topology_token comp_ext_tokens[] = { {SOF_TKN_COMP_UUID, SND_SOC_TPLG_TUPLE_TYPE_UUID, get_token_uuid, offsetof(struct snd_sof_widget, uuid)}, + {SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct snd_sof_widget, core)}, }; static const struct sof_topology_token gain_tokens[] = { -- cgit From 611fddf58862a9e77ae300605b2c00d54e973b1f Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Tue, 7 Mar 2023 13:50:18 +0200 Subject: ASoC: SOF: loader: Remove log prefixes for snd_sof_run_firmware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefixs are unneeded since log level explains the same information Signed-off-by: Curtis Malainey Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307115018.5588-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/loader.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 81d202e5ce53..2f8555f11c03 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -123,7 +123,7 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) "fw_version", 0444); /* errors are only due to memory allocation, not debugfs */ if (ret < 0) { - dev_err(sdev->dev, "error: snd_sof_debugfs_buf_item failed\n"); + dev_err(sdev->dev, "snd_sof_debugfs_buf_item failed\n"); return ret; } } @@ -131,7 +131,7 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) /* perform pre fw run operations */ ret = snd_sof_dsp_pre_fw_run(sdev); if (ret < 0) { - dev_err(sdev->dev, "error: failed pre fw run op\n"); + dev_err(sdev->dev, "failed pre fw run op\n"); return ret; } -- cgit From 1d045d77756d07495ce379343455b1f829fe737d Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 7 Mar 2023 11:51:58 +0200 Subject: ASoC: SOF: Intel: hda-loader: use SOF helper for consistency Update code to remove mix between legacy and SOF definitions. No functionality change. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307095158.2818-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index d680562edb35..de8d9ad89bc7 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -321,13 +321,13 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) { struct hdac_ext_stream *iccmax_stream; - struct hdac_bus *bus = sof_to_bus(sdev); struct snd_dma_buffer dmab_bdl; int ret, ret1; u8 original_gb; /* save the original LTRP guardband value */ - original_gb = snd_hdac_chip_readb(bus, VS_LTRP) & HDA_VS_INTEL_LTRP_GB_MASK; + original_gb = snd_sof_dsp_read8(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_LTRP) & + HDA_VS_INTEL_LTRP_GB_MASK; /* * Prepare capture stream for ICCMAX. We do not need to store @@ -356,7 +356,8 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) } /* restore the original guardband value after FW boot */ - snd_hdac_chip_updateb(bus, VS_LTRP, HDA_VS_INTEL_LTRP_GB_MASK, original_gb); + snd_sof_dsp_update8(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_LTRP, + HDA_VS_INTEL_LTRP_GB_MASK, original_gb); return ret; } -- cgit From 418d2b2fad7cdce5d39d0e2fdbe2460f584b5432 Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Tue, 7 Mar 2023 11:52:51 +0200 Subject: ASoC: SOF: Intel: mtl: Access MTL_HFPWRCTL from HDA_DSP_BAR The Host Power Management/Clock Control (ULP) Registers in the HDA BAR shadow the values of the same registers in the DSP BAR, so let's modify the latter - as done already for other accesses. Signed-off-by: Yong Zhi Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307095251.3058-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 216fd07a3a93..8f0ed1cbf3b5 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -256,7 +256,7 @@ static int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) dev_err(sdev->dev, "failed to power up gated DSP domain\n"); /* make sure SoundWire is not power-gated */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, MTL_HFPWRCTL, + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFPWRCTL, MTL_HfPWRCTL_WPIOXPG(1), MTL_HfPWRCTL_WPIOXPG(1)); return ret; } -- cgit From 3c50211f2d534a5b766b1ff3c6cf6f7bd0bae753 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 7 Mar 2023 13:08:30 +0200 Subject: ASoC: SOF: ipc4-topology: don't allocate blob if it will not be used A copier blob will be only used when a copier is connected in the topology. An ALH copier in playback direction that doesn't have any source means the copier is not connected in the topology. Thus, we don't need to allocate the blob. The patch doesn't do the same test before freeing the blob because the blob is null and it is fine to free null. Signed-off-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307110830.2178-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 3e27c7a48ebd..93b2855388d5 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -517,7 +517,23 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_alh_configuration_blob *blob; + struct snd_soc_dapm_path *p; struct snd_sof_widget *w; + int src_num = 0; + + snd_soc_dapm_widget_for_each_source_path(swidget->widget, p) + src_num++; + + if (swidget->id == snd_soc_dapm_dai_in && src_num == 0) { + /* + * The blob will not be used if the ALH copier is playback direction + * and doesn't connect to any source. + * It is fine to call kfree(ipc4_copier->copier_config) since + * ipc4_copier->copier_config is null. + */ + ret = 0; + break; + } blob = kzalloc(sizeof(*blob), GFP_KERNEL); if (!blob) { -- cgit From db97cc0f7459a2bee68e6e8bf0b2f7a286137fa8 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 7 Mar 2023 13:08:46 +0200 Subject: ASoC: SOF: ipc4-mtrace: process pending logs upon FW crash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the DSP firmware has crashed, some log messages may be pending in the mtrace buffer, but not consumed by the driver as no IPC notification has been sent by the firmware. Check the buffer status for all mtrace slots and ensure any pending log messages are processed before DSP is possibly powered down and the log buffer contents is lost. Signed-off-by: Kai Vehmanen Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307110846.2265-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-mtrace.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-mtrace.c b/sound/soc/sof/ipc4-mtrace.c index 0ec6ef681012..2b4659a1768e 100644 --- a/sound/soc/sof/ipc4-mtrace.c +++ b/sound/soc/sof/ipc4-mtrace.c @@ -609,6 +609,16 @@ static void ipc4_mtrace_free(struct snd_sof_dev *sdev) ipc4_mtrace_disable(sdev); } +static int sof_ipc4_mtrace_update_pos_all_cores(struct snd_sof_dev *sdev) +{ + int i; + + for (i = 0; i < sdev->num_cores; i++) + sof_ipc4_mtrace_update_pos(sdev, i); + + return 0; +} + int sof_ipc4_mtrace_update_pos(struct snd_sof_dev *sdev, int core) { struct sof_mtrace_priv *priv = sdev->fw_trace_data; @@ -642,6 +652,16 @@ int sof_ipc4_mtrace_update_pos(struct snd_sof_dev *sdev, int core) return 0; } +static void ipc4_mtrace_fw_crashed(struct snd_sof_dev *sdev) +{ + /* + * The DSP might not be able to send SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS + * messages anymore, so check the log buffer status on all + * cores and process any pending messages. + */ + sof_ipc4_mtrace_update_pos_all_cores(sdev); +} + static int ipc4_mtrace_resume(struct snd_sof_dev *sdev) { return ipc4_mtrace_enable(sdev); @@ -655,6 +675,7 @@ static void ipc4_mtrace_suspend(struct snd_sof_dev *sdev, pm_message_t pm_state) const struct sof_ipc_fw_tracing_ops ipc4_mtrace_ops = { .init = ipc4_mtrace_init, .free = ipc4_mtrace_free, + .fw_crashed = ipc4_mtrace_fw_crashed, .suspend = ipc4_mtrace_suspend, .resume = ipc4_mtrace_resume, }; -- cgit From 274f8a3b4eb855bb14e38f6f12421ed32a2e670b Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:22 +0200 Subject: ASoC: SOF: Intel: hda-dai: Remove BE DAI DRV ops for SSP DAI's MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the DAI_CONFIG IPC is sent after widget setup and before widget free, there is no need for the BE DAI DRV ops that do the same thing. So remove them. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 113 ------------------------------------------ 1 file changed, 113 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 8d9c38d562d3..c7f89c18d5c2 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -605,115 +605,6 @@ static const struct snd_soc_dai_ops ipc4_hda_dai_ops = { #endif -/* only one flag used so far to harden hw_params/hw_free/trigger/prepare */ -struct ssp_dai_dma_data { - bool setup; -}; - -static int ssp_dai_setup_or_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai, - bool setup) -{ - struct snd_soc_dapm_widget *w; - - w = snd_soc_dai_get_widget(dai, substream->stream); - - if (setup) - return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_NONE, NULL); - - return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, NULL); -} - -static int ssp_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct ssp_dai_dma_data *dma_data; - - dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL); - if (!dma_data) - return -ENOMEM; - - snd_soc_dai_set_dma_data(dai, substream, dma_data); - - return 0; -} - -static int ssp_dai_setup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai, - bool setup) -{ - struct ssp_dai_dma_data *dma_data; - int ret = 0; - - dma_data = snd_soc_dai_get_dma_data(dai, substream); - if (!dma_data) { - dev_err(dai->dev, "%s: failed to get dma_data\n", __func__); - return -EIO; - } - - if (dma_data->setup != setup) { - ret = ssp_dai_setup_or_free(substream, dai, setup); - if (!ret) - dma_data->setup = setup; - } - return ret; -} - -static int ssp_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - /* params are ignored for now */ - return ssp_dai_setup(substream, dai, true); -} - -static int ssp_dai_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - /* - * the SSP will only be reconfigured during resume operations and - * not in case of xruns - */ - return ssp_dai_setup(substream, dai, true); -} - -static int ipc3_ssp_dai_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - if (cmd != SNDRV_PCM_TRIGGER_SUSPEND) - return 0; - - return ssp_dai_setup(substream, dai, false); -} - -static int ssp_dai_hw_free(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - return ssp_dai_setup(substream, dai, false); -} - -static void ssp_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct ssp_dai_dma_data *dma_data; - - dma_data = snd_soc_dai_get_dma_data(dai, substream); - if (!dma_data) { - dev_err(dai->dev, "%s: failed to get dma_data\n", __func__); - return; - } - snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(dma_data); -} - -static const struct snd_soc_dai_ops ipc3_ssp_dai_ops = { - .startup = ssp_dai_startup, - .hw_params = ssp_dai_hw_params, - .prepare = ssp_dai_prepare, - .trigger = ipc3_ssp_dai_trigger, - .hw_free = ssp_dai_hw_free, - .shutdown = ssp_dai_shutdown, -}; - void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) { int i; @@ -721,10 +612,6 @@ void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) switch (sdev->pdata->ipc_type) { case SOF_IPC: for (i = 0; i < ops->num_drv; i++) { - if (strstr(ops->drv[i].name, "SSP")) { - ops->drv[i].ops = &ipc3_ssp_dai_ops; - continue; - } #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) if (strstr(ops->drv[i].name, "iDisp") || strstr(ops->drv[i].name, "Analog") || -- cgit From a8310c0093f4ebeb3a317b4b70e864b91739fc50 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:23 +0200 Subject: ASoC: SOF: Intel: hda-dai: Remove hda_link_dma_params() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No code change. Just code move from hda_link_dma_params() to hda_link_dma_hw_params(). Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 62 +++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 34 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index c7f89c18d5c2..770c00ae29ac 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -168,39 +168,6 @@ static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, return 0; } -static int hda_link_dma_params(struct hdac_ext_stream *hext_stream, - struct hda_pipe_params *params) -{ - struct hdac_stream *hstream = &hext_stream->hstream; - unsigned char stream_tag = hstream->stream_tag; - struct hdac_bus *bus = hstream->bus; - struct hdac_ext_link *hlink; - unsigned int format_val; - - snd_hdac_ext_stream_reset(hext_stream); - - format_val = snd_hdac_calc_stream_format(params->s_freq, params->ch, - params->format, - params->link_bps, 0); - - dev_dbg(bus->dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", - format_val, params->s_freq, params->ch, params->format); - - snd_hdac_ext_stream_setup(hext_stream, format_val); - - if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) { - list_for_each_entry(hlink, &bus->hlink_list, list) { - if (hlink->index == params->link_index) - snd_hdac_ext_bus_link_set_stream_id(hlink, - stream_tag); - } - } - - hext_stream->link_prepared = 1; - - return 0; -} - static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -209,9 +176,12 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct hda_pipe_params p_params = {0}; struct hdac_ext_stream *hext_stream; + struct hdac_stream *hstream; struct hdac_ext_link *hlink; struct snd_sof_dev *sdev; struct hdac_bus *bus; + unsigned int format_val; + unsigned char stream_tag; sdev = snd_soc_component_get_drvdata(cpu_dai->component); bus = sof_to_bus(sdev); @@ -229,6 +199,9 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)hext_stream); } + hstream = &hext_stream->hstream; + stream_tag = hstream->stream_tag; + /* set the hdac_stream in the codec dai */ snd_soc_dai_set_stream(codec_dai, hdac_stream(hext_stream), substream->stream); @@ -242,7 +215,28 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, else p_params.link_bps = codec_dai->driver->capture.sig_bits; - return hda_link_dma_params(hext_stream, &p_params); + snd_hdac_ext_stream_reset(hext_stream); + + format_val = snd_hdac_calc_stream_format(p_params.s_freq, p_params.ch, + p_params.format, + p_params.link_bps, 0); + + dev_dbg(bus->dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", + format_val, p_params.s_freq, p_params.ch, p_params.format); + + snd_hdac_ext_stream_setup(hext_stream, format_val); + + if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) { + list_for_each_entry(hlink, &bus->hlink_list, list) { + if (hlink->index == p_params.link_index) + snd_hdac_ext_bus_link_set_stream_id(hlink, + stream_tag); + } + } + + hext_stream->link_prepared = 1; + + return 0; } static int hda_link_dma_prepare(struct snd_pcm_substream *substream) -- cgit From 2a6afac248b08a0bcec72a6a605f11319738f6db Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:24 +0200 Subject: ASoC: SOF: Intel: hda-dai: remove struct hda_pipe_params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the struct definition and use the params argument directly. Also, use the hlink pointer to set the stream ID instead of looking it up again. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 37 +++++++++---------------------------- 1 file changed, 9 insertions(+), 28 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 770c00ae29ac..009299c6de40 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -29,14 +29,6 @@ MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override"); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) -struct hda_pipe_params { - u32 ch; - u32 s_freq; - snd_pcm_format_t format; - int link_index; - unsigned int link_bps; -}; - /* * This function checks if the host dma channel corresponding * to the link DMA stream_tag argument is assigned to one @@ -174,13 +166,13 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - struct hda_pipe_params p_params = {0}; struct hdac_ext_stream *hext_stream; struct hdac_stream *hstream; struct hdac_ext_link *hlink; struct snd_sof_dev *sdev; struct hdac_bus *bus; unsigned int format_val; + unsigned int link_bps; unsigned char stream_tag; sdev = snd_soc_component_get_drvdata(cpu_dai->component); @@ -202,38 +194,27 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, hstream = &hext_stream->hstream; stream_tag = hstream->stream_tag; + if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) + snd_hdac_ext_bus_link_set_stream_id(hlink, stream_tag); + /* set the hdac_stream in the codec dai */ snd_soc_dai_set_stream(codec_dai, hdac_stream(hext_stream), substream->stream); - p_params.ch = params_channels(params); - p_params.s_freq = params_rate(params); - p_params.link_index = hlink->index; - p_params.format = params_format(params); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - p_params.link_bps = codec_dai->driver->playback.sig_bits; + link_bps = codec_dai->driver->playback.sig_bits; else - p_params.link_bps = codec_dai->driver->capture.sig_bits; + link_bps = codec_dai->driver->capture.sig_bits; snd_hdac_ext_stream_reset(hext_stream); - format_val = snd_hdac_calc_stream_format(p_params.s_freq, p_params.ch, - p_params.format, - p_params.link_bps, 0); + format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params), + params_format(params), link_bps, 0); dev_dbg(bus->dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", - format_val, p_params.s_freq, p_params.ch, p_params.format); + format_val, params_rate(params), params_channels(params), params_format(params)); snd_hdac_ext_stream_setup(hext_stream, format_val); - if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) { - list_for_each_entry(hlink, &bus->hlink_list, list) { - if (hlink->index == p_params.link_index) - snd_hdac_ext_bus_link_set_stream_id(hlink, - stream_tag); - } - } - hext_stream->link_prepared = 1; return 0; -- cgit From 2be2caf481c7200b29116cea83cf8dd45c9e097f Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:25 +0200 Subject: ASoC: SOF: Intel: hda-dai: Modify the signature of hda_link_dma_cleanup() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the trigger_suspend_stop argument from hda_link_dma_cleanup() and move the call to snd_hdac_ext_stream_clear() into snd_hdac_ext_stream_clear(). This is a preparatory step to unify the trigger ops for IPC3 and IPC4. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 009299c6de40..d4b98bfe2adf 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -129,8 +129,7 @@ hda_link_stream_assign(struct hdac_bus *bus, static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_stream *hext_stream, struct snd_soc_dai *cpu_dai, - struct snd_soc_dai *codec_dai, - bool trigger_suspend_stop) + struct snd_soc_dai *codec_dai) { struct hdac_stream *hstream = &hext_stream->hstream; struct hdac_bus *bus = hstream->bus; @@ -142,9 +141,6 @@ static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, if (!hlink) return -EINVAL; - if (trigger_suspend_stop) - snd_hdac_ext_stream_clear(hext_stream); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { stream_tag = hdac_stream(hext_stream)->stream_tag; snd_hdac_ext_bus_link_clear_stream_id(hlink, stream_tag); @@ -246,7 +242,8 @@ static int hda_link_dma_trigger(struct snd_pcm_substream *substream, int cmd) break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: - ret = hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai, true); + snd_hdac_ext_stream_clear(hext_stream); + ret = hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai); if (ret < 0) return ret; @@ -272,7 +269,7 @@ static int hda_link_dma_hw_free(struct snd_pcm_substream *substream) if (!hext_stream) return 0; - return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai, false); + return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai); } static int hda_dai_widget_update(struct snd_soc_dapm_widget *w, @@ -483,7 +480,7 @@ static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, pipeline->state = SOF_IPC4_PIPE_RESET; - ret = hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai, false); + ret = hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai); if (ret < 0) { dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); return ret; @@ -557,7 +554,7 @@ static int hda_dai_suspend(struct hdac_bus *bus) ret = hda_link_dma_cleanup(hext_stream->link_substream, hext_stream, - cpu_dai, codec_dai, false); + cpu_dai, codec_dai); if (ret < 0) return ret; -- cgit From b436ed8dd071cae10ac3f94c541a783a094971ff Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:26 +0200 Subject: ASoC: SOF: Intel: hda-dai: Pass the CPU dai pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass the CPU DAI pointer from the ASoC core to hda_link_dma_hw_params() and ipc3_hda_dai_trigger(). This will avoid looking up the CPU DAI pointer multiple times. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index d4b98bfe2adf..e448c653cfe1 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -157,10 +157,9 @@ static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, } static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) + struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct hdac_ext_stream *hext_stream; struct hdac_stream *hstream; @@ -216,18 +215,18 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, return 0; } -static int hda_link_dma_prepare(struct snd_pcm_substream *substream) +static int hda_link_dma_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int stream = substream->stream; - return hda_link_dma_hw_params(substream, &rtd->dpcm[stream].hw_params); + return hda_link_dma_hw_params(substream, &rtd->dpcm[stream].hw_params, cpu_dai); } -static int hda_link_dma_trigger(struct snd_pcm_substream *substream, int cmd) +static int hda_link_dma_trigger(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai, + int cmd) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream); int ret; @@ -258,10 +257,9 @@ static int hda_link_dma_trigger(struct snd_pcm_substream *substream, int cmd) return 0; } -static int hda_link_dma_hw_free(struct snd_pcm_substream *substream) +static int hda_link_dma_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct hdac_ext_stream *hext_stream; @@ -317,7 +315,7 @@ static int hda_dai_hw_params(struct snd_pcm_substream *substream, if (hext_stream && hext_stream->link_prepared) return 0; - ret = hda_link_dma_hw_params(substream, params); + ret = hda_link_dma_hw_params(substream, params, dai); if (ret < 0) return ret; @@ -357,7 +355,7 @@ static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_d dev_dbg(sdev->dev, "prepare stream dir %d\n", substream->stream); - ret = hda_link_dma_prepare(substream); + ret = hda_link_dma_prepare(substream, dai); if (ret < 0) return ret; @@ -384,7 +382,7 @@ static int ipc3_hda_dai_trigger(struct snd_pcm_substream *substream, dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd, dai->name, substream->stream); - ret = hda_link_dma_trigger(substream, cmd); + ret = hda_link_dma_trigger(substream, dai, cmd); if (ret < 0) return ret; @@ -512,7 +510,7 @@ static int hda_dai_hw_free(struct snd_pcm_substream *substream, { int ret; - ret = hda_link_dma_hw_free(substream); + ret = hda_link_dma_hw_free(substream, dai); if (ret < 0) return ret; -- cgit From be7f4f8d0bee110505750d85e6e11c59f8ceb65f Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:27 +0200 Subject: ASoC: SOF: Intel: hda-dai: Use the dai argument in ipc4_hda_dai_trigger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to define a new variable and look it up again. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index e448c653cfe1..49f25e55b15d 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -426,14 +426,12 @@ static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, struct snd_sof_widget *swidget; struct snd_soc_dapm_widget *w; struct snd_soc_dai *codec_dai; - struct snd_soc_dai *cpu_dai; int ret; dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd, dai->name, substream->stream); rtd = asoc_substream_to_rtd(substream); - cpu_dai = asoc_rtd_to_cpu(rtd, 0); codec_dai = asoc_rtd_to_codec(rtd, 0); w = snd_soc_dai_get_widget(dai, substream->stream); @@ -478,7 +476,7 @@ static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, pipeline->state = SOF_IPC4_PIPE_RESET; - ret = hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai); + ret = hda_link_dma_cleanup(substream, hext_stream, dai, codec_dai); if (ret < 0) { dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); return ret; -- cgit From 2ae49c6fe060baf432472aba48743e72b8345c52 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:28 +0200 Subject: ASoC: SOF: Intel: hda-dai: Introduce DAI widget ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a new ops structure for HDA DAI widget DMA ops and add a new field to struct snd_sof_dai that will be used to set the ops pointer for DAI widgets. Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.h | 31 +++++++++++++++++++++++++++++++ sound/soc/sof/sof-audio.h | 2 ++ 2 files changed, 33 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 0679bebe4ad7..c6243827f8d0 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -928,4 +928,35 @@ extern struct sdw_intel_ops sdw_callback; struct sof_ipc4_fw_library; int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev, struct sof_ipc4_fw_library *fw_lib, bool reload); + +/** + * struct hda_dai_widget_dma_ops - DAI DMA ops optional by default unless specified otherwise + * @get_hext_stream: Mandatory function pointer to get the saved pointer to struct hdac_ext_stream + * @assign_hext_stream: Function pointer to assign a hdac_ext_stream + * @release_hext_stream: Function pointer to release the hdac_ext_stream + * @setup_hext_stream: Function pointer for hdac_ext_stream setup + * @reset_hext_stream: Function pointer for hdac_ext_stream reset + * @pre_trigger: Function pointer for DAI DMA pre-trigger actions + * @trigger: Function pointer for DAI DMA trigger actions + * @post_trigger: Function pointer for DAI DMA post-trigger actions + */ +struct hda_dai_widget_dma_ops { + struct hdac_ext_stream *(*get_hext_stream)(struct snd_sof_dev *sdev, + struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream); + struct hdac_ext_stream *(*assign_hext_stream)(struct snd_sof_dev *sdev, + struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream); + void (*release_hext_stream)(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream); + void (*setup_hext_stream)(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream, + unsigned int format_val); + void (*reset_hext_stream)(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_sream); + int (*pre_trigger)(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd); + int (*trigger)(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd); + int (*post_trigger)(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd); +}; #endif diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index e0579af9d281..239b82f37976 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -502,6 +502,8 @@ struct snd_sof_dai { int number_configs; int current_config; struct list_head list; /* list in sdev dai list */ + /* core should not touch this */ + const void *platform_private; void *private; }; -- cgit From 80afde34e8f9c2459f7cd37ea2d5f71751fedd69 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:29 +0200 Subject: ASoC: SOF: Intel: hda-dai: Define and set the HDA DAI widget DMA ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define and set the get_hext_stream, assign_hext_stream and release_hext_stream DMA ops for HDA DAIs. Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-9-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/Makefile | 2 +- sound/soc/sof/intel/hda-dai-ops.c | 183 +++++++++++++++++++++++++++++++++++++ sound/soc/sof/intel/hda-dai.c | 188 ++++++++++++++------------------------ sound/soc/sof/intel/hda.h | 4 + 4 files changed, 259 insertions(+), 118 deletions(-) create mode 100644 sound/soc/sof/intel/hda-dai-ops.c (limited to 'sound') diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index 8201cbdd654c..38ab86b6a9fe 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -5,7 +5,7 @@ snd-sof-acpi-intel-bdw-objs := bdw.o snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.o \ hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \ - hda-dai.o hda-bus.o hda-mlink.o \ + hda-dai.o hda-dai-ops.o hda-bus.o hda-mlink.o \ skl.o hda-loader-skl.o \ apl.o cnl.o tgl.o icl.o mtl.o hda-common-ops.o diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c new file mode 100644 index 000000000000..9dfcafeab9e4 --- /dev/null +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. + +#include +#include +#include +#include +#include "../ipc4-priv.h" +#include "../ipc4-topology.h" +#include "../sof-priv.h" +#include "../sof-audio.h" +#include "hda.h" + +/* These ops are only applicable for the HDA DAI's in their current form */ +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) +/* + * This function checks if the host dma channel corresponding + * to the link DMA stream_tag argument is assigned to one + * of the FEs connected to the BE DAI. + */ +static bool hda_check_fes(struct snd_soc_pcm_runtime *rtd, + int dir, int stream_tag) +{ + struct snd_pcm_substream *fe_substream; + struct hdac_stream *fe_hstream; + struct snd_soc_dpcm *dpcm; + + for_each_dpcm_fe(rtd, dir, dpcm) { + fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, dir); + fe_hstream = fe_substream->runtime->private_data; + if (fe_hstream->stream_tag == stream_tag) + return true; + } + + return false; +} + +static struct hdac_ext_stream * +hda_link_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct sof_intel_hda_stream *hda_stream; + const struct sof_intel_dsp_desc *chip; + struct snd_sof_dev *sdev; + struct hdac_ext_stream *res = NULL; + struct hdac_stream *hstream = NULL; + + int stream_dir = substream->stream; + + if (!bus->ppcap) { + dev_err(bus->dev, "stream type not supported\n"); + return NULL; + } + + spin_lock_irq(&bus->reg_lock); + list_for_each_entry(hstream, &bus->stream_list, list) { + struct hdac_ext_stream *hext_stream = + stream_to_hdac_ext_stream(hstream); + if (hstream->direction != substream->stream) + continue; + + hda_stream = hstream_to_sof_hda_stream(hext_stream); + sdev = hda_stream->sdev; + chip = get_chip_info(sdev->pdata); + + /* check if link is available */ + if (!hext_stream->link_locked) { + /* + * choose the first available link for platforms that do not have the + * PROCEN_FMT_QUIRK set. + */ + if (!(chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) { + res = hext_stream; + break; + } + + if (hstream->opened) { + /* + * check if the stream tag matches the stream + * tag of one of the connected FEs + */ + if (hda_check_fes(rtd, stream_dir, + hstream->stream_tag)) { + res = hext_stream; + break; + } + } else { + res = hext_stream; + + /* + * This must be a hostless stream. + * So reserve the host DMA channel. + */ + hda_stream->host_reserved = 1; + break; + } + } + } + + if (res) { + /* Make sure that host and link DMA is decoupled. */ + snd_hdac_ext_stream_decouple_locked(bus, res, true); + + res->link_locked = 1; + res->link_substream = substream; + } + spin_unlock_irq(&bus->reg_lock); + + return res; +} + +static struct hdac_ext_stream *hda_get_hext_stream(struct snd_sof_dev *sdev, + struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream) +{ + return snd_soc_dai_get_dma_data(cpu_dai, substream); +} + +static struct hdac_ext_stream *hda_assign_hext_stream(struct snd_sof_dev *sdev, + struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream) +{ + struct hdac_ext_stream *hext_stream; + + hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream); + if (!hext_stream) + return NULL; + + snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)hext_stream); + + return hext_stream; +} + +static void hda_release_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream) +{ + struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream); + + snd_soc_dai_set_dma_data(cpu_dai, substream, NULL); + snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK); +} + +static const struct hda_dai_widget_dma_ops hda_dma_ops = { + .get_hext_stream = hda_get_hext_stream, + .assign_hext_stream = hda_assign_hext_stream, + .release_hext_stream = hda_release_hext_stream, +}; + +#endif + +const struct hda_dai_widget_dma_ops * +hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) +{ +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) + struct snd_sof_dai *sdai = swidget->private; + + switch (sdev->pdata->ipc_type) { + case SOF_IPC: + { + struct sof_dai_private_data *private = sdai->private; + + if (private->dai_config->type == SOF_DAI_INTEL_HDA) + return &hda_dma_ops; + break; + } + case SOF_INTEL_IPC4: + { + struct sof_ipc4_copier *ipc4_copier = sdai->private; + + if (ipc4_copier->dai_type == SOF_DAI_INTEL_HDA) + return &hda_dma_ops; + break; + } + default: + break; + } +#endif + return NULL; +} diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 49f25e55b15d..963c40d8a10b 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -29,101 +29,30 @@ MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override"); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) -/* - * This function checks if the host dma channel corresponding - * to the link DMA stream_tag argument is assigned to one - * of the FEs connected to the BE DAI. - */ -static bool hda_check_fes(struct snd_soc_pcm_runtime *rtd, - int dir, int stream_tag) -{ - struct snd_pcm_substream *fe_substream; - struct hdac_stream *fe_hstream; - struct snd_soc_dpcm *dpcm; - - for_each_dpcm_fe(rtd, dir, dpcm) { - fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, dir); - fe_hstream = fe_substream->runtime->private_data; - if (fe_hstream->stream_tag == stream_tag) - return true; - } - - return false; -} - -static struct hdac_ext_stream * -hda_link_stream_assign(struct hdac_bus *bus, - struct snd_pcm_substream *substream) +static const struct hda_dai_widget_dma_ops * +hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct sof_intel_hda_stream *hda_stream; - const struct sof_intel_dsp_desc *chip; - struct snd_sof_dev *sdev; - struct hdac_ext_stream *res = NULL; - struct hdac_stream *hstream = NULL; - - int stream_dir = substream->stream; + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); + struct snd_sof_widget *swidget = w->dobj.private; + struct snd_sof_dai *sdai = swidget->private; - if (!bus->ppcap) { - dev_err(bus->dev, "stream type not supported\n"); - return NULL; - } + /* select and set the DAI widget ops if not set already */ + if (!sdai->platform_private) { + const struct hda_dai_widget_dma_ops *ops = + hda_select_dai_widget_ops(sdev, swidget); - spin_lock_irq(&bus->reg_lock); - list_for_each_entry(hstream, &bus->stream_list, list) { - struct hdac_ext_stream *hext_stream = - stream_to_hdac_ext_stream(hstream); - if (hstream->direction != substream->stream) - continue; - - hda_stream = hstream_to_sof_hda_stream(hext_stream); - sdev = hda_stream->sdev; - chip = get_chip_info(sdev->pdata); - - /* check if link is available */ - if (!hext_stream->link_locked) { - /* - * choose the first available link for platforms that do not have the - * PROCEN_FMT_QUIRK set. - */ - if (!(chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) { - res = hext_stream; - break; - } - - if (hstream->opened) { - /* - * check if the stream tag matches the stream - * tag of one of the connected FEs - */ - if (hda_check_fes(rtd, stream_dir, - hstream->stream_tag)) { - res = hext_stream; - break; - } - } else { - res = hext_stream; - - /* - * This must be a hostless stream. - * So reserve the host DMA channel. - */ - hda_stream->host_reserved = 1; - break; - } - } - } + if (!ops) + return NULL; - if (res) { - /* Make sure that host and link DMA is decoupled. */ - snd_hdac_ext_stream_decouple_locked(bus, res, true); + /* check if mandatory ops are set */ + if (!ops || !ops->get_hext_stream) + return NULL; - res->link_locked = 1; - res->link_substream = substream; + sdai->platform_private = ops; } - spin_unlock_irq(&bus->reg_lock); - return res; + return sdai->platform_private; } static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, @@ -131,6 +60,8 @@ static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai, struct snd_soc_dai *codec_dai) { + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); struct hdac_stream *hstream = &hext_stream->hstream; struct hdac_bus *bus = hstream->bus; struct sof_intel_hda_stream *hda_stream; @@ -145,8 +76,10 @@ static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, stream_tag = hdac_stream(hext_stream)->stream_tag; snd_hdac_ext_bus_link_clear_stream_id(hlink, stream_tag); } - snd_soc_dai_set_dma_data(cpu_dai, substream, NULL); - snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK); + + if (ops->release_hext_stream) + ops->release_hext_stream(sdev, cpu_dai, substream); + hext_stream->link_prepared = 0; /* free the host DMA channel reserved by hostless streams */ @@ -159,6 +92,7 @@ static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct hdac_ext_stream *hext_stream; @@ -168,7 +102,7 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, struct hdac_bus *bus; unsigned int format_val; unsigned int link_bps; - unsigned char stream_tag; + int stream_tag; sdev = snd_soc_component_get_drvdata(cpu_dai->component); bus = sof_to_bus(sdev); @@ -177,15 +111,16 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, if (!hlink) return -EINVAL; - hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream); - if (!hext_stream) { - hext_stream = hda_link_stream_assign(bus, substream); - if (!hext_stream) - return -EBUSY; + hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); - snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)hext_stream); + if (!hext_stream) { + if (ops->assign_hext_stream) + hext_stream = ops->assign_hext_stream(sdev, cpu_dai, substream); } + if (!hext_stream) + return -EBUSY; + hstream = &hext_stream->hstream; stream_tag = hstream->stream_tag; @@ -226,11 +161,15 @@ static int hda_link_dma_prepare(struct snd_pcm_substream *substream, struct snd_ static int hda_link_dma_trigger(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai, int cmd) { + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream); + struct hdac_ext_stream *hext_stream; int ret; + hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); + if (!hext_stream) return 0; @@ -259,11 +198,18 @@ static int hda_link_dma_trigger(struct snd_pcm_substream *substream, struct snd_ static int hda_link_dma_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct hdac_ext_stream *hext_stream; - hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream); + if (!ops) { + dev_err(sdev->dev, "DAI widget ops not set\n"); + return -EINVAL; + } + + hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); if (!hext_stream) return 0; @@ -288,18 +234,18 @@ static int hda_dai_hw_params_update(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); struct hdac_ext_stream *hext_stream; - struct snd_soc_dapm_widget *w; int stream_tag; - hext_stream = snd_soc_dai_get_dma_data(dai, substream); + hext_stream = ops->get_hext_stream(sdev, dai, substream); if (!hext_stream) return -EINVAL; stream_tag = hdac_stream(hext_stream)->stream_tag; - w = snd_soc_dai_get_widget(dai, substream->stream); - /* set up the DAI widget and send the DAI_CONFIG with the new tag */ return hda_dai_widget_update(w, stream_tag - 1, true); } @@ -308,10 +254,17 @@ static int hda_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct hdac_ext_stream *hext_stream = - snd_soc_dai_get_dma_data(dai, substream); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); + struct hdac_ext_stream *hext_stream; int ret; + if (!ops) { + dev_err(sdev->dev, "DAI widget ops not set\n"); + return -EINVAL; + } + + hext_stream = ops->get_hext_stream(sdev, dai, substream); if (hext_stream && hext_stream->link_prepared) return 0; @@ -343,13 +296,14 @@ static int hda_dai_config_pause_push_ipc(struct snd_soc_dapm_widget *w) static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct hdac_ext_stream *hext_stream = - snd_soc_dai_get_dma_data(dai, substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct hdac_ext_stream *hext_stream; int stream = substream->stream; int ret; + hext_stream = ops->get_hext_stream(sdev, dai, substream); if (hext_stream && hext_stream->link_prepared) return 0; @@ -418,27 +372,27 @@ static int ipc3_hda_dai_trigger(struct snd_pcm_substream *substream, static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(dai, substream); + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); - struct snd_sof_widget *pipe_widget; - struct sof_ipc4_pipeline *pipeline; + const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); + struct snd_sof_widget *swidget = w->dobj.private; + struct hdac_ext_stream *hext_stream; + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; struct snd_soc_pcm_runtime *rtd; - struct snd_sof_widget *swidget; - struct snd_soc_dapm_widget *w; struct snd_soc_dai *codec_dai; int ret; dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd, dai->name, substream->stream); + hext_stream = ops->get_hext_stream(sdev, dai, substream); + if (!hext_stream) + return -EINVAL; + rtd = asoc_substream_to_rtd(substream); codec_dai = asoc_rtd_to_codec(rtd, 0); - w = snd_soc_dai_get_widget(dai, substream->stream); - swidget = w->dobj.private; - pipe_widget = swidget->spipe->pipe_widget; - pipeline = pipe_widget->private; - switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index c6243827f8d0..e0469f86fa63 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -959,4 +959,8 @@ struct hda_dai_widget_dma_ops { int (*post_trigger)(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, struct snd_pcm_substream *substream, int cmd); }; + +const struct hda_dai_widget_dma_ops * +hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); + #endif -- cgit From e2d6569aba39f4b98da8e56999a19dc901188e5e Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:30 +0200 Subject: ASoC: SOF: Intel: hda-dai: Add setup_hext_stream/reset_hext_stream DMA ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define and use the setup_hext_stream/reset_hext_stream DMA ops during link hw_params and cleanup. Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-10-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 13 +++++++++++++ sound/soc/sof/intel/hda-dai.c | 6 ++++-- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index 9dfcafeab9e4..57db589906db 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -144,10 +144,23 @@ static void hda_release_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK); } +static void hda_setup_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream, + unsigned int format_val) +{ + snd_hdac_ext_stream_setup(hext_stream, format_val); +} + +static void hda_reset_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream) +{ + snd_hdac_ext_stream_reset(hext_stream); +} + static const struct hda_dai_widget_dma_ops hda_dma_ops = { .get_hext_stream = hda_get_hext_stream, .assign_hext_stream = hda_assign_hext_stream, .release_hext_stream = hda_release_hext_stream, + .setup_hext_stream = hda_setup_hext_stream, + .reset_hext_stream = hda_reset_hext_stream, }; #endif diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 963c40d8a10b..9616cdba79b6 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -135,7 +135,8 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, else link_bps = codec_dai->driver->capture.sig_bits; - snd_hdac_ext_stream_reset(hext_stream); + if (ops->reset_hext_stream) + ops->reset_hext_stream(sdev, hext_stream); format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params), params_format(params), link_bps, 0); @@ -143,7 +144,8 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, dev_dbg(bus->dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", format_val, params_rate(params), params_channels(params), params_format(params)); - snd_hdac_ext_stream_setup(hext_stream, format_val); + if (ops->setup_hext_stream) + ops->setup_hext_stream(sdev, hext_stream, format_val); hext_stream->link_prepared = 1; -- cgit From e6ffb0d5eda751371d030bb8ae324493b2d1abc2 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:31 +0200 Subject: ASoC: SOF: Intel: hda-dai: Use the topology IPC dai_config op MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the topology IPC dai_config to update the dai_config for HDA DAI widgets. Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-11-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 86 +++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 43 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 9616cdba79b6..b726c0225110 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -29,6 +29,27 @@ MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override"); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) +static int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, + struct snd_sof_dai_config_data *data) +{ + struct snd_sof_widget *swidget = w->dobj.private; + struct snd_soc_component *component = swidget->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); + int ret; + + if (tplg_ops && tplg_ops->dai_config) { + ret = tplg_ops->dai_config(sdev, swidget, flags, data); + if (ret < 0) { + dev_err(sdev->dev, "DAI config with flags %x failed for widget %s\n", + flags, w->name); + return ret; + } + } + + return 0; +} + static const struct hda_dai_widget_dma_ops * hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { @@ -232,33 +253,16 @@ static int hda_dai_widget_update(struct snd_soc_dapm_widget *w, return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, &data); } -static int hda_dai_hw_params_update(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); - const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); - struct hdac_ext_stream *hext_stream; - int stream_tag; - - hext_stream = ops->get_hext_stream(sdev, dai, substream); - if (!hext_stream) - return -EINVAL; - - stream_tag = hdac_stream(hext_stream)->stream_tag; - - /* set up the DAI widget and send the DAI_CONFIG with the new tag */ - return hda_dai_widget_update(w, stream_tag - 1, true); -} - static int hda_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); struct hdac_ext_stream *hext_stream; + struct snd_sof_dai_config_data data = { 0 }; + unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; int ret; if (!ops) { @@ -274,35 +278,22 @@ static int hda_dai_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - return hda_dai_hw_params_update(substream, params, dai); -} - - -static int hda_dai_config_pause_push_ipc(struct snd_soc_dapm_widget *w) -{ - struct snd_sof_widget *swidget = w->dobj.private; - struct snd_soc_component *component = swidget->scomp; - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - int ret = 0; + hext_stream = ops->get_hext_stream(sdev, dai, substream); - if (tplg_ops->dai_config) { - ret = tplg_ops->dai_config(sdev, swidget, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL); - if (ret < 0) - dev_err(sdev->dev, "%s: DAI config failed for widget %s\n", __func__, - w->name); - } + flags |= SOF_DAI_CONFIG_FLAGS_2_STEP_STOP << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; + data.dai_data = hdac_stream(hext_stream)->stream_tag - 1; - return ret; + return hda_dai_config(w, flags, &data); } static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct hdac_ext_stream *hext_stream; - int stream = substream->stream; + struct snd_sof_dai_config_data data = { 0 }; + unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; int ret; hext_stream = ops->get_hext_stream(sdev, dai, substream); @@ -315,7 +306,12 @@ static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_d if (ret < 0) return ret; - return hda_dai_hw_params_update(substream, &rtd->dpcm[stream].hw_params, dai); + hext_stream = ops->get_hext_stream(sdev, dai, substream); + + flags |= SOF_DAI_CONFIG_FLAGS_2_STEP_STOP << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; + data.dai_data = hdac_stream(hext_stream)->stream_tag - 1; + + return hda_dai_config(w, flags, &data); } static int hda_dai_hw_free_ipc(int stream, /* direction */ @@ -356,7 +352,7 @@ static int ipc3_hda_dai_trigger(struct snd_pcm_substream *substream, break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ret = hda_dai_config_pause_push_ipc(w); + ret = hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL); if (ret < 0) return ret; break; @@ -462,13 +458,17 @@ static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, static int hda_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); + struct snd_sof_dai_config_data data = { 0 }; int ret; ret = hda_link_dma_hw_free(substream, dai); if (ret < 0) return ret; - return hda_dai_hw_free_ipc(substream->stream, dai); + data.dai_data = DMA_CHAN_INVALID; + + return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data); } static const struct snd_soc_dai_ops ipc3_hda_dai_ops = { -- cgit From 4b2ee4cd7103607b303a079c0469c06694be87e9 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:32 +0200 Subject: ASoC: SOF: Intel: hda-dai: Define DAI widget DMA trigger ops for IPC4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define and use the SOF widget's DMA pre_trigger/trigger/post_trigger ops in ipc4_hda_dai_trigger(). Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-12-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 128 +++++++++++++++++++++++++++++++++++++- sound/soc/sof/intel/hda-dai.c | 62 +++++------------- 2 files changed, 139 insertions(+), 51 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index 57db589906db..992c31772593 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -155,7 +155,129 @@ static void hda_reset_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stre snd_hdac_ext_stream_reset(hext_stream); } -static const struct hda_dai_widget_dma_ops hda_dma_ops = { +static int hda_ipc4_pre_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd) +{ + struct snd_sof_widget *pipe_widget; + struct sof_ipc4_pipeline *pipeline; + struct snd_sof_widget *swidget; + struct snd_soc_dapm_widget *w; + int ret; + + w = snd_soc_dai_get_widget(cpu_dai, substream->stream); + swidget = w->dobj.private; + pipe_widget = swidget->spipe->pipe_widget; + pipeline = pipe_widget->private; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, + SOF_IPC4_PIPE_PAUSED); + if (ret < 0) + return ret; + + pipeline->state = SOF_IPC4_PIPE_PAUSED; + break; + default: + dev_err(sdev->dev, "unknown trigger command %d\n", cmd); + return -EINVAL; + } + + return 0; +} + +static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd) +{ + struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + snd_hdac_ext_stream_start(hext_stream); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + snd_hdac_ext_stream_clear(hext_stream); + break; + default: + dev_err(sdev->dev, "unknown trigger command %d\n", cmd); + return -EINVAL; + } + + return 0; +} + +static int hda_ipc4_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd) +{ + struct snd_sof_widget *pipe_widget; + struct sof_ipc4_pipeline *pipeline; + struct snd_sof_widget *swidget; + struct snd_soc_dapm_widget *w; + int ret; + + w = snd_soc_dai_get_widget(cpu_dai, substream->stream); + swidget = w->dobj.private; + pipe_widget = swidget->spipe->pipe_widget; + pipeline = pipe_widget->private; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (pipeline->state != SOF_IPC4_PIPE_PAUSED) { + ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, + SOF_IPC4_PIPE_PAUSED); + if (ret < 0) + return ret; + pipeline->state = SOF_IPC4_PIPE_PAUSED; + } + + ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, + SOF_IPC4_PIPE_RUNNING); + if (ret < 0) + return ret; + pipeline->state = SOF_IPC4_PIPE_RUNNING; + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + { + ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, + SOF_IPC4_PIPE_RESET); + if (ret < 0) + return ret; + + pipeline->state = SOF_IPC4_PIPE_RESET; + break; + } + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + break; + default: + dev_err(sdev->dev, "unknown trigger command %d\n", cmd); + return -EINVAL; + } + + return 0; +} + +static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = { + .get_hext_stream = hda_get_hext_stream, + .assign_hext_stream = hda_assign_hext_stream, + .release_hext_stream = hda_release_hext_stream, + .setup_hext_stream = hda_setup_hext_stream, + .reset_hext_stream = hda_reset_hext_stream, + .pre_trigger = hda_ipc4_pre_trigger, + .trigger = hda_trigger, + .post_trigger = hda_ipc4_post_trigger +}; + +static const struct hda_dai_widget_dma_ops hda_ipc3_dma_ops = { .get_hext_stream = hda_get_hext_stream, .assign_hext_stream = hda_assign_hext_stream, .release_hext_stream = hda_release_hext_stream, @@ -177,7 +299,7 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg struct sof_dai_private_data *private = sdai->private; if (private->dai_config->type == SOF_DAI_INTEL_HDA) - return &hda_dma_ops; + return &hda_ipc3_dma_ops; break; } case SOF_INTEL_IPC4: @@ -185,7 +307,7 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg struct sof_ipc4_copier *ipc4_copier = sdai->private; if (ipc4_copier->dai_type == SOF_DAI_INTEL_HDA) - return &hda_dma_ops; + return &hda_ipc4_dma_ops; break; } default: diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index b726c0225110..60c65ce994a0 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -370,13 +370,9 @@ static int ipc3_hda_dai_trigger(struct snd_pcm_substream *substream, static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); - struct snd_sof_widget *swidget = w->dobj.private; struct hdac_ext_stream *hext_stream; - struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; - struct sof_ipc4_pipeline *pipeline = pipe_widget->private; struct snd_soc_pcm_runtime *rtd; struct snd_soc_dai *codec_dai; int ret; @@ -391,65 +387,35 @@ static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, rtd = asoc_substream_to_rtd(substream); codec_dai = asoc_rtd_to_codec(rtd, 0); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - snd_hdac_ext_stream_start(hext_stream); - if (pipeline->state != SOF_IPC4_PIPE_PAUSED) { - ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, - SOF_IPC4_PIPE_PAUSED); - if (ret < 0) - return ret; - pipeline->state = SOF_IPC4_PIPE_PAUSED; - } - - ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, - SOF_IPC4_PIPE_RUNNING); + if (ops->pre_trigger) { + ret = ops->pre_trigger(sdev, dai, substream, cmd); if (ret < 0) return ret; - pipeline->state = SOF_IPC4_PIPE_RUNNING; - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - { - ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, - SOF_IPC4_PIPE_PAUSED); + } + + if (ops->trigger) { + ret = ops->trigger(sdev, dai, substream, cmd); if (ret < 0) return ret; + } - pipeline->state = SOF_IPC4_PIPE_PAUSED; - - snd_hdac_ext_stream_clear(hext_stream); - - ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, - SOF_IPC4_PIPE_RESET); + if (ops->post_trigger) { + ret = ops->post_trigger(sdev, dai, substream, cmd); if (ret < 0) return ret; + } - pipeline->state = SOF_IPC4_PIPE_RESET; - + switch (cmd) { + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: ret = hda_link_dma_cleanup(substream, hext_stream, dai, codec_dai); if (ret < 0) { dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); return ret; } break; - } - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - { - ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, - SOF_IPC4_PIPE_PAUSED); - if (ret < 0) - return ret; - - pipeline->state = SOF_IPC4_PIPE_PAUSED; - - snd_hdac_ext_stream_clear(hext_stream); - break; - } default: - dev_err(sdev->dev, "%s: unknown trigger command %d\n", __func__, cmd); - return -EINVAL; + break; } return 0; -- cgit From 2b009fa0823c1510700fd17a0780ddd06a460fb4 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:33 +0200 Subject: ASoC: SOF: Intel: hda: Unify DAI drv ops for IPC3 and IPC4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define the post_trigger DMA op for IPC3 and unify the DAI driver ops for IPC3 and IPC4 for HDA DAI's. Also, use the post_trigger op to stop the paused streams properly in the hda_dai_suspend() function. This fixes the suspend while paused case for IPC4 because previously we weren't resetting the pipeline when suspending the system with some paused streams. Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-13-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 25 ++++++ sound/soc/sof/intel/hda-dai.c | 183 ++++++++------------------------------ sound/soc/sof/intel/hda.h | 2 + 3 files changed, 62 insertions(+), 148 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index 992c31772593..be109f33715f 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -277,12 +277,37 @@ static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = { .post_trigger = hda_ipc4_post_trigger }; +static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + { + struct snd_sof_dai_config_data data = { 0 }; + + data.dai_data = DMA_CHAN_INVALID; + return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data); + } + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL); + default: + break; + } + + return 0; +} + static const struct hda_dai_widget_dma_ops hda_ipc3_dma_ops = { .get_hext_stream = hda_get_hext_stream, .assign_hext_stream = hda_assign_hext_stream, .release_hext_stream = hda_release_hext_stream, .setup_hext_stream = hda_setup_hext_stream, .reset_hext_stream = hda_reset_hext_stream, + .trigger = hda_trigger, + .post_trigger = hda_ipc3_post_trigger, }; #endif diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 60c65ce994a0..4ac6148940ae 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -27,10 +27,8 @@ static bool hda_use_tplg_nhlt; module_param_named(sof_use_tplg_nhlt, hda_use_tplg_nhlt, bool, 0444); MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override"); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) - -static int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, - struct snd_sof_dai_config_data *data) +int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, + struct snd_sof_dai_config_data *data) { struct snd_sof_widget *swidget = w->dobj.private; struct snd_soc_component *component = swidget->scomp; @@ -50,6 +48,8 @@ static int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) + static const struct hda_dai_widget_dma_ops * hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { @@ -181,44 +181,6 @@ static int hda_link_dma_prepare(struct snd_pcm_substream *substream, struct snd_ return hda_link_dma_hw_params(substream, &rtd->dpcm[stream].hw_params, cpu_dai); } -static int hda_link_dma_trigger(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai, - int cmd) -{ - const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - struct hdac_ext_stream *hext_stream; - int ret; - - hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); - - if (!hext_stream) - return 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - snd_hdac_ext_stream_start(hext_stream); - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - snd_hdac_ext_stream_clear(hext_stream); - ret = hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai); - if (ret < 0) - return ret; - - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - snd_hdac_ext_stream_clear(hext_stream); - - break; - default: - return -EINVAL; - } - return 0; -} - static int hda_link_dma_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); @@ -239,20 +201,6 @@ static int hda_link_dma_hw_free(struct snd_pcm_substream *substream, struct snd_ return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai); } -static int hda_dai_widget_update(struct snd_soc_dapm_widget *w, - int channel, bool widget_setup) -{ - struct snd_sof_dai_config_data data; - - data.dai_data = channel; - - /* set up/free DAI widget and send DAI_CONFIG IPC */ - if (widget_setup) - return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_2_STEP_STOP, &data); - - return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, &data); -} - static int hda_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -314,61 +262,11 @@ static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_d return hda_dai_config(w, flags, &data); } -static int hda_dai_hw_free_ipc(int stream, /* direction */ - struct snd_soc_dai *dai) -{ - struct snd_soc_dapm_widget *w; - - w = snd_soc_dai_get_widget(dai, stream); - - /* free the link DMA channel in the FW and the DAI widget */ - return hda_dai_widget_update(w, DMA_CHAN_INVALID, false); -} - -static int ipc3_hda_dai_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct snd_soc_dapm_widget *w; - int ret; - - dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd, - dai->name, substream->stream); - - ret = hda_link_dma_trigger(substream, dai, cmd); - if (ret < 0) - return ret; - - w = snd_soc_dai_get_widget(dai, substream->stream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - /* - * free DAI widget during stop/suspend to keep widget use_count's balanced. - */ - ret = hda_dai_hw_free_ipc(substream->stream, dai); - if (ret < 0) - return ret; - - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ret = hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL); - if (ret < 0) - return ret; - break; - - default: - break; - } - return 0; -} - /* * In contrast to IPC3, the dai trigger in IPC4 mixes pipeline state changes * (over IPC channel) and DMA state change (direct host register changes). */ -static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) +static int hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); @@ -437,10 +335,10 @@ static int hda_dai_hw_free(struct snd_pcm_substream *substream, return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data); } -static const struct snd_soc_dai_ops ipc3_hda_dai_ops = { +static const struct snd_soc_dai_ops hda_dai_ops = { .hw_params = hda_dai_hw_params, .hw_free = hda_dai_hw_free, - .trigger = ipc3_hda_dai_trigger, + .trigger = hda_dai_trigger, .prepare = hda_dai_prepare, }; @@ -463,12 +361,22 @@ static int hda_dai_suspend(struct hdac_bus *bus) * explicitly during suspend. */ if (hext_stream->link_substream) { - struct snd_soc_dai *cpu_dai; + const struct hda_dai_widget_dma_ops *ops; + struct snd_sof_widget *swidget; + struct snd_soc_dapm_widget *w; struct snd_soc_dai *codec_dai; + struct snd_soc_dai *cpu_dai; + struct snd_sof_dev *sdev; + struct snd_sof_dai *sdai; rtd = asoc_substream_to_rtd(hext_stream->link_substream); cpu_dai = asoc_rtd_to_cpu(rtd, 0); codec_dai = asoc_rtd_to_codec(rtd, 0); + w = snd_soc_dai_get_widget(cpu_dai, hdac_stream(hext_stream)->direction); + swidget = w->dobj.private; + sdev = snd_soc_component_get_drvdata(swidget->scomp); + sdai = swidget->private; + ops = sdai->platform_private; ret = hda_link_dma_cleanup(hext_stream->link_substream, hext_stream, @@ -476,60 +384,39 @@ static int hda_dai_suspend(struct hdac_bus *bus) if (ret < 0) return ret; - /* for consistency with TRIGGER_SUSPEND we free DAI resources */ - ret = hda_dai_hw_free_ipc(hdac_stream(hext_stream)->direction, cpu_dai); - if (ret < 0) - return ret; + /* for consistency with TRIGGER_SUSPEND */ + if (ops->post_trigger) { + ret = ops->post_trigger(sdev, cpu_dai, + hext_stream->link_substream, + SNDRV_PCM_TRIGGER_SUSPEND); + if (ret < 0) + return ret; + } } } return 0; } -static const struct snd_soc_dai_ops ipc4_hda_dai_ops = { - .hw_params = hda_dai_hw_params, - .hw_free = hda_dai_hw_free, - .trigger = ipc4_hda_dai_trigger, - .prepare = hda_dai_prepare, -}; - #endif void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) { int i; - switch (sdev->pdata->ipc_type) { - case SOF_IPC: - for (i = 0; i < ops->num_drv; i++) { -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) - if (strstr(ops->drv[i].name, "iDisp") || - strstr(ops->drv[i].name, "Analog") || - strstr(ops->drv[i].name, "Digital")) - ops->drv[i].ops = &ipc3_hda_dai_ops; -#endif - } - break; - case SOF_INTEL_IPC4: - { - struct sof_ipc4_fw_data *ipc4_data = sdev->private; - - for (i = 0; i < ops->num_drv; i++) { + for (i = 0; i < ops->num_drv; i++) { #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) - if (strstr(ops->drv[i].name, "iDisp") || - strstr(ops->drv[i].name, "Analog") || - strstr(ops->drv[i].name, "Digital")) - ops->drv[i].ops = &ipc4_hda_dai_ops; + if (strstr(ops->drv[i].name, "iDisp") || + strstr(ops->drv[i].name, "Analog") || + strstr(ops->drv[i].name, "Digital")) + ops->drv[i].ops = &hda_dai_ops; #endif - } + } - if (!hda_use_tplg_nhlt) - ipc4_data->nhlt = intel_nhlt_init(sdev->dev); + if (sdev->pdata->ipc_type == SOF_INTEL_IPC4 && !hda_use_tplg_nhlt) { + struct sof_ipc4_fw_data *ipc4_data = sdev->private; - break; - } - default: - break; + ipc4_data->nhlt = intel_nhlt_init(sdev->dev); } } diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index e0469f86fa63..815f73d3acd2 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -962,5 +962,7 @@ struct hda_dai_widget_dma_ops { const struct hda_dai_widget_dma_ops * hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); +int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, + struct snd_sof_dai_config_data *data); #endif -- cgit From a492da0ce6450d6fdea49ec89006d7692c0c1382 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:34 +0200 Subject: ASoC: SOF: Intel: hda: Remove hda_ctrl_dai_widget_setup/free() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove these functions and reuse hda_dai_config(). Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-14-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 78 ++++------------------------------------------- sound/soc/sof/intel/hda.h | 4 --- 2 files changed, 6 insertions(+), 76 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 81c697e20108..890993b2f14b 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -44,70 +44,6 @@ #define EXCEPT_MAX_HDR_SIZE 0x400 #define HDA_EXT_ROM_STATUS_SIZE 8 -int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w, unsigned int quirk_flags, - struct snd_sof_dai_config_data *data) -{ - struct snd_sof_widget *swidget = w->dobj.private; - struct snd_soc_component *component = swidget->scomp; - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - struct snd_sof_dai *sof_dai = swidget->private; - int ret; - - if (!sof_dai) { - dev_err(sdev->dev, "%s: No DAI for DAI widget %s\n", __func__, w->name); - return -EINVAL; - } - - if (tplg_ops->dai_config) { - unsigned int flags; - - /* set HW_PARAMS flag along with quirks */ - flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS | - quirk_flags << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; - - ret = tplg_ops->dai_config(sdev, swidget, flags, data); - if (ret < 0) { - dev_err(sdev->dev, "%s: DAI config failed for widget %s\n", __func__, - w->name); - return ret; - } - } - - return 0; -} - -int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_flags, - struct snd_sof_dai_config_data *data) -{ - struct snd_sof_widget *swidget = w->dobj.private; - struct snd_soc_component *component = swidget->scomp; - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - struct snd_sof_dai *sof_dai = swidget->private; - - if (!sof_dai) { - dev_err(sdev->dev, "%s: No DAI for BE DAI widget %s\n", __func__, w->name); - return -EINVAL; - } - - if (tplg_ops->dai_config) { - unsigned int flags; - int ret; - - /* set HW_FREE flag along with any quirks */ - flags = SOF_DAI_CONFIG_FLAGS_HW_FREE | - quirk_flags << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; - - ret = tplg_ops->dai_config(sdev, swidget, flags, data); - if (ret < 0) - dev_err(sdev->dev, "%s: DAI config failed for widget '%s'\n", __func__, - w->name); - } - - return 0; -} - #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) /* @@ -124,30 +60,28 @@ static int sdw_params_stream(struct device *dev, struct sdw_intel_stream_params_data *params_data) { struct snd_soc_dai *d = params_data->dai; - struct snd_sof_dai_config_data data; - struct snd_soc_dapm_widget *w; + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(d, params_data->stream); + struct snd_sof_dai_config_data data = { 0 }; - w = snd_soc_dai_get_widget(d, params_data->stream); data.dai_index = (params_data->link_id << 8) | d->id; data.dai_data = params_data->alh_stream_id; - return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_NONE, &data); + return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_PARAMS, &data); } static int sdw_free_stream(struct device *dev, struct sdw_intel_stream_free_data *free_data) { struct snd_soc_dai *d = free_data->dai; - struct snd_sof_dai_config_data data; - struct snd_soc_dapm_widget *w; + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(d, free_data->stream); + struct snd_sof_dai_config_data data = { 0 }; - w = snd_soc_dai_get_widget(d, free_data->stream); data.dai_index = (free_data->link_id << 8) | d->id; /* send invalid stream_id */ data.dai_data = 0xFFFF; - return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, &data); + return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data); } struct sdw_intel_ops sdw_callback = { diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 815f73d3acd2..2a43bfc14583 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -896,10 +896,6 @@ int hda_pci_intel_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) struct snd_sof_dai; struct sof_ipc_dai_config; -int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w, unsigned int quirk_flags, - struct snd_sof_dai_config_data *data); -int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_flags, - struct snd_sof_dai_config_data *data); #define SOF_HDA_POSITION_QUIRK_USE_SKYLAKE_LEGACY (0) /* previous implementation */ #define SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS (1) /* recommended if VC0 only */ -- cgit From 8c29e78b8ecbec208bdd6d8b385ada71c1e730cd Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 7 Mar 2023 16:04:35 +0200 Subject: ASoC: SOF: Intel: hda: remove redundant DAI config during hw_free The DAI widget is freed during FE DAI hw_free and therefore the DAI config during BE DAI hw_free is redundant. Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Rander Wang Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230307140435.2808-15-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 18 +----------------- sound/soc/sof/intel/hda.c | 16 ---------------- 2 files changed, 1 insertion(+), 33 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 4ac6148940ae..9637f0f44b01 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -181,7 +181,7 @@ static int hda_link_dma_prepare(struct snd_pcm_substream *substream, struct snd_ return hda_link_dma_hw_params(substream, &rtd->dpcm[stream].hw_params, cpu_dai); } -static int hda_link_dma_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) +static int hda_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); @@ -319,22 +319,6 @@ static int hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct return 0; } -static int hda_dai_hw_free(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); - struct snd_sof_dai_config_data data = { 0 }; - int ret; - - ret = hda_link_dma_hw_free(substream, dai); - if (ret < 0) - return ret; - - data.dai_data = DMA_CHAN_INVALID; - - return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data); -} - static const struct snd_soc_dai_ops hda_dai_ops = { .hw_params = hda_dai_hw_params, .hw_free = hda_dai_hw_free, diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 890993b2f14b..65389c7278e2 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -69,24 +69,8 @@ static int sdw_params_stream(struct device *dev, return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_PARAMS, &data); } -static int sdw_free_stream(struct device *dev, - struct sdw_intel_stream_free_data *free_data) -{ - struct snd_soc_dai *d = free_data->dai; - struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(d, free_data->stream); - struct snd_sof_dai_config_data data = { 0 }; - - data.dai_index = (free_data->link_id << 8) | d->id; - - /* send invalid stream_id */ - data.dai_data = 0xFFFF; - - return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data); -} - struct sdw_intel_ops sdw_callback = { .params_stream = sdw_params_stream, - .free_stream = sdw_free_stream, }; void hda_common_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable) -- cgit From df6380dca2727bca62efdf332eaadd2e225f7c4d Mon Sep 17 00:00:00 2001 From: V sujith kumar Reddy Date: Wed, 8 Mar 2023 14:15:08 +0530 Subject: ASoC: SOF: amd: Add pcm pointer callback for amd platforms. Add pcm pointer callback for amd platforms to read host position update from stream box. Signed-off-by: V sujith kumar Reddy Link: https://lore.kernel.org/r/20230308084509.1496256-2-Vsujithkumar.Reddy@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp-common.c | 1 + sound/soc/sof/amd/acp-pcm.c | 33 +++++++++++++++++++++++++++++++++ sound/soc/sof/amd/acp.h | 2 ++ 3 files changed, 36 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c index bd6c1b198736..8ce4c8956933 100644 --- a/sound/soc/sof/amd/acp-common.c +++ b/sound/soc/sof/amd/acp-common.c @@ -187,6 +187,7 @@ struct snd_sof_dsp_ops sof_acp_common_ops = { .pcm_open = acp_pcm_open, .pcm_close = acp_pcm_close, .pcm_hw_params = acp_pcm_hw_params, + .pcm_pointer = acp_pcm_pointer, .hw_info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | diff --git a/sound/soc/sof/amd/acp-pcm.c b/sound/soc/sof/amd/acp-pcm.c index 727c3a784a20..f342f0bac4a3 100644 --- a/sound/soc/sof/amd/acp-pcm.c +++ b/sound/soc/sof/amd/acp-pcm.c @@ -84,3 +84,36 @@ int acp_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) return acp_dsp_stream_put(sdev, stream); } EXPORT_SYMBOL_NS(acp_pcm_close, SND_SOC_SOF_AMD_COMMON); + +snd_pcm_uframes_t acp_pcm_pointer(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_component *scomp = sdev->component; + struct snd_sof_pcm_stream *stream; + struct sof_ipc_stream_posn posn; + struct snd_sof_pcm *spcm; + snd_pcm_uframes_t pos; + int ret; + + spcm = snd_sof_find_spcm_dai(scomp, rtd); + if (!spcm) { + dev_warn_ratelimited(sdev->dev, "warn: can't find PCM with DAI ID %d\n", + rtd->dai_link->id); + return 0; + } + + stream = &spcm->stream[substream->stream]; + ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn)); + if (ret < 0) { + dev_warn(sdev->dev, "failed to read stream position: %d\n", ret); + return 0; + } + + memcpy(&stream->posn, &posn, sizeof(posn)); + pos = spcm->stream[substream->stream].posn.host_posn; + pos = bytes_to_frames(substream->runtime, pos); + + return pos; +} +EXPORT_SYMBOL_NS(acp_pcm_pointer, SND_SOC_SOF_AMD_COMMON); diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index 39165ebf684b..acad57947616 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -238,6 +238,8 @@ int acp_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) int acp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_sof_platform_stream_params *platform_params); +snd_pcm_uframes_t acp_pcm_pointer(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream); extern struct snd_sof_dsp_ops sof_acp_common_ops; -- cgit From b7f5c11761691a6f330411cb0490c6d0ee16c5f0 Mon Sep 17 00:00:00 2001 From: V sujith kumar Reddy Date: Wed, 8 Mar 2023 14:15:09 +0530 Subject: ASoC: SOF: amd: Enable cont_update_posn variable in pcm hw_params. Enable cont_update_posn variable to update host position in streambox for every dma copy. Signed-off-by: V sujith kumar Reddy Link: https://lore.kernel.org/r/20230308084509.1496256-3-Vsujithkumar.Reddy@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp-pcm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/sof/amd/acp-pcm.c b/sound/soc/sof/amd/acp-pcm.c index f342f0bac4a3..0828245bbb99 100644 --- a/sound/soc/sof/amd/acp-pcm.c +++ b/sound/soc/sof/amd/acp-pcm.c @@ -39,6 +39,7 @@ int acp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substr platform_params->use_phy_address = true; platform_params->phy_addr = stream->reg_offset; platform_params->stream_tag = stream->stream_tag; + platform_params->cont_update_posn = 1; /* write buffer size of stream in scratch memory */ -- cgit From 8987986b07f5dded3f81b159f5bb146f2d1a21ed Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Thu, 9 Mar 2023 14:00:51 +0000 Subject: ASoC: cs35l41: Steam Deck Shared boost properties quirk Add support for Steam Deck bios old properties. If a Steam deck didn't upgrade the BIOS, the driver should be able to handle the previous properties for shared boost types. Signed-off-by: Lucas Tanure Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20230309140051.945329-1-lucas.tanure@collabora.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l41.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index 1624510d09c0..9ec01a5f09ca 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -1022,9 +1022,21 @@ static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_hw_cfg *hw_cf unsigned int val; int ret; - ret = device_property_read_u32(dev, "cirrus,boost-type", &val); - if (ret >= 0) - hw_cfg->bst_type = val; + /* Some ACPI systems received the Shared Boost feature before the upstream driver, + * leaving those systems with deprecated _DSD properties. + * To correctly configure those systems add shared-boost-active and shared-boost-passive + * properties mapped to the correct value in boost-type. + * These two are not DT properties and should not be used in new systems designs. + */ + if (device_property_read_bool(dev, "cirrus,shared-boost-active")) { + hw_cfg->bst_type = CS35L41_SHD_BOOST_ACTV; + } else if (device_property_read_bool(dev, "cirrus,shared-boost-passive")) { + hw_cfg->bst_type = CS35L41_SHD_BOOST_PASS; + } else { + ret = device_property_read_u32(dev, "cirrus,boost-type", &val); + if (ret >= 0) + hw_cfg->bst_type = val; + } ret = device_property_read_u32(dev, "cirrus,boost-peak-milliamp", &val); if (ret >= 0) -- cgit From 75034eb5e4c267d4ab93085b5d6fa3dab2535b34 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 10 Mar 2023 15:34:54 +0200 Subject: ASoC: SOF: Intel: MTL: Don't access EM2 This reverts commit 2b5a30cafb2ef ("ASoC: SOF: Intel: MTL: Enable DMI L1"). It came to our attention that the access to the EM2 register is restricted to the DSP side on MTL compared to prior platforms. Writing to it from the host side has no effect (negative or positive), it is better to remove the code to not cause confusion and wrong impression. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230310133454.15362-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 3 --- sound/soc/sof/intel/mtl.h | 2 -- 2 files changed, 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 8f0ed1cbf3b5..58959c24cb71 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -280,9 +280,6 @@ static int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev) } hda_sdw_int_enable(sdev, true); - - /* enable DMI L1 */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, MTL_EM2, MTL_EM2_L1SEN, MTL_EM2_L1SEN); return 0; } diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h index ddc05304a9d5..26418fb08807 100644 --- a/sound/soc/sof/intel/mtl.h +++ b/sound/soc/sof/intel/mtl.h @@ -28,8 +28,6 @@ #define MTL_HFINTIPPTR_PTR_MASK GENMASK(20, 0) #define MTL_HDA_VS_D0I3C 0x1D4A -#define MTL_EM2 0x1c44 -#define MTL_EM2_L1SEN BIT(13) #define MTL_DSP2CXCAP_PRIMARY_CORE 0x178D00 #define MTL_DSP2CXCTL_PRIMARY_CORE 0x178D04 -- cgit From 1e108e60a44a924e3666fa2a10b53f6c31522856 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 10 Mar 2023 08:47:31 -0600 Subject: ASoC: Use of_property_present() for testing DT property presence It is preferred to use typed property access functions (i.e. of_property_read_ functions) rather than low-level of_get_property/of_find_property functions for reading properties. As part of this, convert of_get_property/of_find_property calls to the recently added of_property_present() helper when we just want to test for presence of a property and nothing more. Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20230310144732.1546328-1-robh@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-macro-common.c | 2 +- sound/soc/generic/audio-graph-card.c | 2 +- sound/soc/generic/audio-graph-card2.c | 2 +- sound/soc/mxs/mxs-sgtl5000.c | 2 +- sound/soc/samsung/i2s.c | 2 +- sound/soc/sh/fsi.c | 2 +- sound/soc/stm/stm32_i2s.c | 2 +- sound/soc/stm/stm32_sai_sub.c | 4 ++-- sound/soc/tegra/tegra_asoc_machine.c | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/lpass-macro-common.c b/sound/soc/codecs/lpass-macro-common.c index 1b9082d237c1..f54baaad54d4 100644 --- a/sound/soc/codecs/lpass-macro-common.c +++ b/sound/soc/codecs/lpass-macro-common.c @@ -16,7 +16,7 @@ struct lpass_macro *lpass_macro_pds_init(struct device *dev) struct lpass_macro *l_pds; int ret; - if (!of_find_property(dev->of_node, "power-domains", NULL)) + if (!of_property_present(dev->of_node, "power-domains")) return NULL; l_pds = devm_kzalloc(dev, sizeof(*l_pds), GFP_KERNEL); diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 5daa824a4ffc..d788f5f23a8a 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -78,7 +78,7 @@ static int graph_get_dai_id(struct device_node *ep) * only of_graph_parse_endpoint(). * We need to check "reg" property */ - if (of_get_property(ep, "reg", NULL)) + if (of_property_present(ep, "reg")) return info.id; node = of_get_parent(ep); diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 06609a526b78..259544f64df9 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -376,7 +376,7 @@ static int graph_get_dai_id(struct device_node *ep) * only of_graph_parse_endpoint(). * We need to check "reg" property */ - if (of_get_property(ep, "reg", NULL)) + if (of_property_present(ep, "reg")) return info.id; node = of_get_parent(ep); diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 746f40938675..a55e7256a4c3 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -150,7 +150,7 @@ static int mxs_sgtl5000_probe(struct platform_device *pdev) card->dev = &pdev->dev; - if (of_find_property(np, "audio-routing", NULL)) { + if (of_property_present(np, "audio-routing")) { card->dapm_widgets = mxs_sgtl5000_dapm_widgets; card->num_dapm_widgets = ARRAY_SIZE(mxs_sgtl5000_dapm_widgets); diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 6f96032090de..083e278aa021 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1289,7 +1289,7 @@ static int i2s_register_clock_provider(struct samsung_i2s_priv *priv) int ret, i; /* Register the clock provider only if it's expected in the DTB */ - if (!of_find_property(dev->of_node, "#clock-cells", NULL)) + if (!of_property_present(dev->of_node, "#clock-cells")) return 0; /* Get the RCLKSRC mux clock parent clock names */ diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index f3edc2e3d9d7..9f3f1af6349f 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1855,7 +1855,7 @@ static void fsi_of_parse(char *name, for (i = 0; i < ARRAY_SIZE(of_parse_property); i++) { sprintf(prop, "%s,%s", name, of_parse_property[i].name); - if (of_get_property(np, prop, NULL)) + if (of_property_present(np, prop)) flags |= of_parse_property[i].val; } info->flags = flags; diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index f3dd9f8e621c..9dad85ecb93f 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -1066,7 +1066,7 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, "Could not get x11k parent clock\n"); /* Register mclk provider if requested */ - if (of_find_property(np, "#clock-cells", NULL)) { + if (of_property_present(np, "#clock-cells")) { ret = stm32_i2s_add_mclk_provider(i2s); if (ret < 0) return ret; diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index eb31b49e6597..8ba4206f751d 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1394,7 +1394,7 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, /* Get spdif iec60958 property */ sai->spdif = false; - if (of_get_property(np, "st,iec60958", NULL)) { + if (of_property_present(np, "st,iec60958")) { if (!STM_SAI_HAS_SPDIF(sai) || sai->dir == SNDRV_PCM_STREAM_CAPTURE) { dev_err(&pdev->dev, "S/PDIF IEC60958 not supported\n"); @@ -1480,7 +1480,7 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, return 0; /* Register mclk provider if requested */ - if (of_find_property(np, "#clock-cells", NULL)) { + if (of_property_present(np, "#clock-cells")) { ret = stm32_sai_add_mclk_provider(sai); if (ret < 0) return ret; diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c index 78faa8bcae27..2dc1f44c5a8b 100644 --- a/sound/soc/tegra/tegra_asoc_machine.c +++ b/sound/soc/tegra/tegra_asoc_machine.c @@ -502,7 +502,7 @@ int tegra_asoc_machine_probe(struct platform_device *pdev) * If clock parents are not set in DT, configure here to use clk_out_1 * as mclk and extern1 as parent for Tegra30 and higher. */ - if (!of_find_property(dev->of_node, "assigned-clock-parents", NULL) && + if (!of_property_present(dev->of_node, "assigned-clock-parents") && !of_machine_is_compatible("nvidia,tegra20")) { struct clk *clk_out_1, *clk_extern1; -- cgit From 2d2998b84330899bf88a0414f3356869be4a69eb Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 10 Mar 2023 08:47:32 -0600 Subject: ASoC: Use of_property_read_bool() for boolean properties It is preferred to use typed property access functions (i.e. of_property_read_ functions) rather than low-level of_get_property/of_find_property functions for reading properties. Convert reading boolean properties to to of_property_read_bool(). Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20230310144733.1546413-1-robh@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/sta32x.c | 39 +++++++++++++--------------- sound/soc/codecs/sta350.c | 63 +++++++++++++++++++++------------------------- sound/soc/codecs/tas5086.c | 2 +- sound/soc/fsl/fsl_sai.c | 12 ++++----- sound/soc/fsl/fsl_ssi.c | 2 +- sound/soc/fsl/imx-card.c | 2 +- sound/soc/sh/rcar/ssi.c | 4 +-- 7 files changed, 57 insertions(+), 67 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 8c86b578eba8..29af9595dac1 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -1054,35 +1054,32 @@ static int sta32x_probe_dt(struct device *dev, struct sta32x_priv *sta32x) of_property_read_u8(np, "st,ch3-output-mapping", &pdata->ch3_output_mapping); - if (of_get_property(np, "st,fault-detect-recovery", NULL)) - pdata->fault_detect_recovery = 1; - if (of_get_property(np, "st,thermal-warning-recovery", NULL)) - pdata->thermal_warning_recovery = 1; - if (of_get_property(np, "st,thermal-warning-adjustment", NULL)) - pdata->thermal_warning_adjustment = 1; - if (of_get_property(np, "st,needs_esd_watchdog", NULL)) - pdata->needs_esd_watchdog = 1; + pdata->fault_detect_recovery = + of_property_read_bool(np, "st,fault-detect-recovery"); + pdata->thermal_warning_recovery = + of_property_read_bool(np, "st,thermal-warning-recovery"); + pdata->thermal_warning_adjustment = + of_property_read_bool(np, "st,thermal-warning-adjustment"); + pdata->needs_esd_watchdog = + of_property_read_bool(np, "st,needs_esd_watchdog"); tmp = 140; of_property_read_u16(np, "st,drop-compensation-ns", &tmp); pdata->drop_compensation_ns = clamp_t(u16, tmp, 0, 300) / 20; /* CONFE */ - if (of_get_property(np, "st,max-power-use-mpcc", NULL)) - pdata->max_power_use_mpcc = 1; - - if (of_get_property(np, "st,max-power-correction", NULL)) - pdata->max_power_correction = 1; - - if (of_get_property(np, "st,am-reduction-mode", NULL)) - pdata->am_reduction_mode = 1; - - if (of_get_property(np, "st,odd-pwm-speed-mode", NULL)) - pdata->odd_pwm_speed_mode = 1; + pdata->max_power_use_mpcc = + of_property_read_bool(np, "st,max-power-use-mpcc"); + pdata->max_power_correction = + of_property_read_bool(np, "st,max-power-correction"); + pdata->am_reduction_mode = + of_property_read_bool(np, "st,am-reduction-mode"); + pdata->odd_pwm_speed_mode = + of_property_read_bool(np, "st,odd-pwm-speed-mode"); /* CONFF */ - if (of_get_property(np, "st,invalid-input-detect-mute", NULL)) - pdata->invalid_input_detect_mute = 1; + pdata->invalid_input_detect_mute = + of_property_read_bool(np, "st,invalid-input-detect-mute"); sta32x->pdata = pdata; diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index 9ed13aeb3cbd..b033a5fcd6c0 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c @@ -1106,12 +1106,12 @@ static int sta350_probe_dt(struct device *dev, struct sta350_priv *sta350) of_property_read_u8(np, "st,ch3-output-mapping", &pdata->ch3_output_mapping); - if (of_get_property(np, "st,thermal-warning-recovery", NULL)) - pdata->thermal_warning_recovery = 1; - if (of_get_property(np, "st,thermal-warning-adjustment", NULL)) - pdata->thermal_warning_adjustment = 1; - if (of_get_property(np, "st,fault-detect-recovery", NULL)) - pdata->fault_detect_recovery = 1; + pdata->thermal_warning_recovery = + of_property_read_bool(np, "st,thermal-warning-recovery"); + pdata->thermal_warning_adjustment = + of_property_read_bool(np, "st,thermal-warning-adjustment"); + pdata->fault_detect_recovery = + of_property_read_bool(np, "st,fault-detect-recovery"); pdata->ffx_power_output_mode = STA350_FFX_PM_VARIABLE_DROP_COMP; if (!of_property_read_string(np, "st,ffx-power-output-mode", @@ -1133,41 +1133,34 @@ static int sta350_probe_dt(struct device *dev, struct sta350_priv *sta350) of_property_read_u16(np, "st,drop-compensation-ns", &tmp); pdata->drop_compensation_ns = clamp_t(u16, tmp, 0, 300) / 20; - if (of_get_property(np, "st,overcurrent-warning-adjustment", NULL)) - pdata->oc_warning_adjustment = 1; + pdata->oc_warning_adjustment = + of_property_read_bool(np, "st,overcurrent-warning-adjustment"); /* CONFE */ - if (of_get_property(np, "st,max-power-use-mpcc", NULL)) - pdata->max_power_use_mpcc = 1; - - if (of_get_property(np, "st,max-power-correction", NULL)) - pdata->max_power_correction = 1; - - if (of_get_property(np, "st,am-reduction-mode", NULL)) - pdata->am_reduction_mode = 1; - - if (of_get_property(np, "st,odd-pwm-speed-mode", NULL)) - pdata->odd_pwm_speed_mode = 1; - - if (of_get_property(np, "st,distortion-compensation", NULL)) - pdata->distortion_compensation = 1; + pdata->max_power_use_mpcc = + of_property_read_bool(np, "st,max-power-use-mpcc"); + pdata->max_power_correction = + of_property_read_bool(np, "st,max-power-correction"); + pdata->am_reduction_mode = + of_property_read_bool(np, "st,am-reduction-mode"); + pdata->odd_pwm_speed_mode = + of_property_read_bool(np, "st,odd-pwm-speed-mode"); + pdata->distortion_compensation = + of_property_read_bool(np, "st,distortion-compensation"); /* CONFF */ - if (of_get_property(np, "st,invalid-input-detect-mute", NULL)) - pdata->invalid_input_detect_mute = 1; + pdata->invalid_input_detect_mute = + of_property_read_bool(np, "st,invalid-input-detect-mute"); /* MISC */ - if (of_get_property(np, "st,activate-mute-output", NULL)) - pdata->activate_mute_output = 1; - - if (of_get_property(np, "st,bridge-immediate-off", NULL)) - pdata->bridge_immediate_off = 1; - - if (of_get_property(np, "st,noise-shape-dc-cut", NULL)) - pdata->noise_shape_dc_cut = 1; - - if (of_get_property(np, "st,powerdown-master-volume", NULL)) - pdata->powerdown_master_vol = 1; + pdata->activate_mute_output = + of_property_read_bool(np, "st,activate-mute-output"); + pdata->bridge_immediate_off = + of_property_read_bool(np, "st,bridge-immediate-off"); + pdata->noise_shape_dc_cut = + of_property_read_bool(np, "st,noise-shape-dc-cut"); + pdata->powerdown_master_vol = + of_property_read_bool(np, "st,powerdown-master-volume"); if (!of_property_read_u8(np, "st,powerdown-delay-divider", &tmp8)) { if (is_power_of_2(tmp8) && tmp8 >= 1 && tmp8 <= 128) diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index 22143cc5afa7..f9e7122894bd 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c @@ -840,7 +840,7 @@ static int tas5086_probe(struct snd_soc_component *component) snprintf(name, sizeof(name), "ti,mid-z-channel-%d", i + 1); - if (of_get_property(of_node, name, NULL) != NULL) + if (of_property_read_bool(of_node, name)) priv->pwm_start_mid_z |= 1 << i; } } diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 1b197478b3d9..4e6b75f1ddd0 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -1380,18 +1380,18 @@ static int fsl_sai_probe(struct platform_device *pdev) sai->cpu_dai_drv.symmetric_channels = 1; sai->cpu_dai_drv.symmetric_sample_bits = 1; - if (of_find_property(np, "fsl,sai-synchronous-rx", NULL) && - of_find_property(np, "fsl,sai-asynchronous", NULL)) { + if (of_property_read_bool(np, "fsl,sai-synchronous-rx") && + of_property_read_bool(np, "fsl,sai-asynchronous")) { /* error out if both synchronous and asynchronous are present */ dev_err(dev, "invalid binding for synchronous mode\n"); return -EINVAL; } - if (of_find_property(np, "fsl,sai-synchronous-rx", NULL)) { + if (of_property_read_bool(np, "fsl,sai-synchronous-rx")) { /* Sync Rx with Tx */ sai->synchronous[RX] = false; sai->synchronous[TX] = true; - } else if (of_find_property(np, "fsl,sai-asynchronous", NULL)) { + } else if (of_property_read_bool(np, "fsl,sai-asynchronous")) { /* Discard all settings for asynchronous mode */ sai->synchronous[RX] = false; sai->synchronous[TX] = false; @@ -1400,7 +1400,7 @@ static int fsl_sai_probe(struct platform_device *pdev) sai->cpu_dai_drv.symmetric_sample_bits = 0; } - if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) && + if (of_property_read_bool(np, "fsl,sai-mclk-direction-output") && of_device_is_compatible(np, "fsl,imx6ul-sai")) { gpr = syscon_regmap_lookup_by_compatible("fsl,imx6ul-iomuxc-gpr"); if (IS_ERR(gpr)) { @@ -1443,7 +1443,7 @@ static int fsl_sai_probe(struct platform_device *pdev) dev_warn(dev, "Error reading SAI version: %d\n", ret); /* Select MCLK direction */ - if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) && + if (of_property_read_bool(np, "fsl,sai-mclk-direction-output") && sai->soc_data->max_register >= FSL_SAI_MCTL) { regmap_update_bits(sai->regmap, FSL_SAI_MCTL, FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN); diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 46a53551b955..6af00b62a60f 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1447,7 +1447,7 @@ static int fsl_ssi_probe_from_dt(struct fsl_ssi *ssi) return -EINVAL; } strcpy(ssi->card_name, "ac97-codec"); - } else if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) { + } else if (!of_property_read_bool(np, "fsl,ssi-asynchronous")) { /* * In synchronous mode, STCK and STFS ports are used by RX * as well. So the software should limit the sample rates, diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c index 3f128ced4180..64a4d7e9db60 100644 --- a/sound/soc/fsl/imx-card.c +++ b/sound/soc/fsl/imx-card.c @@ -563,7 +563,7 @@ static int imx_card_parse_of(struct imx_card_data *data) link_data->cpu_sysclk_id = FSL_SAI_CLK_MAST1; /* sai may support mclk/bclk = 1 */ - if (of_find_property(np, "fsl,mclk-equal-bclk", NULL)) { + if (of_property_read_bool(np, "fsl,mclk-equal-bclk")) { link_data->one2one_ratio = true; } else { int i; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 8ddee5b03ece..690ac0d6ef41 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -1211,10 +1211,10 @@ int rsnd_ssi_probe(struct rsnd_priv *priv) goto rsnd_ssi_probe_done; } - if (of_get_property(np, "shared-pin", NULL)) + if (of_property_read_bool(np, "shared-pin")) rsnd_flags_set(ssi, RSND_SSI_CLK_PIN_SHARE); - if (of_get_property(np, "no-busif", NULL)) + if (of_property_read_bool(np, "no-busif")) rsnd_flags_set(ssi, RSND_SSI_NO_BUSIF); ssi->irq = irq_of_parse_and_map(np, 0); -- cgit From 3eac8de3f51b3567c4ba6139736b59027da56285 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 13 Mar 2023 13:03:38 +0200 Subject: ASoC: SOF: ipc3-control: Rename snd_sof_refresh_control() Rename the snd_sof_refresh_control() to sof_ipc3_refresh_control() to follow the function naming convention for IPC specific code. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230313110344.16644-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc3-control.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c index 217ac5501a98..4e9d04124145 100644 --- a/sound/soc/sof/ipc3-control.c +++ b/sound/soc/sof/ipc3-control.c @@ -104,7 +104,7 @@ unlock: return ret; } -static void snd_sof_refresh_control(struct snd_sof_control *scontrol) +static void sof_ipc3_refresh_control(struct snd_sof_control *scontrol) { struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; struct snd_soc_component *scomp = scontrol->scomp; @@ -138,7 +138,7 @@ static int sof_ipc3_volume_get(struct snd_sof_control *scontrol, unsigned int channels = scontrol->num_channels; unsigned int i; - snd_sof_refresh_control(scontrol); + sof_ipc3_refresh_control(scontrol); /* read back each channel */ for (i = 0; i < channels; i++) @@ -189,7 +189,7 @@ static int sof_ipc3_switch_get(struct snd_sof_control *scontrol, unsigned int channels = scontrol->num_channels; unsigned int i; - snd_sof_refresh_control(scontrol); + sof_ipc3_refresh_control(scontrol); /* read back each channel */ for (i = 0; i < channels; i++) @@ -237,7 +237,7 @@ static int sof_ipc3_enum_get(struct snd_sof_control *scontrol, unsigned int channels = scontrol->num_channels; unsigned int i; - snd_sof_refresh_control(scontrol); + sof_ipc3_refresh_control(scontrol); /* read back each channel */ for (i = 0; i < channels; i++) @@ -286,7 +286,7 @@ static int sof_ipc3_bytes_get(struct snd_sof_control *scontrol, struct sof_abi_hdr *data = cdata->data; size_t size; - snd_sof_refresh_control(scontrol); + sof_ipc3_refresh_control(scontrol); if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n", @@ -352,7 +352,7 @@ static int sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol, struct snd_ctl_tlv header; size_t data_size; - snd_sof_refresh_control(scontrol); + sof_ipc3_refresh_control(scontrol); /* * Decrement the limit by ext bytes header size to -- cgit From 76fc628aebdb452e3c620d9ff5c5e9448d316754 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 13 Mar 2023 13:03:39 +0200 Subject: ASoC: SOF: ipc3-control: Merge functions to handle bytes_ext get variants The code for bytes_ext_get and bytes_ext_volatile_get is identical with the only difference is that in case of volatile_get we refresh the data from the DSP before returning it to user space. Convert the callbacks to a simple wrapper for the same function. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230313110344.16644-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc3-control.c | 80 +++++++++++++------------------------------- 1 file changed, 23 insertions(+), 57 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c index 4e9d04124145..ad040e7bb850 100644 --- a/sound/soc/sof/ipc3-control.c +++ b/sound/soc/sof/ipc3-control.c @@ -343,55 +343,6 @@ static int sof_ipc3_bytes_put(struct snd_sof_control *scontrol, return 0; } -static int sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol, - const unsigned int __user *binary_data, unsigned int size) -{ - struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - struct snd_soc_component *scomp = scontrol->scomp; - struct snd_ctl_tlv header; - size_t data_size; - - sof_ipc3_refresh_control(scontrol); - - /* - * Decrement the limit by ext bytes header size to - * ensure the user space buffer is not exceeded. - */ - if (size < sizeof(struct snd_ctl_tlv)) - return -ENOSPC; - - size -= sizeof(struct snd_ctl_tlv); - - /* set the ABI header values */ - cdata->data->magic = SOF_ABI_MAGIC; - cdata->data->abi = SOF_ABI_VERSION; - - /* check data size doesn't exceed max coming from topology */ - if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { - dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n", - cdata->data->size, - scontrol->max_size - sizeof(struct sof_abi_hdr)); - return -EINVAL; - } - - data_size = cdata->data->size + sizeof(struct sof_abi_hdr); - - /* make sure we don't exceed size provided by user space for data */ - if (data_size > size) - return -ENOSPC; - - header.numid = cdata->cmd; - header.length = data_size; - if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv))) - return -EFAULT; - - if (copy_to_user(tlvd->tlv, cdata->data, data_size)) - return -EFAULT; - - return 0; -} - static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol, const unsigned int __user *binary_data, unsigned int size) @@ -457,16 +408,15 @@ static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol, return 0; } -static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol, - const unsigned int __user *binary_data, - unsigned int size) +static int _sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, + unsigned int size, bool from_dsp) { struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; struct snd_soc_component *scomp = scontrol->scomp; struct snd_ctl_tlv header; size_t data_size; - int ret; /* * Decrement the limit by ext bytes header size to @@ -482,9 +432,12 @@ static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol, cdata->data->abi = SOF_ABI_VERSION; /* get all the component data from DSP */ - ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, true); - if (ret < 0) - return ret; + if (from_dsp) { + int ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, true); + + if (ret < 0) + return ret; + } /* check data size doesn't exceed max coming from topology */ if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { @@ -508,7 +461,20 @@ static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol, if (copy_to_user(tlvd->tlv, cdata->data, data_size)) return -EFAULT; - return ret; + return 0; +} + +static int sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, unsigned int size) +{ + return _sof_ipc3_bytes_ext_get(scontrol, binary_data, size, false); +} + +static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, + unsigned int size) +{ + return _sof_ipc3_bytes_ext_get(scontrol, binary_data, size, true); } static void snd_sof_update_control(struct snd_sof_control *scontrol, -- cgit From dc47ef4f8f6426cd625eb4057e174541e7c23ccd Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Mon, 13 Mar 2023 13:03:42 +0200 Subject: ASoC: SOF: ipc4-control: set_volume_data only applies to VOLSW family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure sof_ipc4_set_volume_data() is only called for the SND_SOC_TPLG_CTL_VOLSW, SND_SOC_TPLG_CTL_VOLSW_SX and SND_SOC_TPLG_CTL_VOLSW_XR_SX info_type. Signed-off-by: Libin Yang Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313110344.16644-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-control.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-control.c b/sound/soc/sof/ipc4-control.c index 67bd2233fd9a..c978325db416 100644 --- a/sound/soc/sof/ipc4-control.c +++ b/sound/soc/sof/ipc4-control.c @@ -186,15 +186,25 @@ static int sof_ipc4_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_s struct snd_sof_control *scontrol; int ret; - list_for_each_entry(scontrol, &sdev->kcontrol_list, list) + list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { if (scontrol->comp_id == swidget->comp_id) { - ret = sof_ipc4_set_volume_data(sdev, swidget, scontrol, false); - if (ret < 0) { - dev_err(sdev->dev, "%s: kcontrol %d set up failed for widget %s\n", - __func__, scontrol->comp_id, swidget->widget->name); - return ret; + switch (scontrol->info_type) { + case SND_SOC_TPLG_CTL_VOLSW: + case SND_SOC_TPLG_CTL_VOLSW_SX: + case SND_SOC_TPLG_CTL_VOLSW_XR_SX: + ret = sof_ipc4_set_volume_data(sdev, swidget, + scontrol, false); + if (ret < 0) { + dev_err(sdev->dev, "kcontrol %d set up failed for widget %s\n", + scontrol->comp_id, swidget->widget->name); + return ret; + } + break; + default: + break; } } + } return 0; } -- cgit From a382082ff74b036944cbc5b6ad29b65f633acd3a Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Mon, 13 Mar 2023 13:03:43 +0200 Subject: ASoC: SOF: ipc4-topology: Add support for TPLG_CTL_BYTES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add byte type support for IPC4. The bytes controls are used to transfer configuration blobs to/from firmware via large_config messages. Signed-off-by: Libin Yang Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313110344.16644-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 67 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index cb75f685e722..d7ce95b9fa0f 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1502,6 +1502,71 @@ static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof return 0; } +static int sof_ipc4_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) +{ + struct sof_ipc4_control_data *control_data; + struct sof_ipc4_msg *msg; + int ret; + + if (scontrol->max_size < (sizeof(*control_data) + sizeof(struct sof_abi_hdr))) { + dev_err(sdev->dev, "insufficient size for a bytes control %s: %zu.\n", + scontrol->name, scontrol->max_size); + return -EINVAL; + } + + if (scontrol->priv_size > scontrol->max_size - sizeof(*control_data)) { + dev_err(sdev->dev, "scontrol %s bytes data size %zu exceeds max %zu.\n", + scontrol->name, scontrol->priv_size, + scontrol->max_size - sizeof(*control_data)); + return -EINVAL; + } + + scontrol->size = sizeof(struct sof_ipc4_control_data) + scontrol->priv_size; + + scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL); + if (!scontrol->ipc_control_data) + return -ENOMEM; + + control_data = scontrol->ipc_control_data; + control_data->index = scontrol->index; + if (scontrol->priv_size > 0) { + memcpy(control_data->data, scontrol->priv, scontrol->priv_size); + kfree(scontrol->priv); + scontrol->priv = NULL; + + if (control_data->data->magic != SOF_IPC4_ABI_MAGIC) { + dev_err(sdev->dev, "Wrong ABI magic (%#x) for control: %s\n", + control_data->data->magic, scontrol->name); + ret = -EINVAL; + goto err; + } + + /* TODO: check the ABI version */ + + if (control_data->data->size + sizeof(struct sof_abi_hdr) != + scontrol->priv_size) { + dev_err(sdev->dev, "Control %s conflict in bytes %zu vs. priv size %zu.\n", + scontrol->name, + control_data->data->size + sizeof(struct sof_abi_hdr), + scontrol->priv_size); + ret = -EINVAL; + goto err; + } + } + + msg = &control_data->msg; + msg->primary = SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_LARGE_CONFIG_SET); + msg->primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); + msg->primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); + + return 0; + +err: + kfree(scontrol->ipc_control_data); + scontrol->ipc_control_data = NULL; + return ret; +} + static int sof_ipc4_control_setup(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) { switch (scontrol->info_type) { @@ -1509,6 +1574,8 @@ static int sof_ipc4_control_setup(struct snd_sof_dev *sdev, struct snd_sof_contr case SND_SOC_TPLG_CTL_VOLSW_SX: case SND_SOC_TPLG_CTL_VOLSW_XR_SX: return sof_ipc4_control_load_volume(sdev, scontrol); + case SND_SOC_TPLG_CTL_BYTES: + return sof_ipc4_control_load_bytes(sdev, scontrol); default: break; } -- cgit From a062c8899fede2ab5660a817e9b602d3fa280a99 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 13 Mar 2023 13:03:44 +0200 Subject: ASoC: SOF: ipc4-control: Add support for bytes control get and put Add support for bytes control by implementing bytes_get/put and bytes_ext_get/put and blobs with either module init instance or large config type. For module init instance type the put will only update the stored configuration blob and it is going to be taken into use next time the module is (re-)initialized. Large config type of blobs are sent to the firmware whenever the DSP is powered up. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Jaska Uimonen Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20230313110344.16644-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-control.c | 248 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 241 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-control.c b/sound/soc/sof/ipc4-control.c index c978325db416..38c2531e2f09 100644 --- a/sound/soc/sof/ipc4-control.c +++ b/sound/soc/sof/ipc4-control.c @@ -180,11 +180,237 @@ static int sof_ipc4_volume_get(struct snd_sof_control *scontrol, return 0; } +static int sof_ipc4_set_get_bytes_data(struct snd_sof_dev *sdev, + struct snd_sof_control *scontrol, + bool set, bool lock) +{ + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; + struct sof_abi_hdr *data = cdata->data; + struct sof_ipc4_msg *msg = &cdata->msg; + int ret = 0; + + /* Send the new data to the firmware only if it is powered up */ + if (set && !pm_runtime_active(sdev->dev)) + return 0; + + msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type); + + msg->data_ptr = data->data; + msg->data_size = data->size; + + ret = sof_ipc4_set_get_kcontrol_data(scontrol, set, lock); + if (ret < 0) + dev_err(sdev->dev, "Failed to %s for %s\n", + set ? "set bytes update" : "get bytes", + scontrol->name); + + msg->data_ptr = NULL; + msg->data_size = 0; + + return ret; +} + +static int sof_ipc4_bytes_put(struct snd_sof_control *scontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct sof_abi_hdr *data = cdata->data; + size_t size; + + if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { + dev_err_ratelimited(scomp->dev, + "data max %zu exceeds ucontrol data array size\n", + scontrol->max_size); + return -EINVAL; + } + + /* scontrol->max_size has been verified to be >= sizeof(struct sof_abi_hdr) */ + if (data->size > scontrol->max_size - sizeof(*data)) { + dev_err_ratelimited(scomp->dev, + "data size too big %u bytes max is %zu\n", + data->size, scontrol->max_size - sizeof(*data)); + return -EINVAL; + } + + size = data->size + sizeof(*data); + + /* copy from kcontrol */ + memcpy(data, ucontrol->value.bytes.data, size); + + sof_ipc4_set_get_bytes_data(sdev, scontrol, true, true); + + return 0; +} + +static int sof_ipc4_bytes_get(struct snd_sof_control *scontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + struct sof_abi_hdr *data = cdata->data; + size_t size; + + if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { + dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n", + scontrol->max_size); + return -EINVAL; + } + + if (data->size > scontrol->max_size - sizeof(*data)) { + dev_err_ratelimited(scomp->dev, + "%u bytes of control data is invalid, max is %zu\n", + data->size, scontrol->max_size - sizeof(*data)); + return -EINVAL; + } + + size = data->size + sizeof(*data); + + /* copy back to kcontrol */ + memcpy(ucontrol->value.bytes.data, data, size); + + return 0; +} + +static int sof_ipc4_bytes_ext_put(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, + unsigned int size) +{ + struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct sof_abi_hdr *data = cdata->data; + struct sof_abi_hdr abi_hdr; + struct snd_ctl_tlv header; + + /* + * The beginning of bytes data contains a header from where + * the length (as bytes) is needed to know the correct copy + * length of data from tlvd->tlv. + */ + if (copy_from_user(&header, tlvd, sizeof(struct snd_ctl_tlv))) + return -EFAULT; + + /* make sure TLV info is consistent */ + if (header.length + sizeof(struct snd_ctl_tlv) > size) { + dev_err_ratelimited(scomp->dev, + "Inconsistent TLV, data %d + header %zu > %d\n", + header.length, sizeof(struct snd_ctl_tlv), size); + return -EINVAL; + } + + /* be->max is coming from topology */ + if (header.length > scontrol->max_size) { + dev_err_ratelimited(scomp->dev, + "Bytes data size %d exceeds max %zu\n", + header.length, scontrol->max_size); + return -EINVAL; + } + + /* Verify the ABI header first */ + if (copy_from_user(&abi_hdr, tlvd->tlv, sizeof(abi_hdr))) + return -EFAULT; + + if (abi_hdr.magic != SOF_IPC4_ABI_MAGIC) { + dev_err_ratelimited(scomp->dev, "Wrong ABI magic 0x%08x\n", + abi_hdr.magic); + return -EINVAL; + } + + if (abi_hdr.size > scontrol->max_size - sizeof(abi_hdr)) { + dev_err_ratelimited(scomp->dev, + "%u bytes of control data is invalid, max is %zu\n", + abi_hdr.size, scontrol->max_size - sizeof(abi_hdr)); + return -EINVAL; + } + + /* Copy the whole binary data which includes the ABI header and the payload */ + if (copy_from_user(data, tlvd->tlv, header.length)) + return -EFAULT; + + sof_ipc4_set_get_bytes_data(sdev, scontrol, true, true); + + return 0; +} + +static int _sof_ipc4_bytes_ext_get(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, + unsigned int size, bool from_dsp) +{ + struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + struct sof_abi_hdr *data = cdata->data; + struct snd_ctl_tlv header; + size_t data_size; + + /* + * Decrement the limit by ext bytes header size to ensure the user space + * buffer is not exceeded. + */ + if (size < sizeof(struct snd_ctl_tlv)) + return -ENOSPC; + + size -= sizeof(struct snd_ctl_tlv); + + /* get all the component data from DSP */ + if (from_dsp) { + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + int ret = sof_ipc4_set_get_bytes_data(sdev, scontrol, false, true); + + if (ret < 0) + return ret; + + /* Set the ABI magic (if the control is not initialized) */ + data->magic = SOF_IPC4_ABI_MAGIC; + } + + if (data->size > scontrol->max_size - sizeof(*data)) { + dev_err_ratelimited(scomp->dev, + "%u bytes of control data is invalid, max is %zu\n", + data->size, scontrol->max_size - sizeof(*data)); + return -EINVAL; + } + + data_size = data->size + sizeof(struct sof_abi_hdr); + + /* make sure we don't exceed size provided by user space for data */ + if (data_size > size) + return -ENOSPC; + + header.numid = scontrol->comp_id; + header.length = data_size; + + if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv))) + return -EFAULT; + + if (copy_to_user(tlvd->tlv, data, data_size)) + return -EFAULT; + + return 0; +} + +static int sof_ipc4_bytes_ext_get(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, + unsigned int size) +{ + return _sof_ipc4_bytes_ext_get(scontrol, binary_data, size, false); +} + +static int sof_ipc4_bytes_ext_volatile_get(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, + unsigned int size) +{ + return _sof_ipc4_bytes_ext_get(scontrol, binary_data, size, true); +} + /* set up all controls for the widget */ static int sof_ipc4_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { struct snd_sof_control *scontrol; - int ret; + int ret = 0; list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { if (scontrol->comp_id == swidget->comp_id) { @@ -194,11 +420,10 @@ static int sof_ipc4_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_s case SND_SOC_TPLG_CTL_VOLSW_XR_SX: ret = sof_ipc4_set_volume_data(sdev, swidget, scontrol, false); - if (ret < 0) { - dev_err(sdev->dev, "kcontrol %d set up failed for widget %s\n", - scontrol->comp_id, swidget->widget->name); - return ret; - } + break; + case SND_SOC_TPLG_CTL_BYTES: + ret = sof_ipc4_set_get_bytes_data(sdev, scontrol, + true, false); break; default: break; @@ -206,7 +431,11 @@ static int sof_ipc4_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_s } } - return 0; + if (ret < 0) + dev_err(sdev->dev, "kcontrol %d set up failed for widget %s\n", + scontrol->comp_id, swidget->widget->name); + + return ret; } static int @@ -234,6 +463,11 @@ sof_ipc4_set_up_volume_table(struct snd_sof_control *scontrol, int tlv[SOF_TLV_I const struct sof_ipc_tplg_control_ops tplg_ipc4_control_ops = { .volume_put = sof_ipc4_volume_put, .volume_get = sof_ipc4_volume_get, + .bytes_put = sof_ipc4_bytes_put, + .bytes_get = sof_ipc4_bytes_get, + .bytes_ext_put = sof_ipc4_bytes_ext_put, + .bytes_ext_get = sof_ipc4_bytes_ext_get, + .bytes_ext_volatile_get = sof_ipc4_bytes_ext_volatile_get, .widget_kcontrol_setup = sof_ipc4_widget_kcontrol_setup, .set_up_volume_table = sof_ipc4_set_up_volume_table, }; -- cgit From bb79f2a608245cd92b3183d77aec6902e51de950 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:47 +0200 Subject: ASoC: SOF: Use input/output pin consistently MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we use input/output and sink/source pins interchangeably. Remove the references to sink/source pins and replace with input/output pins everywhere for consistency and clarity. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 48 +++++++++++++------------- sound/soc/sof/sof-audio.h | 32 ++++++++--------- sound/soc/sof/topology.c | 80 +++++++++++++++++++++---------------------- 3 files changed, 80 insertions(+), 80 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 0bb16ed38e48..a501eb9befa8 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1698,17 +1698,17 @@ static int sof_ipc4_get_queue_id(struct snd_sof_widget *src_widget, u32 num_pins; int i; - if (pin_type == SOF_PIN_TYPE_SOURCE) { + if (pin_type == SOF_PIN_TYPE_OUTPUT) { current_swidget = src_widget; - pin_binding = src_widget->src_pin_binding; - queue_ida = &src_widget->src_queue_ida; - num_pins = src_widget->num_source_pins; + pin_binding = src_widget->output_pin_binding; + queue_ida = &src_widget->output_queue_ida; + num_pins = src_widget->num_output_pins; buddy_name = sink_widget->widget->name; } else { current_swidget = sink_widget; - pin_binding = sink_widget->sink_pin_binding; - queue_ida = &sink_widget->sink_queue_ida; - num_pins = sink_widget->num_sink_pins; + pin_binding = sink_widget->input_pin_binding; + queue_ida = &sink_widget->input_queue_ida; + num_pins = sink_widget->num_input_pins; buddy_name = src_widget->widget->name; } @@ -1716,12 +1716,12 @@ static int sof_ipc4_get_queue_id(struct snd_sof_widget *src_widget, if (num_pins < 1) { dev_err(scomp->dev, "invalid %s num_pins: %d for queue allocation for %s\n", - (pin_type == SOF_PIN_TYPE_SOURCE ? "source" : "sink"), + (pin_type == SOF_PIN_TYPE_OUTPUT ? "output" : "input"), num_pins, current_swidget->widget->name); return -EINVAL; } - /* If there is only one sink/source pin, queue id must be 0 */ + /* If there is only one input/output pin, queue id must be 0 */ if (num_pins == 1) return 0; @@ -1736,7 +1736,7 @@ static int sof_ipc4_get_queue_id(struct snd_sof_widget *src_widget, * mixed use pin binding array and ida for queue ID allocation. */ dev_err(scomp->dev, "no %s queue id found from pin binding array for %s\n", - (pin_type == SOF_PIN_TYPE_SOURCE ? "source" : "sink"), + (pin_type == SOF_PIN_TYPE_OUTPUT ? "output" : "input"), current_swidget->widget->name); return -EINVAL; } @@ -1752,14 +1752,14 @@ static void sof_ipc4_put_queue_id(struct snd_sof_widget *swidget, int queue_id, char **pin_binding; int num_pins; - if (pin_type == SOF_PIN_TYPE_SOURCE) { - pin_binding = swidget->src_pin_binding; - queue_ida = &swidget->src_queue_ida; - num_pins = swidget->num_source_pins; + if (pin_type == SOF_PIN_TYPE_OUTPUT) { + pin_binding = swidget->output_pin_binding; + queue_ida = &swidget->output_queue_ida; + num_pins = swidget->num_output_pins; } else { - pin_binding = swidget->sink_pin_binding; - queue_ida = &swidget->sink_queue_ida; - num_pins = swidget->num_sink_pins; + pin_binding = swidget->input_pin_binding; + queue_ida = &swidget->input_queue_ida; + num_pins = swidget->num_input_pins; } /* Nothing to free if queue ID is not allocated with ida. */ @@ -1829,7 +1829,7 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * int ret; sroute->src_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget, - SOF_PIN_TYPE_SOURCE); + SOF_PIN_TYPE_OUTPUT); if (sroute->src_queue_id < 0) { dev_err(sdev->dev, "failed to get queue ID for source widget: %s\n", src_widget->widget->name); @@ -1837,12 +1837,12 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * } sroute->dst_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget, - SOF_PIN_TYPE_SINK); + SOF_PIN_TYPE_INPUT); if (sroute->dst_queue_id < 0) { dev_err(sdev->dev, "failed to get queue ID for sink widget: %s\n", sink_widget->widget->name); sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, - SOF_PIN_TYPE_SOURCE); + SOF_PIN_TYPE_OUTPUT); return sroute->dst_queue_id; } @@ -1886,8 +1886,8 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * return ret; out: - sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, SOF_PIN_TYPE_SOURCE); - sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id, SOF_PIN_TYPE_SINK); + sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, SOF_PIN_TYPE_OUTPUT); + sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id, SOF_PIN_TYPE_INPUT); return ret; } @@ -1932,8 +1932,8 @@ static int sof_ipc4_route_free(struct snd_sof_dev *sdev, struct snd_sof_route *s src_widget->widget->name, sroute->src_queue_id, sink_widget->widget->name, sroute->dst_queue_id); out: - sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id, SOF_PIN_TYPE_SINK); - sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, SOF_PIN_TYPE_SOURCE); + sof_ipc4_put_queue_id(sink_widget, sroute->dst_queue_id, SOF_PIN_TYPE_INPUT); + sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, SOF_PIN_TYPE_OUTPUT); return ret; } diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 239b82f37976..a1c4d3f34153 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -30,9 +30,9 @@ */ #define SOF_WIDGET_MAX_NUM_PINS 8 -/* The type of a widget pin is either sink or source */ -#define SOF_PIN_TYPE_SINK 0 -#define SOF_PIN_TYPE_SOURCE 1 +/* Widget pin type */ +#define SOF_PIN_TYPE_INPUT 0 +#define SOF_PIN_TYPE_OUTPUT 1 /* max number of FE PCMs before BEs */ #define SOF_BE_PCM_BASE 16 @@ -433,31 +433,31 @@ struct snd_sof_widget { struct snd_sof_tuple *tuples; /* - * The allowed range for num_sink/source_pins is [0, SOF_WIDGET_MAX_NUM_PINS]. - * Widgets may have zero sink or source pins, for example the tone widget has - * zero sink pins. + * The allowed range for num_input/output_pins is [0, SOF_WIDGET_MAX_NUM_PINS]. + * Widgets may have zero input or output pins, for example the tone widget has + * zero input pins. */ - u32 num_sink_pins; - u32 num_source_pins; + u32 num_input_pins; + u32 num_output_pins; /* - * The sink/source pin binding array, it takes the form of + * The input/output pin binding array, it takes the form of * [widget_name_connected_to_pin0, widget_name_connected_to_pin1, ...], * with the index as the queue ID. * * The array is used for special pin binding. Note that even if there - * is only one sink/source pin requires special pin binding, pin binding - * should be defined for all sink/source pins in topology, for pin(s) that + * is only one input/output pin requires special pin binding, pin binding + * should be defined for all input/output pins in topology, for pin(s) that * are not used, give the value "NotConnected". * * If pin binding is not defined in topology, nothing to parse in the kernel, - * sink_pin_binding and src_pin_binding shall be NULL. + * input_pin_binding and output_pin_binding shall be NULL. */ - char **sink_pin_binding; - char **src_pin_binding; + char **input_pin_binding; + char **output_pin_binding; - struct ida src_queue_ida; - struct ida sink_queue_ida; + struct ida output_queue_ida; + struct ida input_queue_ida; void *private; /* core does not touch this */ }; diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 9f3a038fe21a..9f84b4c362c3 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -416,19 +416,19 @@ static const struct sof_topology_token led_tokens[] = { }; static const struct sof_topology_token comp_pin_tokens[] = { - {SOF_TKN_COMP_NUM_SINK_PINS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct snd_sof_widget, num_sink_pins)}, - {SOF_TKN_COMP_NUM_SOURCE_PINS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct snd_sof_widget, num_source_pins)}, + {SOF_TKN_COMP_NUM_INPUT_PINS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct snd_sof_widget, num_input_pins)}, + {SOF_TKN_COMP_NUM_OUTPUT_PINS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct snd_sof_widget, num_output_pins)}, }; -static const struct sof_topology_token comp_sink_pin_binding_tokens[] = { - {SOF_TKN_COMP_SINK_PIN_BINDING_WNAME, SND_SOC_TPLG_TUPLE_TYPE_STRING, +static const struct sof_topology_token comp_input_pin_binding_tokens[] = { + {SOF_TKN_COMP_INPUT_PIN_BINDING_WNAME, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_string, 0}, }; -static const struct sof_topology_token comp_src_pin_binding_tokens[] = { - {SOF_TKN_COMP_SRC_PIN_BINDING_WNAME, SND_SOC_TPLG_TUPLE_TYPE_STRING, +static const struct sof_topology_token comp_output_pin_binding_tokens[] = { + {SOF_TKN_COMP_OUTPUT_PIN_BINDING_WNAME, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_string, 0}, }; @@ -1286,12 +1286,12 @@ static void sof_free_pin_binding(struct snd_sof_widget *swidget, u32 num_pins; int i; - if (pin_type == SOF_PIN_TYPE_SINK) { - pin_binding = swidget->sink_pin_binding; - num_pins = swidget->num_sink_pins; + if (pin_type == SOF_PIN_TYPE_INPUT) { + pin_binding = swidget->input_pin_binding; + num_pins = swidget->num_input_pins; } else { - pin_binding = swidget->src_pin_binding; - num_pins = swidget->num_source_pins; + pin_binding = swidget->output_pin_binding; + num_pins = swidget->num_output_pins; } if (pin_binding) { @@ -1313,14 +1313,14 @@ static int sof_parse_pin_binding(struct snd_sof_widget *swidget, int ret; int i; - if (pin_type == SOF_PIN_TYPE_SINK) { - num_pins = swidget->num_sink_pins; - pin_binding_token = comp_sink_pin_binding_tokens; - token_count = ARRAY_SIZE(comp_sink_pin_binding_tokens); + if (pin_type == SOF_PIN_TYPE_INPUT) { + num_pins = swidget->num_input_pins; + pin_binding_token = comp_input_pin_binding_tokens; + token_count = ARRAY_SIZE(comp_input_pin_binding_tokens); } else { - num_pins = swidget->num_source_pins; - pin_binding_token = comp_src_pin_binding_tokens; - token_count = ARRAY_SIZE(comp_src_pin_binding_tokens); + num_pins = swidget->num_output_pins; + pin_binding_token = comp_output_pin_binding_tokens; + token_count = ARRAY_SIZE(comp_output_pin_binding_tokens); } memset(pin_binding, 0, SOF_WIDGET_MAX_NUM_PINS * sizeof(char *)); @@ -1337,10 +1337,10 @@ static int sof_parse_pin_binding(struct snd_sof_widget *swidget, ret = -ENOMEM; goto err; } - if (pin_type == SOF_PIN_TYPE_SINK) - swidget->sink_pin_binding = pb; + if (pin_type == SOF_PIN_TYPE_INPUT) + swidget->input_pin_binding = pb; else - swidget->src_pin_binding = pb; + swidget->output_pin_binding = pb; } return 0; @@ -1379,8 +1379,8 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, swidget->private = NULL; mutex_init(&swidget->setup_mutex); - ida_init(&swidget->src_queue_ida); - ida_init(&swidget->sink_queue_ida); + ida_init(&swidget->output_queue_ida); + ida_init(&swidget->input_queue_ida); ret = sof_parse_tokens(scomp, swidget, comp_pin_tokens, ARRAY_SIZE(comp_pin_tokens), priv->array, @@ -1391,29 +1391,29 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, goto widget_free; } - if (swidget->num_sink_pins > SOF_WIDGET_MAX_NUM_PINS || - swidget->num_source_pins > SOF_WIDGET_MAX_NUM_PINS) { - dev_err(scomp->dev, "invalid pins for %s: [sink: %d, src: %d]\n", - swidget->widget->name, swidget->num_sink_pins, swidget->num_source_pins); + if (swidget->num_input_pins > SOF_WIDGET_MAX_NUM_PINS || + swidget->num_output_pins > SOF_WIDGET_MAX_NUM_PINS) { + dev_err(scomp->dev, "invalid pins for %s: [input: %d, output: %d]\n", + swidget->widget->name, swidget->num_input_pins, swidget->num_output_pins); ret = -EINVAL; goto widget_free; } - if (swidget->num_sink_pins > 1) { - ret = sof_parse_pin_binding(swidget, priv, SOF_PIN_TYPE_SINK); + if (swidget->num_input_pins > 1) { + ret = sof_parse_pin_binding(swidget, priv, SOF_PIN_TYPE_INPUT); /* on parsing error, pin binding is not allocated, nothing to free. */ if (ret < 0) { - dev_err(scomp->dev, "failed to parse sink pin binding for %s\n", + dev_err(scomp->dev, "failed to parse input pin binding for %s\n", w->name); goto widget_free; } } - if (swidget->num_source_pins > 1) { - ret = sof_parse_pin_binding(swidget, priv, SOF_PIN_TYPE_SOURCE); + if (swidget->num_output_pins > 1) { + ret = sof_parse_pin_binding(swidget, priv, SOF_PIN_TYPE_OUTPUT); /* on parsing error, pin binding is not allocated, nothing to free. */ if (ret < 0) { - dev_err(scomp->dev, "failed to parse source pin binding for %s\n", + dev_err(scomp->dev, "failed to parse output pin binding for %s\n", w->name); goto widget_free; } @@ -1422,7 +1422,7 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, dev_dbg(scomp->dev, "tplg: widget %d (%s) is ready [type: %d, pipe: %d, pins: %d / %d, stream: %s]\n", swidget->comp_id, w->name, swidget->id, index, - swidget->num_sink_pins, swidget->num_source_pins, + swidget->num_input_pins, swidget->num_output_pins, strnlen(w->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0 ? w->sname : "none"); widget_ops = tplg_ops ? tplg_ops->widget : NULL; @@ -1643,11 +1643,11 @@ out: if (widget_ops && widget_ops[swidget->id].ipc_free) widget_ops[swidget->id].ipc_free(swidget); - ida_destroy(&swidget->src_queue_ida); - ida_destroy(&swidget->sink_queue_ida); + ida_destroy(&swidget->output_queue_ida); + ida_destroy(&swidget->input_queue_ida); - sof_free_pin_binding(swidget, SOF_PIN_TYPE_SINK); - sof_free_pin_binding(swidget, SOF_PIN_TYPE_SOURCE); + sof_free_pin_binding(swidget, SOF_PIN_TYPE_INPUT); + sof_free_pin_binding(swidget, SOF_PIN_TYPE_OUTPUT); kfree(swidget->tuples); -- cgit From e63a73f94fef0cf592aa7bb55f907007d747af4f Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:48 +0200 Subject: ASoC: SOF: ipc4-topology: Add a new field in struct sof_ipc4_available_audio_format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new field, input_audio_fmts, in struct sof_ipc4_available_audio_format and parse all the available input audio formats into this new field and not into the base_config field. This is preparation to remove the base_config array from the struct sof_ipc4_available_audio_format. This simplifies the sof_ipc4_init_audio_fmt() function as the reference audio format for matching with input params has the same size. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-pcm.c | 2 +- sound/soc/sof/ipc4-topology.c | 119 ++++++++++++++++++++++-------------------- sound/soc/sof/ipc4-topology.h | 2 + 3 files changed, 65 insertions(+), 58 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 68258767aace..a679c08d9bb1 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -389,7 +389,7 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, snd_mask_none(fmt); snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); - rate->min = ipc4_copier->available_fmt.base_config->audio_fmt.sampling_frequency; + rate->min = ipc4_copier->available_fmt.input_audio_fmts->sampling_frequency; rate->max = rate->min; switch (ipc4_copier->dai_type) { diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index a501eb9befa8..d56e0f12b5d0 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -180,7 +180,7 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, bool has_out_format) { struct sof_ipc4_base_module_cfg *base_config; - struct sof_ipc4_audio_format *out_format; + struct sof_ipc4_audio_format *out_format, *in_format; int audio_fmt_num = 0; int ret, i; @@ -206,7 +206,7 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, swidget->num_tuples, sizeof(*base_config), 1); if (ret) { dev_err(scomp->dev, "parse comp tokens failed %d\n", ret); - goto err_in; + goto err; } } @@ -217,7 +217,7 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, available_fmt->audio_fmt_num); if (ret) { dev_err(scomp->dev, "parse buffer size tokens failed %d\n", ret); - goto err_in; + goto err; } for (i = 0; i < available_fmt->audio_fmt_num; i++) @@ -225,9 +225,17 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, base_config[i].ibs, base_config[i].obs, base_config[i].cpc, base_config[i].is_pages); - ret = sof_update_ipc_object(scomp, &base_config->audio_fmt, + in_format = kcalloc(available_fmt->audio_fmt_num, + sizeof(struct sof_ipc4_audio_format), GFP_KERNEL); + if (!in_format) { + kfree(base_config); + ret = -ENOMEM; + goto err; + } + + ret = sof_update_ipc_object(scomp, available_fmt->input_audio_fmts, SOF_IN_AUDIO_FORMAT_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(*base_config), + swidget->num_tuples, sizeof(struct sof_ipc4_audio_format), available_fmt->audio_fmt_num); if (ret) { dev_err(scomp->dev, "parse base_config audio_fmt tokens failed %d\n", ret); @@ -235,12 +243,10 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, } dev_dbg(scomp->dev, "Get input audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(scomp->dev, &base_config->audio_fmt, - sizeof(*base_config), + sof_ipc4_dbg_audio_format(scomp->dev, available_fmt->input_audio_fmts, + sizeof(struct sof_ipc4_audio_format), available_fmt->audio_fmt_num); - available_fmt->base_config = base_config; - if (!has_out_format) return 0; @@ -260,18 +266,22 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, goto err_out; } - available_fmt->out_audio_fmt = out_format; dev_dbg(scomp->dev, "Get output audio formats for %s\n", swidget->widget->name); sof_ipc4_dbg_audio_format(scomp->dev, out_format, sizeof(*out_format), available_fmt->audio_fmt_num); + available_fmt->base_config = base_config; + available_fmt->out_audio_fmt = out_format; + available_fmt->input_audio_fmts = in_format; + return 0; err_out: kfree(out_format); err_in: + kfree(in_format); +err: kfree(base_config); - return ret; } @@ -283,6 +293,8 @@ static void sof_ipc4_free_audio_fmt(struct sof_ipc4_available_audio_format *avai available_fmt->base_config = NULL; kfree(available_fmt->out_audio_fmt); available_fmt->out_audio_fmt = NULL; + kfree(available_fmt->input_audio_fmts); + available_fmt->input_audio_fmts = NULL; } static void sof_ipc4_widget_free_comp_pipeline(struct snd_sof_widget *swidget) @@ -904,17 +916,16 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, struct sof_ipc4_base_module_cfg *base_config, struct sof_ipc4_audio_format *out_format, struct snd_pcm_hw_params *params, - struct sof_ipc4_available_audio_format *available_fmt, - size_t object_offset) + struct sof_ipc4_available_audio_format *available_fmt) { - void *ptr = available_fmt->ref_audio_fmt; + struct sof_ipc4_audio_format *fmt = available_fmt->ref_audio_fmt; u32 valid_bits; u32 channels; u32 rate; int sample_valid_bits; int i; - if (!ptr) { + if (!fmt) { dev_err(sdev->dev, "no reference formats for %s\n", swidget->widget->name); return -EINVAL; } @@ -943,25 +954,14 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, * Search supported audio formats to match rate, channels ,and * sample_valid_bytes from runtime params */ - for (i = 0; i < available_fmt->audio_fmt_num; i++, ptr = (u8 *)ptr + object_offset) { - struct sof_ipc4_audio_format *fmt = ptr; - + for (i = 0; i < available_fmt->audio_fmt_num; i++, fmt++) { rate = fmt->sampling_frequency; channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); if (params_rate(params) == rate && params_channels(params) == channels && sample_valid_bits == valid_bits) { - dev_dbg(sdev->dev, "matching audio format index for %uHz, %ubit, %u channels: %d\n", + dev_dbg(sdev->dev, "matched audio format index for %uHz, %ubit, %u channels: %d\n", rate, valid_bits, channels, i); - - /* copy ibs/obs and input format */ - memcpy(base_config, &available_fmt->base_config[i], - sizeof(struct sof_ipc4_base_module_cfg)); - - /* copy output format */ - if (out_format) - memcpy(out_format, &available_fmt->out_audio_fmt[i], - sizeof(struct sof_ipc4_audio_format)); break; } } @@ -972,10 +972,25 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, return -EINVAL; } + /* copy input format */ + memcpy(&base_config->audio_fmt, &available_fmt->input_audio_fmts[i], sizeof(*fmt)); + + /* set base_cfg ibs/obs */ + base_config->ibs = available_fmt->base_config[i].ibs; + base_config->obs = available_fmt->base_config[i].obs; + dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name); sof_ipc4_dbg_audio_format(sdev->dev, &base_config->audio_fmt, sizeof(*base_config), 1); if (out_format) { + /* + * Current topology defines pin 0 input and output formats only in pairs. + * This assumes that the pin 0 formats are defined before all other pins. + * So pick the output audio format with the same index as the chosen + * input format. This logic will need to be updated when the format definitions + * in topology change. + */ + memcpy(out_format, &available_fmt->out_audio_fmt[i], sizeof(*fmt)); dev_dbg(sdev->dev, "Init output audio formats for %s\n", swidget->widget->name); sof_ipc4_dbg_audio_format(sdev->dev, out_format, sizeof(*out_format), 1); @@ -1147,7 +1162,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, struct snd_sof_dai *dai; struct snd_mask *fmt; int out_sample_valid_bits; - size_t ref_audio_fmt_size; void **ipc_config_data; int *ipc_config_size; u32 **data; @@ -1171,17 +1185,14 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, available_fmt = &ipc4_copier->available_fmt; /* - * base_config->audio_fmt and out_audio_fmt represent the input and output audio - * formats. Use the input format as the reference to match pcm params for playback - * and the output format as reference for capture. + * Use the input_audio_fmts to match pcm params for playback and the out_audio_fmt + * for capture. */ - if (dir == SNDRV_PCM_STREAM_PLAYBACK) { - available_fmt->ref_audio_fmt = &available_fmt->base_config->audio_fmt; - ref_audio_fmt_size = sizeof(struct sof_ipc4_base_module_cfg); - } else { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; + else available_fmt->ref_audio_fmt = available_fmt->out_audio_fmt; - ref_audio_fmt_size = sizeof(struct sof_ipc4_audio_format); - } + copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(platform_params->stream_tag - 1); @@ -1201,7 +1212,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, available_fmt = &ipc4_copier->available_fmt; if (dir == SNDRV_PCM_STREAM_CAPTURE) { available_fmt->ref_audio_fmt = available_fmt->out_audio_fmt; - ref_audio_fmt_size = sizeof(struct sof_ipc4_audio_format); /* * modify the input params for the dai copier as it only supports @@ -1211,8 +1221,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, snd_mask_none(fmt); snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); } else { - available_fmt->ref_audio_fmt = &available_fmt->base_config->audio_fmt; - ref_audio_fmt_size = sizeof(struct sof_ipc4_base_module_cfg); + available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; } ref_params = pipeline_params; @@ -1232,12 +1241,8 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; - /* - * base_config->audio_fmt represent the input audio formats. Use - * the input format as the reference to match pcm params - */ - available_fmt->ref_audio_fmt = &available_fmt->base_config->audio_fmt; - ref_audio_fmt_size = sizeof(struct sof_ipc4_base_module_cfg); + /* Use the input formats as the reference to match pcm params */ + available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; ref_params = pipeline_params; break; @@ -1251,7 +1256,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, /* set input and output audio formats */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &copier_data->base_config, &copier_data->out_format, ref_params, - available_fmt, ref_audio_fmt_size); + available_fmt); if (ret < 0) return ret; @@ -1400,14 +1405,14 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_gain *gain = swidget->private; + struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt; int ret; - gain->available_fmt.ref_audio_fmt = &gain->available_fmt.base_config->audio_fmt; + available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; /* output format is not required to be sent to the FW for gain */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &gain->base_config, - NULL, pipeline_params, &gain->available_fmt, - sizeof(gain->base_config)); + NULL, pipeline_params, available_fmt); if (ret < 0) return ret; @@ -1425,15 +1430,15 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_mixer *mixer = swidget->private; + struct sof_ipc4_available_audio_format *available_fmt = &mixer->available_fmt; int ret; /* only 32bit is supported by mixer */ - mixer->available_fmt.ref_audio_fmt = &mixer->available_fmt.base_config->audio_fmt; + available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; /* output format is not required to be sent to the FW for mixer */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &mixer->base_config, - NULL, pipeline_params, &mixer->available_fmt, - sizeof(mixer->base_config)); + NULL, pipeline_params, available_fmt); if (ret < 0) return ret; @@ -1451,15 +1456,15 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_src *src = swidget->private; + struct sof_ipc4_available_audio_format *available_fmt = &src->available_fmt; struct snd_interval *rate; int ret; - src->available_fmt.ref_audio_fmt = &src->available_fmt.base_config->audio_fmt; + available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; /* output format is not required to be sent to the FW for SRC */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config, - NULL, pipeline_params, &src->available_fmt, - sizeof(src->base_config)); + NULL, pipeline_params, available_fmt); if (ret < 0) return ret; diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 22900b572766..addc5b55cc10 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -146,6 +146,7 @@ struct ipc4_pipeline_set_state_data { * struct sof_ipc4_available_audio_format - Available audio formats * @base_config: Available base config * @out_audio_fmt: Available output audio format + * @input_audio_fmts: Available input audio formats * @ref_audio_fmt: Reference audio format to match runtime audio format * @dma_buffer_size: Available Gateway DMA buffer size (in bytes) * @audio_fmt_num: Number of available audio formats @@ -153,6 +154,7 @@ struct ipc4_pipeline_set_state_data { struct sof_ipc4_available_audio_format { struct sof_ipc4_base_module_cfg *base_config; struct sof_ipc4_audio_format *out_audio_fmt; + struct sof_ipc4_audio_format *input_audio_fmts; struct sof_ipc4_audio_format *ref_audio_fmt; u32 *dma_buffer_size; int audio_fmt_num; -- cgit From 594c1bb9ff7365b90cb4d325deb8c38ddda90557 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:49 +0200 Subject: ASoC: SOF: ipc4-topology: Do not parse the DMA_BUFFER_SIZE token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not parse the SOF_TKN_CAVS_AUDIO_FORMAT_DMA_BUFFER_SIZE token as the dma_buffer_size can be derived from the input/output buffer size and the type of widget during copier prepare. For the deep buffer case, introduce a new token that will be used to get the deep buffer DMA size for the host copier from topology. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 112 ++++++++++++++++++------------------------ sound/soc/sof/ipc4-topology.h | 5 +- sound/soc/sof/sof-audio.h | 2 +- sound/soc/sof/topology.c | 1 - 4 files changed, 51 insertions(+), 69 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index d56e0f12b5d0..50cd4fe3141c 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -78,8 +78,8 @@ static const struct sof_topology_token ipc4_out_audio_format_tokens[] = { offsetof(struct sof_ipc4_audio_format, fmt_cfg)}, }; -static const struct sof_topology_token ipc4_copier_gateway_cfg_tokens[] = { - {SOF_TKN_CAVS_AUDIO_FORMAT_DMA_BUFFER_SIZE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 0}, +static const struct sof_topology_token ipc4_copier_deep_buffer_tokens[] = { + {SOF_TKN_INTEL_COPIER_DEEP_BUFFER_DMA_MS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 0}, }; static const struct sof_topology_token ipc4_copier_tokens[] = { @@ -138,8 +138,8 @@ static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = { [SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS] = {"IPC4 Audio format buffer size tokens", ipc4_audio_format_buffer_size_tokens, ARRAY_SIZE(ipc4_audio_format_buffer_size_tokens)}, - [SOF_COPIER_GATEWAY_CFG_TOKENS] = {"IPC4 Copier gateway config tokens", - ipc4_copier_gateway_cfg_tokens, ARRAY_SIZE(ipc4_copier_gateway_cfg_tokens)}, + [SOF_COPIER_DEEP_BUFFER_TOKENS] = {"IPC4 Copier deep buffer tokens", + ipc4_copier_deep_buffer_tokens, ARRAY_SIZE(ipc4_copier_deep_buffer_tokens)}, [SOF_COPIER_TOKENS] = {"IPC4 Copier tokens", ipc4_copier_tokens, ARRAY_SIZE(ipc4_copier_tokens)}, [SOF_AUDIO_FMT_NUM_TOKENS] = {"IPC4 Audio format number tokens", @@ -348,7 +348,7 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) struct snd_soc_component *scomp = swidget->scomp; struct sof_ipc4_copier *ipc4_copier; int node_type = 0; - int ret, i; + int ret; ipc4_copier = kzalloc(sizeof(*ipc4_copier), GFP_KERNEL); if (!ipc4_copier) @@ -363,13 +363,6 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) if (ret) goto free_copier; - available_fmt->dma_buffer_size = kcalloc(available_fmt->audio_fmt_num, sizeof(u32), - GFP_KERNEL); - if (!available_fmt->dma_buffer_size) { - ret = -ENOMEM; - goto free_available_fmt; - } - /* * This callback is used by host copier and module-to-module copier, * and only host copier needs to set gtw_cfg. @@ -377,21 +370,6 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) if (!WIDGET_IS_AIF(swidget->id)) goto skip_gtw_cfg; - ret = sof_update_ipc_object(scomp, available_fmt->dma_buffer_size, - SOF_COPIER_GATEWAY_CFG_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(u32), - available_fmt->audio_fmt_num); - if (ret) { - dev_err(scomp->dev, "Failed to parse dma buffer size in audio format for %s\n", - swidget->widget->name); - goto err; - } - - dev_dbg(scomp->dev, "dma buffer size:\n"); - for (i = 0; i < available_fmt->audio_fmt_num; i++) - dev_dbg(scomp->dev, "%d: %u\n", i, - available_fmt->dma_buffer_size[i]); - ret = sof_update_ipc_object(scomp, &node_type, SOF_COPIER_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(node_type), 1); @@ -399,7 +377,7 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) if (ret) { dev_err(scomp->dev, "parse host copier node type token failed %d\n", ret); - goto err; + goto free_available_fmt; } dev_dbg(scomp->dev, "host copier '%s' node_type %u\n", swidget->widget->name, node_type); @@ -407,7 +385,7 @@ skip_gtw_cfg: ipc4_copier->gtw_attr = kzalloc(sizeof(*ipc4_copier->gtw_attr), GFP_KERNEL); if (!ipc4_copier->gtw_attr) { ret = -ENOMEM; - goto err; + goto free_available_fmt; } ipc4_copier->copier_config = (uint32_t *)ipc4_copier->gtw_attr; @@ -438,8 +416,6 @@ skip_gtw_cfg: free_gtw_attr: kfree(ipc4_copier->gtw_attr); -err: - kfree(available_fmt->dma_buffer_size); free_available_fmt: sof_ipc4_free_audio_fmt(available_fmt); free_copier: @@ -457,7 +433,6 @@ static void sof_ipc4_widget_free_comp_pcm(struct snd_sof_widget *swidget) return; available_fmt = &ipc4_copier->available_fmt; - kfree(available_fmt->dma_buffer_size); kfree(available_fmt->base_config); kfree(available_fmt->out_audio_fmt); kfree(ipc4_copier->gtw_attr); @@ -472,7 +447,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) struct snd_sof_dai *dai = swidget->private; struct sof_ipc4_copier *ipc4_copier; int node_type = 0; - int ret, i; + int ret; ipc4_copier = kzalloc(sizeof(*ipc4_copier), GFP_KERNEL); if (!ipc4_copier) @@ -486,33 +461,12 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) if (ret) goto free_copier; - available_fmt->dma_buffer_size = kcalloc(available_fmt->audio_fmt_num, sizeof(u32), - GFP_KERNEL); - if (!available_fmt->dma_buffer_size) { - ret = -ENOMEM; - goto free_available_fmt; - } - - ret = sof_update_ipc_object(scomp, available_fmt->dma_buffer_size, - SOF_COPIER_GATEWAY_CFG_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(u32), - available_fmt->audio_fmt_num); - if (ret) { - dev_err(scomp->dev, "Failed to parse dma buffer size in audio format for %s\n", - swidget->widget->name); - goto err; - } - - for (i = 0; i < available_fmt->audio_fmt_num; i++) - dev_dbg(scomp->dev, "%d: dma buffer size: %u\n", i, - available_fmt->dma_buffer_size[i]); - ret = sof_update_ipc_object(scomp, &node_type, SOF_COPIER_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(node_type), 1); if (ret) { dev_err(scomp->dev, "parse dai node type failed %d\n", ret); - goto err; + goto free_available_fmt; } ret = sof_update_ipc_object(scomp, ipc4_copier, @@ -520,7 +474,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) swidget->num_tuples, sizeof(u32), 1); if (ret) { dev_err(scomp->dev, "parse dai copier node token failed %d\n", ret); - goto err; + goto free_available_fmt; } dev_dbg(scomp->dev, "dai %s node_type %u dai_type %u dai_index %d\n", swidget->widget->name, @@ -554,7 +508,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) blob = kzalloc(sizeof(*blob), GFP_KERNEL); if (!blob) { ret = -ENOMEM; - goto err; + goto free_available_fmt; } list_for_each_entry(w, &sdev->widget_list, list) { @@ -583,7 +537,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) ipc4_copier->gtw_attr = kzalloc(sizeof(*ipc4_copier->gtw_attr), GFP_KERNEL); if (!ipc4_copier->gtw_attr) { ret = -ENOMEM; - goto err; + goto free_available_fmt; } ipc4_copier->copier_config = (uint32_t *)ipc4_copier->gtw_attr; @@ -604,8 +558,6 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) free_copier_config: kfree(ipc4_copier->copier_config); -err: - kfree(available_fmt->dma_buffer_size); free_available_fmt: sof_ipc4_free_audio_fmt(available_fmt); free_copier: @@ -633,7 +585,6 @@ static void sof_ipc4_widget_free_comp_dai(struct snd_sof_widget *swidget) ipc4_copier = dai->private; available_fmt = &ipc4_copier->available_fmt; - kfree(available_fmt->dma_buffer_size); kfree(available_fmt->base_config); kfree(available_fmt->out_audio_fmt); if (ipc4_copier->dai_type != SOF_DAI_INTEL_SSP && @@ -1166,6 +1117,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, int *ipc_config_size; u32 **data; int ipc_size, ret; + u32 deep_buffer_dma_ms = 0; dev_dbg(sdev->dev, "copier %s, type %d", swidget->widget->name, swidget->id); @@ -1177,6 +1129,16 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, struct snd_sof_widget *pipe_widget; struct sof_ipc4_pipeline *pipeline; + /* parse the deep buffer dma size */ + ret = sof_update_ipc_object(scomp, &deep_buffer_dma_ms, + SOF_COPIER_DEEP_BUFFER_TOKENS, swidget->tuples, + swidget->num_tuples, sizeof(u32), 1); + if (ret) { + dev_err(scomp->dev, "Failed to parse deep buffer dma size for %s\n", + swidget->widget->name); + return ret; + } + pipe_widget = swidget->spipe->pipe_widget; pipeline = pipe_widget->private; ipc4_copier = (struct sof_ipc4_copier *)swidget->private; @@ -1367,8 +1329,29 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, return -EINVAL; } - /* set the gateway dma_buffer_size using the matched ID returned above */ - copier_data->gtw_cfg.dma_buffer_size = available_fmt->dma_buffer_size[ret]; + /* + * Set the gateway dma_buffer_size to 2ms buffer size to meet the FW expectation. In the + * deep buffer case, set the dma_buffer_size depending on the deep_buffer_dma_ms set + * in topology. + */ + switch (swidget->id) { + case snd_soc_dapm_dai_in: + copier_data->gtw_cfg.dma_buffer_size = + SOF_IPC4_MIN_DMA_BUFFER_SIZE * copier_data->base_config.ibs; + break; + case snd_soc_dapm_aif_in: + copier_data->gtw_cfg.dma_buffer_size = + max((u32)SOF_IPC4_MIN_DMA_BUFFER_SIZE, deep_buffer_dma_ms) * + copier_data->base_config.ibs; + break; + case snd_soc_dapm_dai_out: + case snd_soc_dapm_aif_out: + copier_data->gtw_cfg.dma_buffer_size = + SOF_IPC4_MIN_DMA_BUFFER_SIZE * copier_data->base_config.obs; + break; + default: + break; + } data = &ipc4_copier->copier_config; ipc_config_size = &ipc4_copier->ipc_config_size; @@ -2170,7 +2153,7 @@ static enum sof_tokens common_copier_token_list[] = { SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, SOF_OUT_AUDIO_FORMAT_TOKENS, - SOF_COPIER_GATEWAY_CFG_TOKENS, + SOF_COPIER_DEEP_BUFFER_TOKENS, SOF_COPIER_TOKENS, SOF_COMP_EXT_TOKENS, }; @@ -2186,7 +2169,6 @@ static enum sof_tokens dai_token_list[] = { SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, SOF_OUT_AUDIO_FORMAT_TOKENS, - SOF_COPIER_GATEWAY_CFG_TOKENS, SOF_COPIER_TOKENS, SOF_DAI_TOKENS, SOF_COMP_EXT_TOKENS, diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index addc5b55cc10..696d6c39a21b 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -55,6 +55,9 @@ #define SOF_IPC4_INVALID_NODE_ID 0xffffffff +/* FW requires minimum 2ms DMA buffer size */ +#define SOF_IPC4_MIN_DMA_BUFFER_SIZE 2 + /* * The base of multi-gateways. Multi-gateways addressing starts from * ALH_MULTI_GTW_BASE and there are ALH_MULTI_GTW_COUNT multi-sources @@ -148,7 +151,6 @@ struct ipc4_pipeline_set_state_data { * @out_audio_fmt: Available output audio format * @input_audio_fmts: Available input audio formats * @ref_audio_fmt: Reference audio format to match runtime audio format - * @dma_buffer_size: Available Gateway DMA buffer size (in bytes) * @audio_fmt_num: Number of available audio formats */ struct sof_ipc4_available_audio_format { @@ -156,7 +158,6 @@ struct sof_ipc4_available_audio_format { struct sof_ipc4_audio_format *out_audio_fmt; struct sof_ipc4_audio_format *input_audio_fmts; struct sof_ipc4_audio_format *ref_audio_fmt; - u32 *dma_buffer_size; int audio_fmt_num; }; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index a1c4d3f34153..4504f9efdc50 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -257,7 +257,7 @@ enum sof_tokens { SOF_IN_AUDIO_FORMAT_TOKENS, SOF_OUT_AUDIO_FORMAT_TOKENS, SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, - SOF_COPIER_GATEWAY_CFG_TOKENS, + SOF_COPIER_DEEP_BUFFER_TOKENS, SOF_COPIER_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, SOF_COPIER_FORMAT_TOKENS, diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 9f84b4c362c3..2d76ab13b3d1 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1232,7 +1232,6 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s continue; case SOF_IN_AUDIO_FORMAT_TOKENS: case SOF_OUT_AUDIO_FORMAT_TOKENS: - case SOF_COPIER_GATEWAY_CFG_TOKENS: case SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS: num_sets = sof_get_token_value(SOF_TKN_COMP_NUM_AUDIO_FORMATS, swidget->tuples, swidget->num_tuples); -- cgit From 171d5ccedbb6277a8f9a3eae36e4f465ddc3187f Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:50 +0200 Subject: ASoC: SOF: ipc4-topology: Parse the SOF_COMP_TOKENS only once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to parse the cpc and is_pages values multiple times. It is enough to parse the 2 tokens directly into the base_config field in each module's init_instance IPC payload. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 50cd4fe3141c..b6933fa1a36d 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -170,6 +170,7 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, * @scomp: pointer to pointer to SOC component * @swidget: pointer to struct snd_sof_widget containing tuples * @available_fmt: pointer to struct sof_ipc4_available_audio_format being filling in + * @module_base_cfg: Pointer to the base_config in the module init IPC payload * @has_out_format: true if available_fmt contains output format * * Return: 0 if successful @@ -177,6 +178,7 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt, + struct sof_ipc4_base_module_cfg *module_base_cfg, bool has_out_format) { struct sof_ipc4_base_module_cfg *base_config; @@ -199,17 +201,18 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, if (!base_config) return -ENOMEM; - /* set cpc and is_pages for all base_cfg */ - for (i = 0; i < available_fmt->audio_fmt_num; i++) { - ret = sof_update_ipc_object(scomp, &base_config[i], - SOF_COMP_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(*base_config), 1); - if (ret) { - dev_err(scomp->dev, "parse comp tokens failed %d\n", ret); - goto err; - } + /* set cpc and is_pages in the module's base_config */ + ret = sof_update_ipc_object(scomp, module_base_cfg, SOF_COMP_TOKENS, swidget->tuples, + swidget->num_tuples, sizeof(*module_base_cfg), 1); + if (ret) { + dev_err(scomp->dev, "parse comp tokens for %s failed, error: %d\n", + swidget->widget->name, ret); + goto err; } + dev_dbg(scomp->dev, "widget %s cpc: %d is_pages: %d\n", + swidget->widget->name, module_base_cfg->cpc, module_base_cfg->is_pages); + /* copy the ibs/obs for each base_cfg */ ret = sof_update_ipc_object(scomp, base_config, SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, swidget->tuples, @@ -221,9 +224,8 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, } for (i = 0; i < available_fmt->audio_fmt_num; i++) - dev_dbg(scomp->dev, "%d: ibs: %d obs: %d cpc: %d is_pages: %d\n", i, - base_config[i].ibs, base_config[i].obs, - base_config[i].cpc, base_config[i].is_pages); + dev_dbg(scomp->dev, "%d: ibs: %d obs: %d\n", i, + base_config[i].ibs, base_config[i].obs); in_format = kcalloc(available_fmt->audio_fmt_num, sizeof(struct sof_ipc4_audio_format), GFP_KERNEL); @@ -359,7 +361,8 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name); - ret = sof_ipc4_get_audio_fmt(scomp, swidget, available_fmt, true); + ret = sof_ipc4_get_audio_fmt(scomp, swidget, available_fmt, + &ipc4_copier->data.base_config, true); if (ret) goto free_copier; @@ -457,7 +460,8 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name); - ret = sof_ipc4_get_audio_fmt(scomp, swidget, available_fmt, true); + ret = sof_ipc4_get_audio_fmt(scomp, swidget, available_fmt, + &ipc4_copier->data.base_config, true); if (ret) goto free_copier; @@ -665,7 +669,8 @@ static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget) gain->data.init_val = SOF_IPC4_VOL_ZERO_DB; /* The out_audio_fmt in topology is ignored as it is not required to be sent to the FW */ - ret = sof_ipc4_get_audio_fmt(scomp, swidget, &gain->available_fmt, false); + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &gain->available_fmt, &gain->base_config, + false); if (ret) goto err; @@ -731,7 +736,8 @@ static int sof_ipc4_widget_setup_comp_mixer(struct snd_sof_widget *swidget) swidget->private = mixer; /* The out_audio_fmt in topology is ignored as it is not required to be sent to the FW */ - ret = sof_ipc4_get_audio_fmt(scomp, swidget, &mixer->available_fmt, false); + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &mixer->available_fmt, + &mixer->base_config, false); if (ret) goto err; @@ -762,7 +768,8 @@ static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget) swidget->private = src; /* The out_audio_fmt in topology is ignored as it is not required by SRC */ - ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, false); + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, &src->base_config, + false); if (ret) goto err; -- cgit From 8abc9ab956b5756693710e1e09557e0189f01bef Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:51 +0200 Subject: ASoC: SOF: ipc4-topology: Always parse the output formats in topology MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parse the output formats available in topology always. Whether the output format is sent in the init instance payload or not is decided when sof_ipc4_init_audio_fmt() is invoked. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index b6933fa1a36d..0e1e4fc9224c 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -171,15 +171,13 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, * @swidget: pointer to struct snd_sof_widget containing tuples * @available_fmt: pointer to struct sof_ipc4_available_audio_format being filling in * @module_base_cfg: Pointer to the base_config in the module init IPC payload - * @has_out_format: true if available_fmt contains output format * * Return: 0 if successful */ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt, - struct sof_ipc4_base_module_cfg *module_base_cfg, - bool has_out_format) + struct sof_ipc4_base_module_cfg *module_base_cfg) { struct sof_ipc4_base_module_cfg *base_config; struct sof_ipc4_audio_format *out_format, *in_format; @@ -249,9 +247,6 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, sizeof(struct sof_ipc4_audio_format), available_fmt->audio_fmt_num); - if (!has_out_format) - return 0; - out_format = kcalloc(available_fmt->audio_fmt_num, sizeof(*out_format), GFP_KERNEL); if (!out_format) { ret = -ENOMEM; @@ -362,7 +357,7 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name); ret = sof_ipc4_get_audio_fmt(scomp, swidget, available_fmt, - &ipc4_copier->data.base_config, true); + &ipc4_copier->data.base_config); if (ret) goto free_copier; @@ -461,7 +456,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name); ret = sof_ipc4_get_audio_fmt(scomp, swidget, available_fmt, - &ipc4_copier->data.base_config, true); + &ipc4_copier->data.base_config); if (ret) goto free_copier; @@ -668,9 +663,7 @@ static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget) gain->data.channels = SOF_IPC4_GAIN_ALL_CHANNELS_MASK; gain->data.init_val = SOF_IPC4_VOL_ZERO_DB; - /* The out_audio_fmt in topology is ignored as it is not required to be sent to the FW */ - ret = sof_ipc4_get_audio_fmt(scomp, swidget, &gain->available_fmt, &gain->base_config, - false); + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &gain->available_fmt, &gain->base_config); if (ret) goto err; @@ -735,9 +728,8 @@ static int sof_ipc4_widget_setup_comp_mixer(struct snd_sof_widget *swidget) swidget->private = mixer; - /* The out_audio_fmt in topology is ignored as it is not required to be sent to the FW */ ret = sof_ipc4_get_audio_fmt(scomp, swidget, &mixer->available_fmt, - &mixer->base_config, false); + &mixer->base_config); if (ret) goto err; @@ -767,9 +759,7 @@ static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget) swidget->private = src; - /* The out_audio_fmt in topology is ignored as it is not required by SRC */ - ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, &src->base_config, - false); + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, &src->base_config); if (ret) goto err; -- cgit From 7ab6b1e8302cf7a9bc8808c43b3e751e4148a351 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:52 +0200 Subject: ASoC: SOF: ipc4-topology: Modify the type of available input/output formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a new struct sof_ipc4_pin_format which contains the pin index and the buffer size. Replace the type of available input/output audio formats in struct sof_ipc4_available_audio_format with this new struct type and rename them to input_pin_fmts and output_pin_fmts. Also, add a new token, SOF_TKN_CAVS_AUDIO_FORMAT_PIN_INDEX that will be used to parse the pin index for the audio format from topology. Currently we only set the audio format for Pin 0 in topology, so the default value will be 0 for all audio formats. Finally, parse the pin_index and the input/output buffer sizes along with audio formats into the pin_format arrays in struct sof_ipc4_available_audio_format. This makes the base_config array in struct sof_ipc4_available_audio_format redundant. So remove it. This change will allow the addition of audio formats for the non-zero pins in topology transparent to the topology parser in the kernel. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-pcm.c | 2 +- sound/soc/sof/ipc4-topology.c | 181 +++++++++++++++++------------------------- sound/soc/sof/ipc4-topology.h | 27 +++++-- sound/soc/sof/sof-audio.h | 1 - sound/soc/sof/topology.c | 1 - 5 files changed, 95 insertions(+), 117 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index a679c08d9bb1..701da5ee4e4e 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -389,7 +389,7 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, snd_mask_none(fmt); snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); - rate->min = ipc4_copier->available_fmt.input_audio_fmts->sampling_frequency; + rate->min = ipc4_copier->available_fmt.input_pin_fmts->audio_fmt.sampling_frequency; rate->max = rate->min; switch (ipc4_copier->dai_type) { diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 0e1e4fc9224c..c462db95f3b2 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -41,41 +41,44 @@ static const struct sof_topology_token ipc4_comp_tokens[] = { offsetof(struct sof_ipc4_base_module_cfg, is_pages)}, }; -static const struct sof_topology_token ipc4_audio_format_buffer_size_tokens[] = { - {SOF_TKN_CAVS_AUDIO_FORMAT_IBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_base_module_cfg, ibs)}, - {SOF_TKN_CAVS_AUDIO_FORMAT_OBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_base_module_cfg, obs)}, -}; - static const struct sof_topology_token ipc4_in_audio_format_tokens[] = { {SOF_TKN_CAVS_AUDIO_FORMAT_IN_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, sampling_frequency)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.sampling_frequency)}, {SOF_TKN_CAVS_AUDIO_FORMAT_IN_BIT_DEPTH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, bit_depth)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.bit_depth)}, {SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_MAP, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, ch_map)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_map)}, {SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, ch_cfg)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_cfg)}, {SOF_TKN_CAVS_AUDIO_FORMAT_IN_INTERLEAVING_STYLE, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_u32, offsetof(struct sof_ipc4_audio_format, interleaving_style)}, + get_token_u32, offsetof(struct sof_ipc4_pin_format, + audio_fmt.interleaving_style)}, {SOF_TKN_CAVS_AUDIO_FORMAT_IN_FMT_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, fmt_cfg)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.fmt_cfg)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_PIN_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_pin_format, pin_index)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_IBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_pin_format, buffer_size)}, }; static const struct sof_topology_token ipc4_out_audio_format_tokens[] = { {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, sampling_frequency)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.sampling_frequency)}, {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_BIT_DEPTH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, bit_depth)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.bit_depth)}, {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_MAP, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, ch_map)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_map)}, {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, ch_cfg)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_cfg)}, {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_INTERLEAVING_STYLE, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_u32, offsetof(struct sof_ipc4_audio_format, interleaving_style)}, + get_token_u32, offsetof(struct sof_ipc4_pin_format, + audio_fmt.interleaving_style)}, {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_FMT_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - offsetof(struct sof_ipc4_audio_format, fmt_cfg)}, + offsetof(struct sof_ipc4_pin_format, audio_fmt.fmt_cfg)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_PIN_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_pin_format, pin_index)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_OBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_pin_format, buffer_size)}, }; static const struct sof_topology_token ipc4_copier_deep_buffer_tokens[] = { @@ -135,9 +138,6 @@ static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = { ipc4_in_audio_format_tokens, ARRAY_SIZE(ipc4_in_audio_format_tokens)}, [SOF_OUT_AUDIO_FORMAT_TOKENS] = {"IPC4 Output Audio format tokens", ipc4_out_audio_format_tokens, ARRAY_SIZE(ipc4_out_audio_format_tokens)}, - [SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS] = {"IPC4 Audio format buffer size tokens", - ipc4_audio_format_buffer_size_tokens, - ARRAY_SIZE(ipc4_audio_format_buffer_size_tokens)}, [SOF_COPIER_DEEP_BUFFER_TOKENS] = {"IPC4 Copier deep buffer tokens", ipc4_copier_deep_buffer_tokens, ARRAY_SIZE(ipc4_copier_deep_buffer_tokens)}, [SOF_COPIER_TOKENS] = {"IPC4 Copier tokens", ipc4_copier_tokens, @@ -148,20 +148,18 @@ static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = { [SOF_SRC_TOKENS] = {"SRC tokens", src_tokens, ARRAY_SIZE(src_tokens)}, }; -static void sof_ipc4_dbg_audio_format(struct device *dev, - struct sof_ipc4_audio_format *format, - size_t object_size, int num_format) +static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_format *pin_fmt, + int num_formats) { - struct sof_ipc4_audio_format *fmt; - void *ptr = format; int i; - for (i = 0; i < num_format; i++, ptr = (u8 *)ptr + object_size) { - fmt = ptr; + for (i = 0; i < num_formats; i++) { + struct sof_ipc4_audio_format *fmt = &pin_fmt[i].audio_fmt; dev_dbg(dev, - " #%d: %uHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x)\n", - i, fmt->sampling_frequency, fmt->bit_depth, fmt->ch_map, - fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg); + "Pin index #%d: %uHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n", + pin_fmt[i].pin_index, fmt->sampling_frequency, fmt->bit_depth, fmt->ch_map, + fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg, + pin_fmt[i].buffer_size); } } @@ -179,10 +177,9 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, struct sof_ipc4_available_audio_format *available_fmt, struct sof_ipc4_base_module_cfg *module_base_cfg) { - struct sof_ipc4_base_module_cfg *base_config; - struct sof_ipc4_audio_format *out_format, *in_format; + struct sof_ipc4_pin_format *out_format, *in_format; int audio_fmt_num = 0; - int ret, i; + int ret; ret = sof_update_ipc_object(scomp, &audio_fmt_num, SOF_AUDIO_FMT_NUM_TOKENS, swidget->tuples, @@ -195,47 +192,25 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, dev_dbg(scomp->dev, "Number of audio formats: %d\n", available_fmt->audio_fmt_num); - base_config = kcalloc(available_fmt->audio_fmt_num, sizeof(*base_config), GFP_KERNEL); - if (!base_config) - return -ENOMEM; - /* set cpc and is_pages in the module's base_config */ ret = sof_update_ipc_object(scomp, module_base_cfg, SOF_COMP_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(*module_base_cfg), 1); if (ret) { dev_err(scomp->dev, "parse comp tokens for %s failed, error: %d\n", swidget->widget->name, ret); - goto err; + return ret; } dev_dbg(scomp->dev, "widget %s cpc: %d is_pages: %d\n", swidget->widget->name, module_base_cfg->cpc, module_base_cfg->is_pages); - /* copy the ibs/obs for each base_cfg */ - ret = sof_update_ipc_object(scomp, base_config, - SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(*base_config), - available_fmt->audio_fmt_num); - if (ret) { - dev_err(scomp->dev, "parse buffer size tokens failed %d\n", ret); - goto err; - } - - for (i = 0; i < available_fmt->audio_fmt_num; i++) - dev_dbg(scomp->dev, "%d: ibs: %d obs: %d\n", i, - base_config[i].ibs, base_config[i].obs); - - in_format = kcalloc(available_fmt->audio_fmt_num, - sizeof(struct sof_ipc4_audio_format), GFP_KERNEL); - if (!in_format) { - kfree(base_config); - ret = -ENOMEM; - goto err; - } + in_format = kcalloc(available_fmt->audio_fmt_num, sizeof(*in_format), GFP_KERNEL); + if (!in_format) + return -ENOMEM; - ret = sof_update_ipc_object(scomp, available_fmt->input_audio_fmts, + ret = sof_update_ipc_object(scomp, in_format, SOF_IN_AUDIO_FORMAT_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(struct sof_ipc4_audio_format), + swidget->num_tuples, sizeof(*in_format), available_fmt->audio_fmt_num); if (ret) { dev_err(scomp->dev, "parse base_config audio_fmt tokens failed %d\n", ret); @@ -243,8 +218,7 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, } dev_dbg(scomp->dev, "Get input audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(scomp->dev, available_fmt->input_audio_fmts, - sizeof(struct sof_ipc4_audio_format), + sof_ipc4_dbg_audio_format(scomp->dev, available_fmt->input_pin_fmts, available_fmt->audio_fmt_num); out_format = kcalloc(available_fmt->audio_fmt_num, sizeof(*out_format), GFP_KERNEL); @@ -264,12 +238,10 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, } dev_dbg(scomp->dev, "Get output audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(scomp->dev, out_format, sizeof(*out_format), - available_fmt->audio_fmt_num); + sof_ipc4_dbg_audio_format(scomp->dev, out_format, available_fmt->audio_fmt_num); - available_fmt->base_config = base_config; - available_fmt->out_audio_fmt = out_format; - available_fmt->input_audio_fmts = in_format; + available_fmt->output_pin_fmts = out_format; + available_fmt->input_pin_fmts = in_format; return 0; @@ -277,8 +249,6 @@ err_out: kfree(out_format); err_in: kfree(in_format); -err: - kfree(base_config); return ret; } @@ -286,12 +256,10 @@ err: static void sof_ipc4_free_audio_fmt(struct sof_ipc4_available_audio_format *available_fmt) { - kfree(available_fmt->base_config); - available_fmt->base_config = NULL; - kfree(available_fmt->out_audio_fmt); - available_fmt->out_audio_fmt = NULL; - kfree(available_fmt->input_audio_fmts); - available_fmt->input_audio_fmts = NULL; + kfree(available_fmt->output_pin_fmts); + available_fmt->output_pin_fmts = NULL; + kfree(available_fmt->input_pin_fmts); + available_fmt->input_pin_fmts = NULL; } static void sof_ipc4_widget_free_comp_pipeline(struct snd_sof_widget *swidget) @@ -431,8 +399,7 @@ static void sof_ipc4_widget_free_comp_pcm(struct snd_sof_widget *swidget) return; available_fmt = &ipc4_copier->available_fmt; - kfree(available_fmt->base_config); - kfree(available_fmt->out_audio_fmt); + kfree(available_fmt->output_pin_fmts); kfree(ipc4_copier->gtw_attr); kfree(ipc4_copier); swidget->private = NULL; @@ -584,8 +551,7 @@ static void sof_ipc4_widget_free_comp_dai(struct snd_sof_widget *swidget) ipc4_copier = dai->private; available_fmt = &ipc4_copier->available_fmt; - kfree(available_fmt->base_config); - kfree(available_fmt->out_audio_fmt); + kfree(available_fmt->output_pin_fmts); if (ipc4_copier->dai_type != SOF_DAI_INTEL_SSP && ipc4_copier->dai_type != SOF_DAI_INTEL_DMIC) kfree(ipc4_copier->copier_config); @@ -866,14 +832,14 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params, struct sof_ipc4_available_audio_format *available_fmt) { - struct sof_ipc4_audio_format *fmt = available_fmt->ref_audio_fmt; + struct sof_ipc4_pin_format *pin_fmt = available_fmt->ref_audio_fmt; u32 valid_bits; u32 channels; u32 rate; int sample_valid_bits; int i; - if (!fmt) { + if (!pin_fmt) { dev_err(sdev->dev, "no reference formats for %s\n", swidget->widget->name); return -EINVAL; } @@ -902,7 +868,9 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, * Search supported audio formats to match rate, channels ,and * sample_valid_bytes from runtime params */ - for (i = 0; i < available_fmt->audio_fmt_num; i++, fmt++) { + for (i = 0; i < available_fmt->audio_fmt_num; i++) { + struct sof_ipc4_audio_format *fmt = &pin_fmt[i].audio_fmt; + rate = fmt->sampling_frequency; channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); @@ -921,15 +889,16 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, } /* copy input format */ - memcpy(&base_config->audio_fmt, &available_fmt->input_audio_fmts[i], sizeof(*fmt)); + memcpy(&base_config->audio_fmt, &available_fmt->input_pin_fmts[i].audio_fmt, + sizeof(*out_format)); /* set base_cfg ibs/obs */ - base_config->ibs = available_fmt->base_config[i].ibs; - base_config->obs = available_fmt->base_config[i].obs; + base_config->ibs = available_fmt->input_pin_fmts[i].buffer_size; + base_config->obs = available_fmt->output_pin_fmts[i].buffer_size; dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(sdev->dev, &base_config->audio_fmt, - sizeof(*base_config), 1); + sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->input_pin_fmts[i], 1); + if (out_format) { /* * Current topology defines pin 0 input and output formats only in pairs. @@ -938,10 +907,10 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, * input format. This logic will need to be updated when the format definitions * in topology change. */ - memcpy(out_format, &available_fmt->out_audio_fmt[i], sizeof(*fmt)); + memcpy(out_format, &available_fmt->output_pin_fmts[i].audio_fmt, + sizeof(*out_format)); dev_dbg(sdev->dev, "Init output audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(sdev->dev, out_format, - sizeof(*out_format), 1); + sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->output_pin_fmts[i], 1); } /* Return the index of the matched format */ @@ -1144,13 +1113,13 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, available_fmt = &ipc4_copier->available_fmt; /* - * Use the input_audio_fmts to match pcm params for playback and the out_audio_fmt + * Use the input_pin_fmts to match pcm params for playback and the output_pin_fmts * for capture. */ if (dir == SNDRV_PCM_STREAM_PLAYBACK) - available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; + available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; else - available_fmt->ref_audio_fmt = available_fmt->out_audio_fmt; + available_fmt->ref_audio_fmt = available_fmt->output_pin_fmts; copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; copier_data->gtw_cfg.node_id |= @@ -1170,7 +1139,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; if (dir == SNDRV_PCM_STREAM_CAPTURE) { - available_fmt->ref_audio_fmt = available_fmt->out_audio_fmt; + available_fmt->ref_audio_fmt = available_fmt->output_pin_fmts; /* * modify the input params for the dai copier as it only supports @@ -1180,7 +1149,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, snd_mask_none(fmt); snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); } else { - available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; + available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; } ref_params = pipeline_params; @@ -1201,7 +1170,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, available_fmt = &ipc4_copier->available_fmt; /* Use the input formats as the reference to match pcm params */ - available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; + available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; ref_params = pipeline_params; break; @@ -1388,7 +1357,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt; int ret; - available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; + available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; /* output format is not required to be sent to the FW for gain */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &gain->base_config, @@ -1414,7 +1383,7 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, int ret; /* only 32bit is supported by mixer */ - available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; + available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; /* output format is not required to be sent to the FW for mixer */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &mixer->base_config, @@ -1440,7 +1409,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, struct snd_interval *rate; int ret; - available_fmt->ref_audio_fmt = available_fmt->input_audio_fmts; + available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; /* output format is not required to be sent to the FW for SRC */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config, @@ -2147,7 +2116,6 @@ static int sof_ipc4_link_setup(struct snd_sof_dev *sdev, struct snd_soc_dai_link static enum sof_tokens common_copier_token_list[] = { SOF_COMP_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, - SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, SOF_OUT_AUDIO_FORMAT_TOKENS, SOF_COPIER_DEEP_BUFFER_TOKENS, @@ -2163,7 +2131,6 @@ static enum sof_tokens pipeline_token_list[] = { static enum sof_tokens dai_token_list[] = { SOF_COMP_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, - SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, SOF_OUT_AUDIO_FORMAT_TOKENS, SOF_COPIER_TOKENS, @@ -2175,8 +2142,8 @@ static enum sof_tokens pga_token_list[] = { SOF_COMP_TOKENS, SOF_GAIN_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, - SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, + SOF_OUT_AUDIO_FORMAT_TOKENS, SOF_COMP_EXT_TOKENS, }; @@ -2184,7 +2151,7 @@ static enum sof_tokens mixer_token_list[] = { SOF_COMP_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, - SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, + SOF_OUT_AUDIO_FORMAT_TOKENS, SOF_COMP_EXT_TOKENS, }; @@ -2193,7 +2160,7 @@ static enum sof_tokens src_token_list[] = { SOF_SRC_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, - SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, + SOF_OUT_AUDIO_FORMAT_TOKENS, SOF_COMP_EXT_TOKENS, }; diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 696d6c39a21b..2d9b1ba549f7 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -145,19 +145,32 @@ struct ipc4_pipeline_set_state_data { DECLARE_FLEX_ARRAY(u32, pipeline_ids); } __packed; +/** + * struct sof_ipc4_pin_format - Module pin format + * @pin_index: pin index + * @buffer_size: buffer size in bytes + * @audio_fmt: audio format for the pin + * + * This structure can be used for both output or input pins and the pin_index is relative to the + * pin type i.e output/input pin + */ +struct sof_ipc4_pin_format { + u32 pin_index; + u32 buffer_size; + struct sof_ipc4_audio_format audio_fmt; +}; + /** * struct sof_ipc4_available_audio_format - Available audio formats - * @base_config: Available base config - * @out_audio_fmt: Available output audio format - * @input_audio_fmts: Available input audio formats + * @output_pin_fmts: Available output pin formats + * @input_pin_fmts: Available input pin formats * @ref_audio_fmt: Reference audio format to match runtime audio format * @audio_fmt_num: Number of available audio formats */ struct sof_ipc4_available_audio_format { - struct sof_ipc4_base_module_cfg *base_config; - struct sof_ipc4_audio_format *out_audio_fmt; - struct sof_ipc4_audio_format *input_audio_fmts; - struct sof_ipc4_audio_format *ref_audio_fmt; + struct sof_ipc4_pin_format *output_pin_fmts; + struct sof_ipc4_pin_format *input_pin_fmts; + struct sof_ipc4_pin_format *ref_audio_fmt; int audio_fmt_num; }; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 4504f9efdc50..d220af5f08fb 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -256,7 +256,6 @@ enum sof_tokens { SOF_COMP_EXT_TOKENS, SOF_IN_AUDIO_FORMAT_TOKENS, SOF_OUT_AUDIO_FORMAT_TOKENS, - SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS, SOF_COPIER_DEEP_BUFFER_TOKENS, SOF_COPIER_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 2d76ab13b3d1..3a091f18731f 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1232,7 +1232,6 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s continue; case SOF_IN_AUDIO_FORMAT_TOKENS: case SOF_OUT_AUDIO_FORMAT_TOKENS: - case SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS: num_sets = sof_get_token_value(SOF_TKN_COMP_NUM_AUDIO_FORMATS, swidget->tuples, swidget->num_tuples); -- cgit From 9c560549e32bc2951c67106c59587f9f7bf6b70e Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:53 +0200 Subject: ASoC: SOF: ipc4-topology: Modify the signature of sof_ipc4_init_audio_fmt() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only the copier needs to set the output format in its IPC payload. So move the code to set the output format inside sof_ipc4_prepare_copier_module() and modify the signature of sof_ipc4_init_audio_fmt() to remove the out_format argument. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-9-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index c462db95f3b2..baa8f4fa6d20 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -828,7 +828,6 @@ static int sof_ipc4_widget_assign_instance_id(struct snd_sof_dev *sdev, static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, struct sof_ipc4_base_module_cfg *base_config, - struct sof_ipc4_audio_format *out_format, struct snd_pcm_hw_params *params, struct sof_ipc4_available_audio_format *available_fmt) { @@ -890,7 +889,7 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, /* copy input format */ memcpy(&base_config->audio_fmt, &available_fmt->input_pin_fmts[i].audio_fmt, - sizeof(*out_format)); + sizeof(struct sof_ipc4_audio_format)); /* set base_cfg ibs/obs */ base_config->ibs = available_fmt->input_pin_fmts[i].buffer_size; @@ -899,20 +898,6 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name); sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->input_pin_fmts[i], 1); - if (out_format) { - /* - * Current topology defines pin 0 input and output formats only in pairs. - * This assumes that the pin 0 formats are defined before all other pins. - * So pick the output audio format with the same index as the chosen - * input format. This logic will need to be updated when the format definitions - * in topology change. - */ - memcpy(out_format, &available_fmt->output_pin_fmts[i].audio_fmt, - sizeof(*out_format)); - dev_dbg(sdev->dev, "Init output audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->output_pin_fmts[i], 1); - } - /* Return the index of the matched format */ return i; } @@ -1182,12 +1167,23 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, } /* set input and output audio formats */ - ret = sof_ipc4_init_audio_fmt(sdev, swidget, &copier_data->base_config, - &copier_data->out_format, ref_params, + ret = sof_ipc4_init_audio_fmt(sdev, swidget, &copier_data->base_config, ref_params, available_fmt); if (ret < 0) return ret; + /* + * Set the output format. Current topology defines pin 0 input and output formats in pairs. + * This assumes that the pin 0 formats are defined before all other pins. + * So pick the output audio format with the same index as the chosen + * input format. This logic will need to be updated when the format definitions + * in topology change. + */ + memcpy(&copier_data->out_format, &available_fmt->output_pin_fmts[ret].audio_fmt, + sizeof(struct sof_ipc4_audio_format)); + dev_dbg(sdev->dev, "Output audio format for %s\n", swidget->widget->name); + sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->output_pin_fmts[ret], 1); + switch (swidget->id) { case snd_soc_dapm_dai_in: case snd_soc_dapm_dai_out: @@ -1361,7 +1357,7 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, /* output format is not required to be sent to the FW for gain */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &gain->base_config, - NULL, pipeline_params, available_fmt); + pipeline_params, available_fmt); if (ret < 0) return ret; @@ -1387,7 +1383,7 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, /* output format is not required to be sent to the FW for mixer */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &mixer->base_config, - NULL, pipeline_params, available_fmt); + pipeline_params, available_fmt); if (ret < 0) return ret; @@ -1413,7 +1409,7 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, /* output format is not required to be sent to the FW for SRC */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config, - NULL, pipeline_params, available_fmt); + pipeline_params, available_fmt); if (ret < 0) return ret; -- cgit From f534a94c3d765bcd5bdf10271a265883be2b4030 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:54 +0200 Subject: ASoC: SOF: ipc4-topology: Remove the ref_audio_fmt field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the field in struct sof_ipc4_available_audio_format and pass the format list to be searched as an argument to sof_ipc4_init_audio_fmt() directly. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-10-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 42 ++++++++++++++++++------------------------ sound/soc/sof/ipc4-topology.h | 2 -- 2 files changed, 18 insertions(+), 26 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index baa8f4fa6d20..3aacc440a5e4 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -829,16 +829,16 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, struct sof_ipc4_base_module_cfg *base_config, struct snd_pcm_hw_params *params, - struct sof_ipc4_available_audio_format *available_fmt) + struct sof_ipc4_available_audio_format *available_fmt, + struct sof_ipc4_pin_format *pin_fmts) { - struct sof_ipc4_pin_format *pin_fmt = available_fmt->ref_audio_fmt; u32 valid_bits; u32 channels; u32 rate; int sample_valid_bits; int i; - if (!pin_fmt) { + if (!pin_fmts) { dev_err(sdev->dev, "no reference formats for %s\n", swidget->widget->name); return -EINVAL; } @@ -868,7 +868,7 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, * sample_valid_bytes from runtime params */ for (i = 0; i < available_fmt->audio_fmt_num; i++) { - struct sof_ipc4_audio_format *fmt = &pin_fmt[i].audio_fmt; + struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt; rate = fmt->sampling_frequency; channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); @@ -1058,6 +1058,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt; struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct sof_ipc4_pin_format *format_list_to_search; struct sof_ipc4_copier_data *copier_data; struct snd_pcm_hw_params *ref_params; struct sof_ipc4_copier *ipc4_copier; @@ -1102,9 +1103,9 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, * for capture. */ if (dir == SNDRV_PCM_STREAM_PLAYBACK) - available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; + format_list_to_search = available_fmt->input_pin_fmts; else - available_fmt->ref_audio_fmt = available_fmt->output_pin_fmts; + format_list_to_search = available_fmt->output_pin_fmts; copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; copier_data->gtw_cfg.node_id |= @@ -1124,7 +1125,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; if (dir == SNDRV_PCM_STREAM_CAPTURE) { - available_fmt->ref_audio_fmt = available_fmt->output_pin_fmts; + format_list_to_search = available_fmt->output_pin_fmts; /* * modify the input params for the dai copier as it only supports @@ -1134,7 +1135,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, snd_mask_none(fmt); snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); } else { - available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; + format_list_to_search = available_fmt->input_pin_fmts; } ref_params = pipeline_params; @@ -1154,8 +1155,8 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; - /* Use the input formats as the reference to match pcm params */ - available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; + /* Use the input formats to match pcm params */ + format_list_to_search = available_fmt->input_pin_fmts; ref_params = pipeline_params; break; @@ -1168,7 +1169,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, /* set input and output audio formats */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &copier_data->base_config, ref_params, - available_fmt); + available_fmt, format_list_to_search); if (ret < 0) return ret; @@ -1353,11 +1354,9 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt = &gain->available_fmt; int ret; - available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; - - /* output format is not required to be sent to the FW for gain */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &gain->base_config, - pipeline_params, available_fmt); + pipeline_params, available_fmt, + available_fmt->input_pin_fmts); if (ret < 0) return ret; @@ -1378,12 +1377,9 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, struct sof_ipc4_available_audio_format *available_fmt = &mixer->available_fmt; int ret; - /* only 32bit is supported by mixer */ - available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; - - /* output format is not required to be sent to the FW for mixer */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &mixer->base_config, - pipeline_params, available_fmt); + pipeline_params, available_fmt, + available_fmt->input_pin_fmts); if (ret < 0) return ret; @@ -1405,11 +1401,9 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, struct snd_interval *rate; int ret; - available_fmt->ref_audio_fmt = available_fmt->input_pin_fmts; - - /* output format is not required to be sent to the FW for SRC */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config, - pipeline_params, available_fmt); + pipeline_params, available_fmt, + available_fmt->input_pin_fmts); if (ret < 0) return ret; diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 2d9b1ba549f7..6359ef8736ae 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -164,13 +164,11 @@ struct sof_ipc4_pin_format { * struct sof_ipc4_available_audio_format - Available audio formats * @output_pin_fmts: Available output pin formats * @input_pin_fmts: Available input pin formats - * @ref_audio_fmt: Reference audio format to match runtime audio format * @audio_fmt_num: Number of available audio formats */ struct sof_ipc4_available_audio_format { struct sof_ipc4_pin_format *output_pin_fmts; struct sof_ipc4_pin_format *input_pin_fmts; - struct sof_ipc4_pin_format *ref_audio_fmt; int audio_fmt_num; }; -- cgit From 4fdef47a44d6ff735902dfe740918f23932225ca Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:55 +0200 Subject: ASoC: SOF: ipc4-topology: Add new tokens for input/output pin format count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for handling processing modules with different input/output pin counts, introduce two new tokens for input/output audio format counts. Use these token values to parse all the available audio formats from topology. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-11-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 143 +++++++++++++++++++++++++----------------- sound/soc/sof/ipc4-topology.h | 6 +- sound/soc/sof/topology.c | 42 ++++++++----- 3 files changed, 114 insertions(+), 77 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 3aacc440a5e4..c91a90dd8a6e 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -90,8 +90,10 @@ static const struct sof_topology_token ipc4_copier_tokens[] = { }; static const struct sof_topology_token ipc4_audio_fmt_num_tokens[] = { - {SOF_TKN_COMP_NUM_AUDIO_FORMATS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, - 0}, + {SOF_TKN_COMP_NUM_INPUT_AUDIO_FORMATS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_available_audio_format, num_input_formats)}, + {SOF_TKN_COMP_NUM_OUTPUT_AUDIO_FORMATS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc4_available_audio_format, num_output_formats)}, }; static const struct sof_topology_token dai_tokens[] = { @@ -178,19 +180,24 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, struct sof_ipc4_base_module_cfg *module_base_cfg) { struct sof_ipc4_pin_format *out_format, *in_format; - int audio_fmt_num = 0; int ret; - ret = sof_update_ipc_object(scomp, &audio_fmt_num, + ret = sof_update_ipc_object(scomp, available_fmt, SOF_AUDIO_FMT_NUM_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(audio_fmt_num), 1); - if (ret || audio_fmt_num <= 0) { - dev_err(scomp->dev, "Invalid number of audio formats: %d\n", audio_fmt_num); + swidget->num_tuples, sizeof(available_fmt), 1); + if (ret) { + dev_err(scomp->dev, "Failed to parse audio format token count\n"); + return ret; + } + + if (!available_fmt->num_input_formats && !available_fmt->num_output_formats) { + dev_err(scomp->dev, "No input/output pin formats set in topology\n"); return -EINVAL; } - available_fmt->audio_fmt_num = audio_fmt_num; - dev_dbg(scomp->dev, "Number of audio formats: %d\n", available_fmt->audio_fmt_num); + dev_dbg(scomp->dev, + "Number of input audio formats: %d. Number of output audio formats: %d\n", + available_fmt->num_input_formats, available_fmt->num_output_formats); /* set cpc and is_pages in the module's base_config */ ret = sof_update_ipc_object(scomp, module_base_cfg, SOF_COMP_TOKENS, swidget->tuples, @@ -204,51 +211,57 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, dev_dbg(scomp->dev, "widget %s cpc: %d is_pages: %d\n", swidget->widget->name, module_base_cfg->cpc, module_base_cfg->is_pages); - in_format = kcalloc(available_fmt->audio_fmt_num, sizeof(*in_format), GFP_KERNEL); - if (!in_format) - return -ENOMEM; + if (available_fmt->num_input_formats) { + in_format = kcalloc(available_fmt->num_input_formats, + sizeof(*in_format), GFP_KERNEL); + if (!in_format) + return -ENOMEM; + available_fmt->input_pin_fmts = in_format; + + ret = sof_update_ipc_object(scomp, in_format, + SOF_IN_AUDIO_FORMAT_TOKENS, swidget->tuples, + swidget->num_tuples, sizeof(*in_format), + available_fmt->num_input_formats); + if (ret) { + dev_err(scomp->dev, "parse input audio fmt tokens failed %d\n", ret); + goto err_in; + } - ret = sof_update_ipc_object(scomp, in_format, - SOF_IN_AUDIO_FORMAT_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(*in_format), - available_fmt->audio_fmt_num); - if (ret) { - dev_err(scomp->dev, "parse base_config audio_fmt tokens failed %d\n", ret); - goto err_in; + dev_dbg(scomp->dev, "Input audio formats for %s\n", swidget->widget->name); + sof_ipc4_dbg_audio_format(scomp->dev, in_format, + available_fmt->num_input_formats); } - dev_dbg(scomp->dev, "Get input audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(scomp->dev, available_fmt->input_pin_fmts, - available_fmt->audio_fmt_num); - - out_format = kcalloc(available_fmt->audio_fmt_num, sizeof(*out_format), GFP_KERNEL); - if (!out_format) { - ret = -ENOMEM; - goto err_in; - } + if (available_fmt->num_output_formats) { + out_format = kcalloc(available_fmt->num_output_formats, sizeof(*out_format), + GFP_KERNEL); + if (!out_format) { + ret = -ENOMEM; + goto err_in; + } - ret = sof_update_ipc_object(scomp, out_format, - SOF_OUT_AUDIO_FORMAT_TOKENS, swidget->tuples, - swidget->num_tuples, sizeof(*out_format), - available_fmt->audio_fmt_num); + ret = sof_update_ipc_object(scomp, out_format, + SOF_OUT_AUDIO_FORMAT_TOKENS, swidget->tuples, + swidget->num_tuples, sizeof(*out_format), + available_fmt->num_output_formats); + if (ret) { + dev_err(scomp->dev, "parse output audio fmt tokens failed\n"); + goto err_out; + } - if (ret) { - dev_err(scomp->dev, "parse output audio_fmt tokens failed\n"); - goto err_out; + available_fmt->output_pin_fmts = out_format; + dev_dbg(scomp->dev, "Output audio formats for %s\n", swidget->widget->name); + sof_ipc4_dbg_audio_format(scomp->dev, out_format, + available_fmt->num_output_formats); } - dev_dbg(scomp->dev, "Get output audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(scomp->dev, out_format, available_fmt->audio_fmt_num); - - available_fmt->output_pin_fmts = out_format; - available_fmt->input_pin_fmts = in_format; - return 0; err_out: kfree(out_format); err_in: kfree(in_format); + available_fmt->input_pin_fmts = NULL; return ret; } @@ -830,7 +843,7 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, struct sof_ipc4_base_module_cfg *base_config, struct snd_pcm_hw_params *params, struct sof_ipc4_available_audio_format *available_fmt, - struct sof_ipc4_pin_format *pin_fmts) + struct sof_ipc4_pin_format *pin_fmts, u32 pin_fmts_size) { u32 valid_bits; u32 channels; @@ -858,7 +871,7 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, return -EINVAL; } - if (!available_fmt->audio_fmt_num) { + if (!pin_fmts_size) { dev_err(sdev->dev, "no formats available for %s\n", swidget->widget->name); return -EINVAL; } @@ -867,7 +880,7 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, * Search supported audio formats to match rate, channels ,and * sample_valid_bytes from runtime params */ - for (i = 0; i < available_fmt->audio_fmt_num; i++) { + for (i = 0; i < pin_fmts_size; i++) { struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt; rate = fmt->sampling_frequency; @@ -881,22 +894,26 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, } } - if (i == available_fmt->audio_fmt_num) { + if (i == pin_fmts_size) { dev_err(sdev->dev, "%s: Unsupported audio format: %uHz, %ubit, %u channels\n", __func__, params_rate(params), sample_valid_bits, params_channels(params)); return -EINVAL; } /* copy input format */ - memcpy(&base_config->audio_fmt, &available_fmt->input_pin_fmts[i].audio_fmt, - sizeof(struct sof_ipc4_audio_format)); + if (available_fmt->num_input_formats && i < available_fmt->num_input_formats) { + memcpy(&base_config->audio_fmt, &available_fmt->input_pin_fmts[i].audio_fmt, + sizeof(struct sof_ipc4_audio_format)); + + /* set base_cfg ibs/obs */ + base_config->ibs = available_fmt->input_pin_fmts[i].buffer_size; - /* set base_cfg ibs/obs */ - base_config->ibs = available_fmt->input_pin_fmts[i].buffer_size; - base_config->obs = available_fmt->output_pin_fmts[i].buffer_size; + dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name); + sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->input_pin_fmts[i], 1); + } - dev_dbg(sdev->dev, "Init input audio formats for %s\n", swidget->widget->name); - sof_ipc4_dbg_audio_format(sdev->dev, &available_fmt->input_pin_fmts[i], 1); + if (available_fmt->num_output_formats && i < available_fmt->num_output_formats) + base_config->obs = available_fmt->output_pin_fmts[i].buffer_size; /* Return the index of the matched format */ return i; @@ -1070,6 +1087,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, u32 **data; int ipc_size, ret; u32 deep_buffer_dma_ms = 0; + u32 format_list_count; dev_dbg(sdev->dev, "copier %s, type %d", swidget->widget->name, swidget->id); @@ -1102,10 +1120,13 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, * Use the input_pin_fmts to match pcm params for playback and the output_pin_fmts * for capture. */ - if (dir == SNDRV_PCM_STREAM_PLAYBACK) + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { format_list_to_search = available_fmt->input_pin_fmts; - else + format_list_count = available_fmt->num_input_formats; + } else { format_list_to_search = available_fmt->output_pin_fmts; + format_list_count = available_fmt->num_output_formats; + } copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; copier_data->gtw_cfg.node_id |= @@ -1126,6 +1147,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, available_fmt = &ipc4_copier->available_fmt; if (dir == SNDRV_PCM_STREAM_CAPTURE) { format_list_to_search = available_fmt->output_pin_fmts; + format_list_count = available_fmt->num_output_formats; /* * modify the input params for the dai copier as it only supports @@ -1136,6 +1158,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); } else { format_list_to_search = available_fmt->input_pin_fmts; + format_list_count = available_fmt->num_input_formats; } ref_params = pipeline_params; @@ -1157,6 +1180,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, /* Use the input formats to match pcm params */ format_list_to_search = available_fmt->input_pin_fmts; + format_list_count = available_fmt->num_input_formats; ref_params = pipeline_params; break; @@ -1169,7 +1193,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, /* set input and output audio formats */ ret = sof_ipc4_init_audio_fmt(sdev, swidget, &copier_data->base_config, ref_params, - available_fmt, format_list_to_search); + available_fmt, format_list_to_search, format_list_count); if (ret < 0) return ret; @@ -1356,7 +1380,8 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, ret = sof_ipc4_init_audio_fmt(sdev, swidget, &gain->base_config, pipeline_params, available_fmt, - available_fmt->input_pin_fmts); + available_fmt->input_pin_fmts, + available_fmt->num_input_formats); if (ret < 0) return ret; @@ -1379,7 +1404,8 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, ret = sof_ipc4_init_audio_fmt(sdev, swidget, &mixer->base_config, pipeline_params, available_fmt, - available_fmt->input_pin_fmts); + available_fmt->input_pin_fmts, + available_fmt->num_input_formats); if (ret < 0) return ret; @@ -1403,7 +1429,8 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config, pipeline_params, available_fmt, - available_fmt->input_pin_fmts); + available_fmt->input_pin_fmts, + available_fmt->num_input_formats); if (ret < 0) return ret; diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 6359ef8736ae..fad7a628f782 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -164,12 +164,14 @@ struct sof_ipc4_pin_format { * struct sof_ipc4_available_audio_format - Available audio formats * @output_pin_fmts: Available output pin formats * @input_pin_fmts: Available input pin formats - * @audio_fmt_num: Number of available audio formats + * @num_input_formats: Number of input pin formats + * @num_output_formats: Number of output pin formats */ struct sof_ipc4_available_audio_format { struct sof_ipc4_pin_format *output_pin_fmts; struct sof_ipc4_pin_format *input_pin_fmts; - int audio_fmt_num; + u32 num_input_formats; + u32 num_output_formats; }; /** diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 3a091f18731f..b642835e14df 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1231,35 +1231,43 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s continue; case SOF_IN_AUDIO_FORMAT_TOKENS: - case SOF_OUT_AUDIO_FORMAT_TOKENS: - num_sets = sof_get_token_value(SOF_TKN_COMP_NUM_AUDIO_FORMATS, + num_sets = sof_get_token_value(SOF_TKN_COMP_NUM_INPUT_AUDIO_FORMATS, swidget->tuples, swidget->num_tuples); - if (num_sets < 0) { - dev_err(sdev->dev, "Invalid audio format count for %s\n", + dev_err(sdev->dev, "Invalid input audio format count for %s\n", swidget->widget->name); ret = num_sets; goto err; } - - if (num_sets > 1) { - struct snd_sof_tuple *new_tuples; - - num_tuples += token_list[object_token_list[i]].count * num_sets; - new_tuples = krealloc(swidget->tuples, - sizeof(*new_tuples) * num_tuples, GFP_KERNEL); - if (!new_tuples) { - ret = -ENOMEM; - goto err; - } - - swidget->tuples = new_tuples; + break; + case SOF_OUT_AUDIO_FORMAT_TOKENS: + num_sets = sof_get_token_value(SOF_TKN_COMP_NUM_OUTPUT_AUDIO_FORMATS, + swidget->tuples, swidget->num_tuples); + if (num_sets < 0) { + dev_err(sdev->dev, "Invalid output audio format count for %s\n", + swidget->widget->name); + ret = num_sets; + goto err; } break; default: break; } + if (num_sets > 1) { + struct snd_sof_tuple *new_tuples; + + num_tuples += token_list[object_token_list[i]].count * num_sets; + new_tuples = krealloc(swidget->tuples, + sizeof(*new_tuples) * num_tuples, GFP_KERNEL); + if (!new_tuples) { + ret = -ENOMEM; + goto err; + } + + swidget->tuples = new_tuples; + } + /* copy one set of tuples per token ID into swidget->tuples */ ret = sof_copy_tuples(sdev, private->array, le32_to_cpu(private->size), object_token_list[i], num_sets, swidget->tuples, -- cgit From ad70f2f0e6e38675d7805482d2c625fca5756a2e Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 13 Mar 2023 14:48:56 +0200 Subject: ASoC: SOF: ipc4-topology: Search only pin 0 formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Base config only contains the input/output audio formats for pin 0. So match only the pin 0 formats during runtime format selection. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313124856.8140-12-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index c91a90dd8a6e..683182e53a32 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -877,12 +877,15 @@ static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, } /* - * Search supported audio formats to match rate, channels ,and + * Search supported audio formats with pin index 0 to match rate, channels ,and * sample_valid_bytes from runtime params */ for (i = 0; i < pin_fmts_size; i++) { struct sof_ipc4_audio_format *fmt = &pin_fmts[i].audio_fmt; + if (pin_fmts[i].pin_index) + continue; + rate = fmt->sampling_frequency; channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); -- cgit From ff728899065922534d80170685fb807194d6487b Mon Sep 17 00:00:00 2001 From: Trevor Wu Date: Tue, 7 Mar 2023 12:09:35 +0800 Subject: ASoC: mediatek: mt8195: add dai id check before accessing array Coverity shows "afe_priv->dai_priv[dai_id] evaluates to an address that could be at negative offset of an array.". Add dai id check before accessing the array element. This ensures that the offset of an array must be a valid index. Signed-off-by: Trevor Wu Link: https://lore.kernel.org/r/20230307040938.7484-2-trevor.wu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8195/mt8195-dai-adda.c | 17 ++- sound/soc/mediatek/mt8195/mt8195-dai-etdm.c | 177 ++++++++++++++++++++++++---- sound/soc/mediatek/mt8195/mt8195-dai-pcm.c | 26 +++- 3 files changed, 185 insertions(+), 35 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-adda.c b/sound/soc/mediatek/mt8195/mt8195-dai-adda.c index f04bd1781356..0dd35255066b 100644 --- a/sound/soc/mediatek/mt8195/mt8195-dai-adda.c +++ b/sound/soc/mediatek/mt8195/mt8195-dai-adda.c @@ -704,13 +704,18 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_adda_priv *adda_priv = afe_priv->dai_priv[dai->id]; + struct mtk_dai_adda_priv *adda_priv; unsigned int rate = params_rate(params); - int id = dai->id; - int ret = 0; + int ret; + + if (dai->id != MT8195_AFE_IO_DL_SRC && + dai->id != MT8195_AFE_IO_UL_SRC1 && + dai->id != MT8195_AFE_IO_UL_SRC2) + return -EINVAL; + adda_priv = afe_priv->dai_priv[dai->id]; dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n", - __func__, id, substream->stream, rate); + __func__, dai->id, substream->stream, rate); if (rate > ADDA_HIRES_THRES) adda_priv->hires_required = 1; @@ -718,9 +723,9 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, adda_priv->hires_required = 0; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - ret = mtk_dai_da_configure(afe, rate, id); + ret = mtk_dai_da_configure(afe, rate, dai->id); else - ret = mtk_dai_ad_configure(afe, rate, id); + ret = mtk_dai_ad_configure(afe, rate, dai->id); return ret; } diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c index f2c9a1fdbe0d..eedb9165f911 100644 --- a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c +++ b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c @@ -137,6 +137,38 @@ static const struct mtk_dai_etdm_rate mt8195_etdm_rates[] = { { .rate = 352800, .reg_value = 21, }, }; +static bool mt8195_afe_etdm_is_valid(int id) +{ + switch (id) { + case MT8195_AFE_IO_ETDM1_IN: + fallthrough; + case MT8195_AFE_IO_ETDM2_IN: + fallthrough; + case MT8195_AFE_IO_ETDM1_OUT: + fallthrough; + case MT8195_AFE_IO_ETDM2_OUT: + fallthrough; + case MT8195_AFE_IO_DPTX: + fallthrough; + case MT8195_AFE_IO_ETDM3_OUT: + return true; + default: + return false; + } +} + +static bool mt8195_afe_hdmitx_dptx_is_valid(int id) +{ + switch (id) { + case MT8195_AFE_IO_DPTX: + fallthrough; + case MT8195_AFE_IO_ETDM3_OUT: + return true; + default: + return false; + } +} + static int get_etdm_fs_timing(unsigned int rate) { int i; @@ -236,8 +268,12 @@ static int is_cowork_mode(struct snd_soc_dai *dai) { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + struct mtk_dai_etdm_priv *etdm_data; + if (!mt8195_afe_etdm_is_valid(dai->id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai->id]; return (etdm_data->cowork_slv_count > 0 || etdm_data->cowork_source_id != COWORK_ETDM_NONE); } @@ -264,8 +300,14 @@ static int get_etdm_cowork_master_id(struct snd_soc_dai *dai) { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; - int dai_id = etdm_data->cowork_source_id; + struct mtk_dai_etdm_priv *etdm_data; + int dai_id; + + if (!mt8195_afe_etdm_is_valid(dai->id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai->id]; + dai_id = etdm_data->cowork_source_id; if (dai_id == COWORK_ETDM_NONE) dai_id = dai->id; @@ -1276,9 +1318,13 @@ static int mt8195_afe_enable_etdm(struct mtk_base_afe *afe, int dai_id) int ret = 0; struct etdm_con_reg etdm_reg; struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; unsigned long flags; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); etdm_data->en_ref_cnt++; if (etdm_data->en_ref_cnt == 1) { @@ -1299,9 +1345,13 @@ static int mt8195_afe_disable_etdm(struct mtk_base_afe *afe, int dai_id) int ret = 0; struct etdm_con_reg etdm_reg; struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; unsigned long flags; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); if (etdm_data->en_ref_cnt > 0) { etdm_data->en_ref_cnt--; @@ -1357,12 +1407,16 @@ static int etdm_cowork_slv_sel(int id, int slave_mode) static int mt8195_etdm_sync_mode_configure(struct mtk_base_afe *afe, int dai_id) { struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; unsigned int reg = 0; unsigned int mask; unsigned int val; int cowork_source_sel; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; if (etdm_data->cowork_source_id == COWORK_ETDM_NONE) return 0; @@ -1532,8 +1586,10 @@ static int mtk_dai_etdm_startup(struct snd_pcm_substream *substream, if (is_cowork_mode(dai)) { mst_dai_id = get_etdm_cowork_master_id(dai); - mtk_dai_etdm_enable_mclk(afe, mst_dai_id); + if (!mt8195_afe_etdm_is_valid(mst_dai_id)) + return -EINVAL; + mtk_dai_etdm_enable_mclk(afe, mst_dai_id); cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(mst_dai_id); if (cg_id >= 0) mt8195_afe_enable_clk(afe, afe_priv->clk[cg_id]); @@ -1571,6 +1627,9 @@ static void mtk_dai_etdm_shutdown(struct snd_pcm_substream *substream, if (is_cowork_mode(dai)) { mst_dai_id = get_etdm_cowork_master_id(dai); + if (!mt8195_afe_etdm_is_valid(mst_dai_id)) + return; + cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(mst_dai_id); if (cg_id >= 0) mt8195_afe_disable_clk(afe, afe_priv->clk[cg_id]); @@ -1631,16 +1690,24 @@ static int mtk_dai_etdm_in_configure(struct mtk_base_afe *afe, int dai_id) { struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; struct etdm_con_reg etdm_reg; - bool slave_mode = etdm_data->slave_mode; - unsigned int data_mode = etdm_data->data_mode; - unsigned int lrck_width = etdm_data->lrck_width; + bool slave_mode; + unsigned int data_mode; + unsigned int lrck_width; unsigned int val = 0; unsigned int mask = 0; int i; int ret; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; + slave_mode = etdm_data->slave_mode; + data_mode = etdm_data->data_mode; + lrck_width = etdm_data->lrck_width; + dev_dbg(afe->dev, "%s rate %u channels %u, id %d\n", __func__, rate, channels, dai_id); @@ -1748,15 +1815,22 @@ static int mtk_dai_etdm_out_configure(struct mtk_base_afe *afe, int dai_id) { struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; struct etdm_con_reg etdm_reg; - bool slave_mode = etdm_data->slave_mode; - unsigned int lrck_width = etdm_data->lrck_width; + bool slave_mode; + unsigned int lrck_width; unsigned int val = 0; unsigned int mask = 0; int ret; int fs = 0; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; + slave_mode = etdm_data->slave_mode; + lrck_width = etdm_data->lrck_width; + dev_dbg(afe->dev, "%s rate %u channels %u, id %d\n", __func__, rate, channels, dai_id); @@ -1837,7 +1911,7 @@ static int mtk_dai_etdm_out_configure(struct mtk_base_afe *afe, static int mtk_dai_etdm_mclk_configure(struct mtk_base_afe *afe, int dai_id) { struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; int clk_id = mtk_dai_etdm_get_clk_id_by_dai_id(dai_id); int clkdiv_id = mtk_dai_etdm_get_clkdiv_id_by_dai_id(dai_id); int apll; @@ -1850,6 +1924,10 @@ static int mtk_dai_etdm_mclk_configure(struct mtk_base_afe *afe, int dai_id) if (clk_id < 0 || clkdiv_id < 0) return 0; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; ret = get_etdm_reg(dai_id, &etdm_reg); if (ret < 0) return ret; @@ -1888,9 +1966,9 @@ static int mtk_dai_etdm_configure(struct mtk_base_afe *afe, int dai_id) { struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; struct etdm_con_reg etdm_reg; - bool slave_mode = etdm_data->slave_mode; + bool slave_mode; unsigned int etdm_channels; unsigned int val = 0; unsigned int mask = 0; @@ -1898,6 +1976,11 @@ static int mtk_dai_etdm_configure(struct mtk_base_afe *afe, unsigned int wlen = get_etdm_wlen(bit_width); int ret; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; + slave_mode = etdm_data->slave_mode; ret = get_etdm_reg(dai_id, &etdm_reg); if (ret < 0) return ret; @@ -1973,6 +2056,8 @@ static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream, if (is_cowork_mode(dai)) { mst_dai_id = get_etdm_cowork_master_id(dai); + if (!mt8195_afe_etdm_is_valid(mst_dai_id)) + return -EINVAL; ret = mtk_dai_etdm_mclk_configure(afe, mst_dai_id); if (ret) @@ -2024,6 +2109,9 @@ static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_RESUME: if (is_cowork_mode(dai)) { mst_dai_id = get_etdm_cowork_master_id(dai); + if (!mt8195_afe_etdm_is_valid(mst_dai_id)) + return -EINVAL; + mst_etdm_data = afe_priv->dai_priv[mst_dai_id]; //open master first @@ -2040,6 +2128,9 @@ static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_SUSPEND: if (is_cowork_mode(dai)) { mst_dai_id = get_etdm_cowork_master_id(dai); + if (!mt8195_afe_etdm_is_valid(mst_dai_id)) + return -EINVAL; + mst_etdm_data = afe_priv->dai_priv[mst_dai_id]; for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) { @@ -2061,10 +2152,14 @@ static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd, static int mtk_dai_etdm_cal_mclk(struct mtk_base_afe *afe, int freq, int dai_id) { struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct mtk_dai_etdm_priv *etdm_data; int apll; int apll_rate; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai_id]; if (freq == 0) { etdm_data->mclk_freq = freq; return 0; @@ -2104,6 +2199,9 @@ static int mtk_dai_etdm_set_sysclk(struct snd_soc_dai *dai, else dai_id = dai->id; + if (!mt8195_afe_etdm_is_valid(dai_id)) + return -EINVAL; + etdm_data = afe_priv->dai_priv[dai_id]; etdm_data->mclk_dir = dir; return mtk_dai_etdm_cal_mclk(afe, freq, dai_id); @@ -2115,8 +2213,12 @@ static int mtk_dai_etdm_set_tdm_slot(struct snd_soc_dai *dai, { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + struct mtk_dai_etdm_priv *etdm_data; + + if (!mt8195_afe_etdm_is_valid(dai->id)) + return -EINVAL; + etdm_data = afe_priv->dai_priv[dai->id]; dev_dbg(dai->dev, "%s id %d slot_width %d\n", __func__, dai->id, slot_width); @@ -2129,8 +2231,12 @@ static int mtk_dai_etdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + struct mtk_dai_etdm_priv *etdm_data; + + if (!mt8195_afe_etdm_is_valid(dai->id)) + return -EINVAL; + etdm_data = afe_priv->dai_priv[dai->id]; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: etdm_data->format = MTK_DAI_ETDM_FORMAT_I2S; @@ -2248,13 +2354,18 @@ static int mtk_dai_hdmitx_dptx_hw_params(struct snd_pcm_substream *substream, { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + struct mtk_dai_etdm_priv *etdm_data; unsigned int rate = params_rate(params); unsigned int channels = params_channels(params); snd_pcm_format_t format = params_format(params); int width = snd_pcm_format_physical_width(format); int ret = 0; + if (!mt8195_afe_hdmitx_dptx_is_valid(dai->id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai->id]; + /* dptx configure */ if (dai->id == MT8195_AFE_IO_DPTX) { regmap_update_bits(afe->regmap, AFE_DPTX_CON, @@ -2331,7 +2442,12 @@ static int mtk_dai_hdmitx_dptx_set_sysclk(struct snd_soc_dai *dai, { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + struct mtk_dai_etdm_priv *etdm_data; + + if (!mt8195_afe_hdmitx_dptx_is_valid(dai->id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai->id]; dev_dbg(dai->dev, "%s id %d freq %u, dir %d\n", __func__, dai->id, freq, dir); @@ -2370,10 +2486,14 @@ static int mtk_dai_etdm_probe(struct snd_soc_dai *dai) { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + struct mtk_dai_etdm_priv *etdm_data; dev_dbg(dai->dev, "%s id %d\n", __func__, dai->id); + if (!mt8195_afe_etdm_is_valid(dai->id)) + return -EINVAL; + + etdm_data = afe_priv->dai_priv[dai->id]; if (etdm_data->mclk_freq) { dev_dbg(afe->dev, "MCLK always on, rate %d\n", etdm_data->mclk_freq); @@ -2477,6 +2597,11 @@ static void mt8195_etdm_update_sync_info(struct mtk_base_afe *afe) etdm_data = afe_priv->dai_priv[i]; if (etdm_data->cowork_source_id != COWORK_ETDM_NONE) { mst_dai_id = etdm_data->cowork_source_id; + if (!mt8195_afe_etdm_is_valid(mst_dai_id)) { + dev_err(afe->dev, "%s invalid dai id %d\n", + __func__, mst_dai_id); + return; + } mst_data = afe_priv->dai_priv[mst_dai_id]; if (mst_data->cowork_source_id != COWORK_ETDM_NONE) dev_info(afe->dev, "%s [%d] wrong sync source\n" @@ -2513,6 +2638,12 @@ static void mt8195_dai_etdm_parse_of(struct mtk_base_afe *afe) for (i = 0; i < MT8195_AFE_IO_ETDM_NUM; i++) { dai_id = ETDM_TO_DAI_ID(i); + if (!mt8195_afe_etdm_is_valid(dai_id)) { + dev_err(afe->dev, "%s invalid dai id %d\n", + __func__, dai_id); + return; + } + etdm_data = afe_priv->dai_priv[dai_id]; ret = snprintf(prop, sizeof(prop), diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c index 051433689ff5..6d6d79300d51 100644 --- a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c +++ b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c @@ -122,17 +122,26 @@ static int mtk_dai_pcm_configure(struct snd_pcm_substream *substream, struct snd_pcm_runtime * const runtime = substream->runtime; struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_pcmif_priv *pcmif_priv = afe_priv->dai_priv[dai->id]; - unsigned int slave_mode = pcmif_priv->slave_mode; - unsigned int lrck_inv = pcmif_priv->lrck_inv; - unsigned int bck_inv = pcmif_priv->bck_inv; - unsigned int fmt = pcmif_priv->format; + struct mtk_dai_pcmif_priv *pcmif_priv; + unsigned int slave_mode; + unsigned int lrck_inv; + unsigned int bck_inv; + unsigned int fmt; unsigned int bit_width = dai->sample_bits; unsigned int val = 0; unsigned int mask = 0; int fs = 0; int mode = 0; + if (dai->id != MT8195_AFE_IO_PCM) + return -EINVAL; + + pcmif_priv = afe_priv->dai_priv[dai->id]; + slave_mode = pcmif_priv->slave_mode; + lrck_inv = pcmif_priv->lrck_inv; + bck_inv = pcmif_priv->bck_inv; + fmt = pcmif_priv->format; + /* sync freq mode */ fs = mt8195_afe_fs_timing(runtime->rate); if (fs < 0) @@ -230,10 +239,15 @@ static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; - struct mtk_dai_pcmif_priv *pcmif_priv = afe_priv->dai_priv[dai->id]; + struct mtk_dai_pcmif_priv *pcmif_priv; dev_dbg(dai->dev, "%s fmt 0x%x\n", __func__, fmt); + if (dai->id != MT8195_AFE_IO_PCM) + return -EINVAL; + + pcmif_priv = afe_priv->dai_priv[dai->id]; + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: pcmif_priv->format = MTK_DAI_PCM_FMT_I2S; -- cgit From 1a3f0116b74ba2f9477c28fcf9d66ac7126455fd Mon Sep 17 00:00:00 2001 From: Trevor Wu Date: Tue, 7 Mar 2023 12:09:36 +0800 Subject: ASoC: mediatek: mt9195-mt6359: fix UNINIT problem Coverity shows using uninitialized value monitor. When regmap_read returns an error, monitor keeps the value left from earlier computation. To prevent from the unexpected result in the case, assign 0 to monitor. Signed-off-by: Trevor Wu Link: https://lore.kernel.org/r/20230307040938.7484-3-trevor.wu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8195/mt8195-mt6359.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359.c b/sound/soc/mediatek/mt8195/mt8195-mt6359.c index 4682748d82be..ceca882ecff7 100644 --- a/sound/soc/mediatek/mt8195/mt8195-mt6359.c +++ b/sound/soc/mediatek/mt8195/mt8195-mt6359.c @@ -158,7 +158,7 @@ static int mt8195_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd) int mtkaif_phase_cycle[MT8195_MTKAIF_MISO_NUM]; int mtkaif_calibration_num_phase; bool mtkaif_calibration_ok; - unsigned int monitor; + unsigned int monitor = 0; int counter; int phase; int i; -- cgit From 9760e01b3851dc51d1901876668168328d34a647 Mon Sep 17 00:00:00 2001 From: Trevor Wu Date: Tue, 7 Mar 2023 12:09:37 +0800 Subject: ASoC: mediatek: mt6358: fix UNINIT problem Coverity shows decaring variable reg without initializer. When regmap_read returns an error, reg keeps the value left from earlier computation. To prevent from the unexpected result in the case, assign 0 to reg. Signed-off-by: Trevor Wu Link: https://lore.kernel.org/r/20230307040938.7484-4-trevor.wu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6358.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c index b54610b27906..d7b157ddc9a8 100644 --- a/sound/soc/codecs/mt6358.c +++ b/sound/soc/codecs/mt6358.c @@ -429,7 +429,7 @@ static int mt6358_put_volsw(struct snd_kcontrol *kcontrol, struct mt6358_priv *priv = snd_soc_component_get_drvdata(component); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg; + unsigned int reg = 0; int ret; ret = snd_soc_put_volsw(kcontrol, ucontrol); -- cgit From 3a60fa4c063dacc5eb66660aa23107f3cb8a477e Mon Sep 17 00:00:00 2001 From: Trevor Wu Date: Tue, 7 Mar 2023 12:09:38 +0800 Subject: ASoC: mediatek: mt6359: fix UNINIT problem Coverity shows decaring variable reg without initializer. When regmap_read returns an error, reg keeps the value left from earlier computation. To prevent from the unexpected result in the case, assign 0 to reg. Signed-off-by: Trevor Wu Link: https://lore.kernel.org/r/20230307040938.7484-5-trevor.wu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6359.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/mt6359.c b/sound/soc/codecs/mt6359.c index c9a453ce8a2a..cb487e63615c 100644 --- a/sound/soc/codecs/mt6359.c +++ b/sound/soc/codecs/mt6359.c @@ -358,7 +358,7 @@ static int mt6359_put_volsw(struct snd_kcontrol *kcontrol, struct mt6359_priv *priv = snd_soc_component_get_drvdata(component); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg; + unsigned int reg = 0; int index = ucontrol->value.integer.value[0]; int ret; -- cgit From 8cd3cb17fcf216cb859f86a00fff428fbcecc1d8 Mon Sep 17 00:00:00 2001 From: Chao Song Date: Mon, 13 Mar 2023 12:13:02 +0200 Subject: ASoC: SOF: sof-audio: add support for setting up loopback routes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During route setup, playback stream routes are setup by going through sink path, capture stream routes are set up by going through source path. This is not sufficient to handle loopback cases between pipelines configured with different directions, e.g. a sidetone or an amplifier feedback connected to a speaker protection module. So, add the logic to handle such routes between widgets that aren't in the list of DAPM widgets associated with the same PCM. Link: https://github.com/thesofproject/linux/issues/4042 Suggested-by: Bard Liao Signed-off-by: Chao Song Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230313101302.20950-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-audio.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 6de388a8d0b8..4f12e137ff63 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -280,9 +280,11 @@ int sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsourc static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget_list *list, int dir) { + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); struct snd_soc_dapm_widget *widget; + struct snd_sof_route *sroute; struct snd_soc_dapm_path *p; - int ret; + int ret = 0; int i; /* @@ -325,6 +327,63 @@ static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev, } } + /* + * The above loop handles connections between widgets that belong to the DAPM widget list. + * This is not sufficient to handle loopback cases between pipelines configured with + * different directions, e.g. a sidetone or an amplifier feedback connected to a speaker + * protection module. + */ + list_for_each_entry(sroute, &sdev->route_list, list) { + bool src_widget_in_dapm_list, sink_widget_in_dapm_list; + struct snd_sof_widget *swidget; + + if (sroute->setup) + continue; + + src_widget_in_dapm_list = widget_in_list(list, sroute->src_widget->widget); + sink_widget_in_dapm_list = widget_in_list(list, sroute->sink_widget->widget); + + /* + * if both source and sink are in the DAPM list, the route must already have been + * set up above. And if neither are in the DAPM list, the route shouldn't be + * handled now. + */ + if (src_widget_in_dapm_list == sink_widget_in_dapm_list) + continue; + + /* + * At this point either the source widget or the sink widget is in the DAPM list + * with a route that might need to be set up. Check the use_count of the widget + * that is not in the DAPM list to confirm if it is in use currently before setting + * up the route. + */ + if (src_widget_in_dapm_list) + swidget = sroute->sink_widget; + else + swidget = sroute->src_widget; + + mutex_lock(&swidget->setup_mutex); + if (!swidget->use_count) { + mutex_unlock(&swidget->setup_mutex); + continue; + } + + if (tplg_ops && tplg_ops->route_setup) { + /* + * this route will get freed when either the source widget or the sink + * widget is freed during hw_free + */ + ret = tplg_ops->route_setup(sdev, sroute); + if (!ret) + sroute->setup = true; + } + + mutex_unlock(&swidget->setup_mutex); + + if (ret < 0) + return ret; + } + return 0; } -- cgit From d7d103d1779c3d0bc4d55f2802930a6b067450c0 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Thu, 9 Mar 2023 09:09:59 -0500 Subject: ASoC: SMA1303: set sma_i2c_regmap storage-class-specifier to static smatch reports sound/soc/codecs/sma1303.c:1594:28: warning: symbol 'sma_i2c_regmap' was not declared. Should it be static? sma_i2c_regmap is only used in sma1303, so it should be static Signed-off-by: Tom Rix Link: https://lore.kernel.org/r/20230309140959.2616497-1-trix@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/sma1303.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/sma1303.c b/sound/soc/codecs/sma1303.c index fa4b0a60f8a9..b6c132edf3bd 100644 --- a/sound/soc/codecs/sma1303.c +++ b/sound/soc/codecs/sma1303.c @@ -1591,7 +1591,7 @@ static const struct snd_soc_component_driver sma1303_component = { .num_dapm_routes = ARRAY_SIZE(sma1303_audio_map), }; -const struct regmap_config sma_i2c_regmap = { +static const struct regmap_config sma_i2c_regmap = { .reg_bits = 8, .val_bits = 8, -- cgit From a9048d64fb9605eb68c9912724e4a1346db8ba1a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 10 Mar 2023 22:43:29 +0100 Subject: ASoC: codecs: adau1977-spi: Mark OF related data as maybe unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be compile tested with !CONFIG_OF making certain data unused: sound/soc/codecs/adau1977-spi.c:58:34: error: ‘adau1977_spi_of_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230310214333.274903-6-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/adau1977-spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/adau1977-spi.c b/sound/soc/codecs/adau1977-spi.c index 8370bec27a9c..207c5c95f35a 100644 --- a/sound/soc/codecs/adau1977-spi.c +++ b/sound/soc/codecs/adau1977-spi.c @@ -55,7 +55,7 @@ static const struct spi_device_id adau1977_spi_ids[] = { }; MODULE_DEVICE_TABLE(spi, adau1977_spi_ids); -static const struct of_device_id adau1977_spi_of_match[] = { +static const struct of_device_id adau1977_spi_of_match[] __maybe_unused = { { .compatible = "adi,adau1977" }, { .compatible = "adi,adau1978" }, { .compatible = "adi,adau1979" }, -- cgit From 413beba1a336e6068119f31a4441c51a7aeb1b55 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 10 Mar 2023 22:43:30 +0100 Subject: ASoC: codecs: pcm179x-spi: Mark OF related data as maybe unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be compile tested with !CONFIG_OF making certain data unused: sound/soc/codecs/pcm179x-spi.c:32:34: error: ‘pcm179x_of_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230310214333.274903-7-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/pcm179x-spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/pcm179x-spi.c b/sound/soc/codecs/pcm179x-spi.c index ebf63ea90a1c..192fee90c971 100644 --- a/sound/soc/codecs/pcm179x-spi.c +++ b/sound/soc/codecs/pcm179x-spi.c @@ -29,7 +29,7 @@ static int pcm179x_spi_probe(struct spi_device *spi) return pcm179x_common_init(&spi->dev, regmap); } -static const struct of_device_id pcm179x_of_match[] = { +static const struct of_device_id pcm179x_of_match[] __maybe_unused = { { .compatible = "ti,pcm1792a", }, { } }; -- cgit From 0e8599a35823f05e90513918ff1201f8d210e315 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 10 Mar 2023 22:43:31 +0100 Subject: ASoC: codecs: rt1019: Mark OF related data as maybe unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be compile tested with !CONFIG_OF making certain data unused: sound/soc/codecs/rt1019.c:549:34: error: ‘rt1019_of_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230310214333.274903-8-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt1019.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt1019.c b/sound/soc/codecs/rt1019.c index 49f527c61a7a..dff2596c81eb 100644 --- a/sound/soc/codecs/rt1019.c +++ b/sound/soc/codecs/rt1019.c @@ -546,7 +546,7 @@ static const struct i2c_device_id rt1019_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt1019_i2c_id); -static const struct of_device_id rt1019_of_match[] = { +static const struct of_device_id rt1019_of_match[] __maybe_unused = { { .compatible = "realtek,rt1019", }, {}, }; -- cgit From 075a430db402eed0907b80493f1432d47a5120a7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 10 Mar 2023 22:43:32 +0100 Subject: ASoC: codecs: src4xxx-i2c: Mark OF related data as maybe unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be compile tested with !CONFIG_OF making certain data unused: sound/soc/codecs/src4xxx-i2c.c:27:34: error: ‘src4xxx_of_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230310214333.274903-9-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/src4xxx-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/src4xxx-i2c.c b/sound/soc/codecs/src4xxx-i2c.c index 27026030704a..a40fd20df984 100644 --- a/sound/soc/codecs/src4xxx-i2c.c +++ b/sound/soc/codecs/src4xxx-i2c.c @@ -24,7 +24,7 @@ static const struct i2c_device_id src4xxx_i2c_ids[] = { }; MODULE_DEVICE_TABLE(i2c, src4xxx_i2c_ids); -static const struct of_device_id src4xxx_of_match[] = { +static const struct of_device_id src4xxx_of_match[] __maybe_unused = { { .compatible = "ti,src4392", }, { } }; -- cgit From da1f22825b4fec7e25431fa5238252452f3dce46 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 10 Mar 2023 22:43:33 +0100 Subject: ASoC: codecs: zl38060: Mark OF related data as maybe unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be compile tested with !CONFIG_OF making certain data unused: sound/soc/codecs/zl38060.c:611:34: error: ‘zl38_dt_ids’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230310214333.274903-10-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/zl38060.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/zl38060.c b/sound/soc/codecs/zl38060.c index c3d0a2a7c36f..28c92d90299e 100644 --- a/sound/soc/codecs/zl38060.c +++ b/sound/soc/codecs/zl38060.c @@ -608,7 +608,7 @@ static int zl38_spi_probe(struct spi_device *spi) &zl38_dai, 1); } -static const struct of_device_id zl38_dt_ids[] = { +static const struct of_device_id zl38_dt_ids[] __maybe_unused = { { .compatible = "mscc,zl38060", }, { /* sentinel */ } }; -- cgit From 12e3b2848bfa8197062b7989eefb7c081d372fb8 Mon Sep 17 00:00:00 2001 From: Ajye Huang Date: Sat, 11 Mar 2023 02:42:01 +0800 Subject: ASoC: Intel: sof_rt5682: Enable Bluetooth offload on adl_rt1019_rt5682 Enable Bluetooth audio offload for drv_name "adl_rt1019_rt5682" with following board configuration specifically: SSP0 - rt5682 Headset SSP1 - alc1019p speaker amp SSP2 - Bluetooth audio Signed-off-by: Ajye Huang Signed-off-by: Mac Chiang Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20230310184201.1302232-1-ajye_huang@compal.corp-partner.google.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 4fe448295a90..2eec32846078 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -1109,7 +1109,9 @@ static const struct platform_device_id board_ids[] = { SOF_SPEAKER_AMP_PRESENT | SOF_RT1019_SPEAKER_AMP_PRESENT | SOF_RT5682_SSP_AMP(1) | - SOF_RT5682_NUM_HDMIDEV(4)), + SOF_RT5682_NUM_HDMIDEV(4) | + SOF_BT_OFFLOAD_SSP(2) | + SOF_SSP_BT_OFFLOAD_PRESENT), }, { .name = "mtl_mx98357_rt5682", -- cgit From 3c728b1bc5b99c5275ac5c7788ef814c0e51ef54 Mon Sep 17 00:00:00 2001 From: Eugene Huang Date: Tue, 14 Mar 2023 17:05:52 +0800 Subject: ASOC: Intel: sof_sdw: add quirk for Intel 'Rooks County' NUC M15 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same quirks as the 'Bishop County' NUC M15, except the rt711 is in the 'JD2 100K' jack detection mode. Link: https://github.com/thesofproject/linux/issues/4088 Signed-off-by: Eugene Huang Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230314090553.498664-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index d2ed807abde9..767fa89d0870 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -213,6 +213,17 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { SOF_SDW_PCH_DMIC | RT711_JD1), }, + { + /* NUC15 'Rooks County' LAPRC510 and LAPRC710 skews */ + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"), + DMI_MATCH(DMI_PRODUCT_NAME, "LAPRC"), + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_SDW_PCH_DMIC | + RT711_JD2_100K), + }, /* TigerLake-SDCA devices */ { .callback = sof_sdw_quirk_cb, -- cgit From 9c691a42b8926c8966561265cdae3ddc7464d3a2 Mon Sep 17 00:00:00 2001 From: Eugene Huang Date: Tue, 14 Mar 2023 17:05:53 +0800 Subject: ASoC: Intel: soc-acpi: add table for Intel 'Rooks County' NUC M15 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same topology as the HP Omen 16-k0005TX, except with the rt1316 amp on link2. Link: https://github.com/thesofproject/linux/issues/4088 Signed-off-by: Eugene Huang Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230314090553.498664-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-adl-match.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'sound') diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c index 28dd2046e4ac..d8c80041388a 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -354,6 +354,20 @@ static const struct snd_soc_acpi_link_adr adl_sdw_rt711_link0_rt1316_link3[] = { {} }; +static const struct snd_soc_acpi_link_adr adl_sdw_rt711_link0_rt1316_link2[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), + .adr_d = rt711_sdca_0_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt1316_2_single_adr), + .adr_d = rt1316_2_single_adr, + }, + {} +}; + static const struct snd_soc_acpi_adr_device mx8373_2_adr[] = { { .adr = 0x000223019F837300ull, @@ -624,6 +638,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-adl-rt711-l0-rt1316-l3.tplg", }, + { + .link_mask = 0x5, /* 2 active links required */ + .links = adl_sdw_rt711_link0_rt1316_link2, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-adl-rt711-l0-rt1316-l2.tplg", + }, { .link_mask = 0x1, /* link0 required */ .links = adl_rvp, -- cgit From 083a25b18d6ad9f1f540e629909aa3eaaaf01823 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 9 Mar 2023 15:13:37 +0800 Subject: ASoC: soc-pcm: fix hw->formats cleared by soc_pcm_hw_init() for dpcm The hw->formats may be set by snd_dmaengine_pcm_refine_runtime_hwparams() in component's startup()/open(), but soc_pcm_hw_init() will init hw->formats in dpcm_runtime_setup_fe() after component's startup()/open(), which causes the valuable hw->formats to be cleared. So need to store the hw->formats before initialization, then restore it after initialization. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1678346017-3660-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 5eb056b942ce..7958c9defd49 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1661,10 +1661,14 @@ static void dpcm_runtime_setup_fe(struct snd_pcm_substream *substream) struct snd_pcm_hardware *hw = &runtime->hw; struct snd_soc_dai *dai; int stream = substream->stream; + u64 formats = hw->formats; int i; soc_pcm_hw_init(hw); + if (formats) + hw->formats &= formats; + for_each_rtd_cpu_dais(fe, i, dai) { struct snd_soc_pcm_stream *cpu_stream; -- cgit From f147ca85d6ecaf65106d1650f3c2e8afacbc833f Mon Sep 17 00:00:00 2001 From: "Nícolas F. R. A. Prado via Alsa-devel" Date: Mon, 13 Mar 2023 17:29:06 -0400 Subject: ASoC: mt8192: Remove function name log messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are some log messages in the mt8192 sound code that print the function name, presumably to aid in tracing. However this can also be achieved by ftrace and without spamming the console, so remove these messages. Signed-off-by: Nícolas F. R. A. Prado Link: https://lore.kernel.org/r/167874298172.26.17917791030607314817@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-afe-clk.c | 4 ---- sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 4 ---- sound/soc/mediatek/mt8192/mt8192-dai-tdm.c | 2 -- sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 2 -- 4 files changed, 12 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-clk.c b/sound/soc/mediatek/mt8192/mt8192-afe-clk.c index bba5f3056e8f..416aff726253 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-clk.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-clk.c @@ -206,8 +206,6 @@ int mt8192_afe_enable_clock(struct mtk_base_afe *afe) struct mt8192_afe_private *afe_priv = afe->platform_priv; int ret; - dev_info(afe->dev, "%s()\n", __func__); - ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_SYS_AUDIO]); if (ret) { dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", @@ -276,8 +274,6 @@ void mt8192_afe_disable_clock(struct mtk_base_afe *afe) { struct mt8192_afe_private *afe_priv = afe->platform_priv; - dev_info(afe->dev, "%s()\n", __func__); - clk_disable_unprepare(afe_priv->clk[CLK_AFE]); mt8192_set_audio_int_bus_parent(afe, CLK_CLK26M); clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c index e1e4ca931551..a420b78dde89 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c @@ -2055,8 +2055,6 @@ static int mt8192_afe_runtime_suspend(struct device *dev) unsigned int value; int ret; - dev_info(afe->dev, "%s()\n", __func__); - if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl) goto skip_regmap; @@ -2097,8 +2095,6 @@ static int mt8192_afe_runtime_resume(struct device *dev) struct mt8192_afe_private *afe_priv = afe->platform_priv; int ret; - dev_info(afe->dev, "%s()\n", __func__); - ret = mt8192_afe_enable_clock(afe); if (ret) return ret; diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c index f3bebed2428a..bcd2150c2816 100644 --- a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c +++ b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c @@ -754,8 +754,6 @@ int mt8192_dai_tdm_register(struct mtk_base_afe *afe) struct mtk_afe_tdm_priv *tdm_priv; struct mtk_base_afe_dai *dai; - dev_info(afe->dev, "%s()\n", __func__); - dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); if (!dai) return -ENOMEM; diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index 16660eda577e..87737d054682 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -161,8 +161,6 @@ static int mt8192_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd) int counter; int mtkaif_calib_ok; - dev_info(afe->dev, "%s(), start\n", __func__); - pm_runtime_get_sync(afe->dev); mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA, 1); mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA, 0); -- cgit From 5f2a53c0687b151c2ecad19995108b40df76ba86 Mon Sep 17 00:00:00 2001 From: "Nícolas F. R. A. Prado" Date: Mon, 13 Mar 2023 17:29:07 -0400 Subject: ASoC: mt8192: Move spammy messages to debug level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are many log messages throughout the mt8192 sound drivers that print to the info level and are triggered very frequently. Move these messages to the debug level to avoid spamming the console. Signed-off-by: Nícolas F. R. A. Prado Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20230313212908.2282961-3-nfraprado@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 2 +- sound/soc/mediatek/mt8192/mt8192-dai-tdm.c | 26 +++++++++++----------- .../mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 10 ++++----- 3 files changed, 19 insertions(+), 19 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c index a420b78dde89..333e0ee98c5a 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c @@ -369,7 +369,7 @@ static int ul_tinyconn_event(struct snd_soc_dapm_widget *w, unsigned int reg_shift; unsigned int reg_mask_shift; - dev_info(afe->dev, "%s(), event 0x%x\n", __func__, event); + dev_dbg(afe->dev, "%s(), event 0x%x\n", __func__, event); if (strstr(w->name, "UL1")) { reg_shift = VUL1_USE_TINY_SFT; diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c index bcd2150c2816..9ce06821c7d0 100644 --- a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c +++ b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c @@ -256,8 +256,8 @@ static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w, return -EINVAL; } - dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n", - __func__, w->name, event); + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -288,8 +288,8 @@ static int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget *w, return -EINVAL; } - dev_info(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n", - __func__, w->name, event, dai_id); + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n", + __func__, w->name, event, dai_id); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -320,8 +320,8 @@ static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w, return -EINVAL; } - dev_info(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n", - __func__, w->name, event, dai_id); + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n", + __func__, w->name, event, dai_id); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -545,13 +545,13 @@ static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream, if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0) dev_warn(afe->dev, "%s(), bck cannot generate", __func__); - dev_info(afe->dev, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n", - __func__, - tdm_id, rate, channels, format, - tdm_priv->mclk_rate, tdm_priv->bck_rate); + dev_dbg(afe->dev, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n", + __func__, + tdm_id, rate, channels, format, + tdm_priv->mclk_rate, tdm_priv->bck_rate); - dev_info(afe->dev, "%s(), out_channels_per_sdata = %d\n", - __func__, out_channels_per_sdata); + dev_dbg(afe->dev, "%s(), out_channels_per_sdata = %d\n", + __func__, out_channels_per_sdata); /* set tdm */ if (tdm_priv->bck_invert) @@ -644,7 +644,7 @@ static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai, return -EINVAL; } - dev_info(afe->dev, "%s(), freq %d\n", __func__, freq); + dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq); return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq); } diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index 87737d054682..5e163e23a207 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -292,11 +292,11 @@ static int mt8192_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd) mt8192_afe_gpio_request(afe->dev, false, MT8192_DAI_ADDA_CH34, 0); pm_runtime_put(afe->dev); - dev_info(afe->dev, "%s(), mtkaif_chosen_phase[0/1/2]:%d/%d/%d\n", - __func__, - afe_priv->mtkaif_chosen_phase[0], - afe_priv->mtkaif_chosen_phase[1], - afe_priv->mtkaif_chosen_phase[2]); + dev_dbg(afe->dev, "%s(), mtkaif_chosen_phase[0/1/2]:%d/%d/%d\n", + __func__, + afe_priv->mtkaif_chosen_phase[0], + afe_priv->mtkaif_chosen_phase[1], + afe_priv->mtkaif_chosen_phase[2]); return 0; } -- cgit From 5c5a7521e9364a40fe2c1b67ab79991e3e9085df Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 6 Mar 2023 01:43:30 +0000 Subject: ASoC: soc-dai.c: add missing flag check at snd_soc_pcm_dai_probe() dai->probed is used at snd_soc_pcm_dai_probe/remove(), and used to call real remove() function only when it was probed. int snd_soc_pcm_dai_probe(...) { ... for_each_rtd_dais(rtd, i, dai) { ... if (dai->driver->probe) { (A) int ret = dai->driver->probe(dai); if (ret < 0) return soc_dai_ret(dai, ret); } => dai->probed = 1; } ... } int snd_soc_pcm_dai_remove(...) { ... for_each_rtd_dais(rtd, i, dai) { ... => if (dai->probed && ...) { ... } => dai->probed = 0; } ... } But on probe() case, we need to check dai->probed before calling real probe() function at (A), otherwise real probe() might be called multi times (but real remove() will be called only once). This patch checks it at probe(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87wn3u64e6.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-dai.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 0119afbd01fc..02dd64dea179 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -542,6 +542,9 @@ int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order) if (dai->driver->probe_order != order) continue; + if (dai->probed) + continue; + if (dai->driver->probe) { int ret = dai->driver->probe(dai); -- cgit From 0d3a5178c2994eaf91ad135816a79138055b394a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 6 Mar 2023 01:43:54 +0000 Subject: ASoC: soc-pcm.c: remove indirect runtime copy substream->runtime will be attached when substream was opened at snd_pcm_attach_substream(). When it uses DPCM, FE substream->runtime is attached, but BE substream->runtime is not. Thus, we are copying FE substream->runtime to BE. But, we are copyig FE substream->runtime to FE dpcm->runtime first (A), and copy it to BE dpcm->runtime (B), and copy it to BE substream->runtime (C). static int dpcm_fe_dai_open(...) { ... (A) fe->dpcm[stream].runtime = fe_substream->runtime; ... } static int dpcm_be_connect(...) { ... (B) be->dpcm[stream].runtime = fe->dpcm[stream].runtime; ... } int dpcm_be_dai_startup(...) { ... (C) be_substream->runtime = be->dpcm[stream].runtime; ... } It is too roundabout and troublesome. OTOH, it is directly copying fe_substream->runtime at dpcm_be_reparent() without using be->dpcm[stream].runtime. static void dpcm_be_reparent(...) { ... for_each_dpcm_fe(be, stream, dpcm) { ... => be_substream->runtime = fe_substream->runtime; break; } } This patch removes indirect copying. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87v8je64dh.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 7 ------- sound/soc/soc-pcm.c | 10 ++++------ 2 files changed, 4 insertions(+), 13 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index e7aa6f360cab..554c329ec87f 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -134,8 +134,6 @@ err_no_lock: static int soc_compr_open_fe(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *fe = cstream->private_data; - struct snd_pcm_substream *fe_substream = - fe->pcm->streams[cstream->direction].substream; struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); struct snd_soc_dpcm *dpcm; struct snd_soc_dapm_widget_list *list; @@ -143,7 +141,6 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) int ret; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); - fe->dpcm[stream].runtime = fe_substream->runtime; ret = dpcm_path_get(fe, stream, &list); if (ret < 0) @@ -153,7 +150,6 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) /* calculate valid and active FE <-> BE dpcms */ dpcm_process_paths(fe, stream, &list, 1); - fe->dpcm[stream].runtime = fe_substream->runtime; fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; @@ -164,7 +160,6 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; dpcm_be_disconnect(fe, stream); - fe->dpcm[stream].runtime = NULL; goto out; } @@ -236,8 +231,6 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) mutex_unlock(&fe->card->pcm_mutex); - fe->dpcm[stream].runtime = NULL; - snd_soc_link_compr_shutdown(cstream, 0); snd_soc_compr_components_free(cstream, 0); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 5eb056b942ce..b7f8a5bcfbc6 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1230,7 +1230,6 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, dpcm->be = be; dpcm->fe = fe; - be->dpcm[stream].runtime = fe->dpcm[stream].runtime; dpcm->state = SND_SOC_DPCM_LINK_STATE_NEW; snd_soc_dpcm_stream_lock_irq(fe, stream); list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients); @@ -1465,10 +1464,11 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list *list = *list_; struct snd_soc_pcm_runtime *be; struct snd_soc_dapm_widget *widget; + struct snd_pcm_substream *fe_substream = snd_soc_dpcm_get_substream(fe, stream); int i, new = 0, err; /* don't connect if FE is not running */ - if (!fe->dpcm[stream].runtime && !fe->fe_compr) + if (!fe_substream->runtime && !fe->fe_compr) return new; /* Create any new FE <--> BE connections */ @@ -1590,6 +1590,7 @@ void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream, int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) { + struct snd_pcm_substream *fe_substream = snd_soc_dpcm_get_substream(fe, stream); struct snd_soc_pcm_runtime *be; struct snd_soc_dpcm *dpcm; int err, count = 0; @@ -1629,7 +1630,7 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) dev_dbg(be->dev, "ASoC: open %s BE %s\n", stream ? "capture" : "playback", be->dai_link->name); - be_substream->runtime = be->dpcm[stream].runtime; + be_substream->runtime = fe_substream->runtime; err = __soc_pcm_open(be, be_substream); if (err < 0) { be->dpcm[stream].users--; @@ -2693,8 +2694,6 @@ static void dpcm_fe_dai_cleanup(struct snd_pcm_substream *fe_substream) dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; dpcm_be_disconnect(fe, stream); - - fe->dpcm[stream].runtime = NULL; } static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) @@ -2719,7 +2718,6 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) int stream = fe_substream->stream; snd_soc_dpcm_mutex_lock(fe); - fe->dpcm[stream].runtime = fe_substream->runtime; ret = dpcm_path_get(fe, stream, &list); if (ret < 0) -- cgit From 205efd4619b860404ebb5882e5a119eb3b3b3716 Mon Sep 17 00:00:00 2001 From: Ge-org Brohammer Date: Fri, 17 Mar 2023 00:38:51 +0200 Subject: ASoC: amd: yc: Add DMI entries to support Victus by HP Laptop 16-e1xxx (8A22) This model requires an additional detection quirk to enable the internal microphone. Tried to use git send-email this time. Signed-off-by: Ge-org Brohammer Link: https://lore.kernel.org/r/PAVP195MB2261322C220E95D7F4B2732ADABC9@PAVP195MB2261.EURP195.PROD.OUTLOOK.COM Signed-off-by: Mark Brown --- sound/soc/amd/yc/acp6x-mach.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sound') diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index 4a69ce702360..0acdf0156f07 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -269,6 +269,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_BOARD_NAME, "8A43"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8A22"), + } + }, {} }; -- cgit From 279e52d6b9f366f9930a0f90ee84e7d0a6a27b26 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 16 Mar 2023 16:14:57 +0200 Subject: ASoC: SOF: ipc4-pcm: support multiple configs for BE DAIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backend DAIs may support multiple audio formats. Modify pipeline setup to select a suitable configuration based on topology and frontend DAI runtime configuration. For sampling rate, if one of the BE DAI configurations has a sampling rate matching that of FE DAI, configure BE DAI to this rate. For sample format, the current code hardcodes DAI copier sample format to 32bit for both playback and capture pipelines. This is not always desired, so lift the limitation and set the sample format based on topology definitions for the copiers. For capture pipelines, we want to set the BE DAI pipeline format based on topology instead of using the FE DAI format. This covers the common use-case where BE DAI outputs data at a higher sample precision and sample width is reduced later in the pipeline. Instead of hardcoding to 32bit, use the BE DAI copier output format defined in topology. Signed-off-by: Kai Vehmanen Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230316141458.13940-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-pcm.c | 66 +++++++++++++++++++++++++++++++++----- sound/soc/sof/ipc4-topology.c | 74 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 125 insertions(+), 15 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 701da5ee4e4e..4598057b7f28 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -362,15 +362,68 @@ static void ipc4_ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const } } +/* + * Fixup DAI link parameters for sampling rate based on + * DAI copier configuration. + */ +static int sof_ipc4_pcm_dai_link_fixup_rate(struct snd_sof_dev *sdev, + struct snd_pcm_hw_params *params, + struct sof_ipc4_copier *ipc4_copier) +{ + struct sof_ipc4_pin_format *pin_fmts = ipc4_copier->available_fmt.input_pin_fmts; + struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + int num_input_formats = ipc4_copier->available_fmt.num_input_formats; + unsigned int fe_rate = params_rate(params); + bool fe_be_rate_match = false; + bool single_be_rate = true; + unsigned int be_rate; + int i; + + /* + * Copier does not change sampling rate, so we + * need to only consider the input pin information. + */ + for (i = 0; i < num_input_formats; i++) { + unsigned int val = pin_fmts[i].audio_fmt.sampling_frequency; + + if (i == 0) + be_rate = val; + else if (val != be_rate) + single_be_rate = false; + + if (val == fe_rate) { + fe_be_rate_match = true; + break; + } + } + + /* + * If rate is different than FE rate, topology must + * contain an SRC. But we do require topology to + * define a single rate in the DAI copier config in + * this case (FE rate may be variable). + */ + if (!fe_be_rate_match) { + if (!single_be_rate) { + dev_err(sdev->dev, "Unable to select sampling rate for DAI link\n"); + return -EINVAL; + } + + rate->min = be_rate; + rate->max = rate->min; + } + + return 0; +} + static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); struct snd_sof_dai *dai = snd_sof_find_dai(component, rtd->dai_link->name); - struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct sof_ipc4_copier *ipc4_copier; + int ret; if (!dai) { dev_err(component->dev, "%s: No DAI found with name %s\n", __func__, @@ -385,12 +438,9 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, return -EINVAL; } - /* always set BE format to 32-bits for both playback and capture */ - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); - - rate->min = ipc4_copier->available_fmt.input_pin_fmts->audio_fmt.sampling_frequency; - rate->max = rate->min; + ret = sof_ipc4_pcm_dai_link_fixup_rate(sdev, params, ipc4_copier); + if (ret) + return ret; switch (ipc4_copier->dai_type) { case SOF_DAI_INTEL_SSP: diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index e7b3bdc95dd7..cf438f32b4ed 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1069,6 +1069,69 @@ static int snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_s } #endif +static int ipc4_set_fmt_mask(struct snd_mask *fmt, unsigned int bit_depth) +{ + switch (bit_depth) { + case 16: + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); + break; + case 24: + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); + break; + case 32: + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ipc4_copier_set_capture_fmt(struct snd_sof_dev *sdev, + struct snd_pcm_hw_params *pipeline_params, + struct snd_pcm_hw_params *fe_params, + struct sof_ipc4_available_audio_format *available_fmt) +{ + struct sof_ipc4_audio_format *audio_fmt; + unsigned int sample_valid_bits; + bool multiple_formats = false; + bool fe_format_match = false; + struct snd_mask *fmt; + int i; + + for (i = 0; i < available_fmt->num_output_formats; i++) { + unsigned int val; + + audio_fmt = &available_fmt->output_pin_fmts[i].audio_fmt; + val = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(audio_fmt->fmt_cfg); + + if (i == 0) + sample_valid_bits = val; + else if (sample_valid_bits != val) + multiple_formats = true; + + if (snd_pcm_format_width(params_format(fe_params)) == val) + fe_format_match = true; + } + + fmt = hw_param_mask(pipeline_params, SNDRV_PCM_HW_PARAM_FORMAT); + snd_mask_none(fmt); + + if (multiple_formats) { + if (fe_format_match) { + /* multiple formats defined and one matches FE */ + snd_mask_set_format(fmt, params_format(fe_params)); + return 0; + } + + dev_err(sdev->dev, "Multiple audio formats for single dai_out not supported\n"); + return -EINVAL; + } + + return ipc4_set_fmt_mask(fmt, sample_valid_bits); +} + static int sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, struct snd_pcm_hw_params *fe_params, @@ -1152,13 +1215,10 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, format_list_to_search = available_fmt->output_pin_fmts; format_list_count = available_fmt->num_output_formats; - /* - * modify the input params for the dai copier as it only supports - * 32-bit always - */ - fmt = hw_param_mask(pipeline_params, SNDRV_PCM_HW_PARAM_FORMAT); - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); + ret = ipc4_copier_set_capture_fmt(sdev, pipeline_params, fe_params, + available_fmt); + if (ret < 0) + return ret; } else { format_list_to_search = available_fmt->input_pin_fmts; format_list_count = available_fmt->num_input_formats; -- cgit From 37ec7ab49f951ef8c38102328b84d3dc7155dc68 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 16 Mar 2023 16:14:58 +0200 Subject: ASoC: SOF: ipc4-topology: use common helper function in copier prepare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the ipc4_set_fmt_mask() helper function instead of open-coding the logic in multiple places. Signed-off-by: Kai Vehmanen Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230316141458.13940-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index cf438f32b4ed..4fba8ada9a06 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1363,21 +1363,9 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, out_sample_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(copier_data->out_format.fmt_cfg); snd_mask_none(fmt); - switch (out_sample_valid_bits) { - case 16: - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); - break; - case 24: - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - break; - case 32: - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); - break; - default: - dev_err(sdev->dev, "invalid sample frame format %d\n", - params_format(pipeline_params)); - return -EINVAL; - } + ret = ipc4_set_fmt_mask(fmt, out_sample_valid_bits); + if (ret) + return ret; /* * Set the gateway dma_buffer_size to 2ms buffer size to meet the FW expectation. In the -- cgit From 04b522a4d2acf8447d69bf87b3ab67d5e6d631a2 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 16 Mar 2023 17:11:32 +0200 Subject: ASoC: SOF: ipc4-topology: Move the kcontrol module_id update to helper Introduce a helper function to update the message template for a kcontrol associated with a widget. In this way the helper can be re-used by other components later. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Jaska Uimonen Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20230316151137.7598-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index e7b3bdc95dd7..c00df3956c02 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -320,6 +320,24 @@ static int sof_ipc4_widget_setup_msg(struct snd_sof_widget *swidget, struct sof_ return 0; } +static void sof_ipc4_widget_update_kcontrol_module_id(struct snd_sof_widget *swidget) +{ + struct snd_soc_component *scomp = swidget->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct sof_ipc4_fw_module *fw_module = swidget->module_info; + struct snd_sof_control *scontrol; + + /* update module ID for all kcontrols for this widget */ + list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { + if (scontrol->comp_id == swidget->comp_id) { + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; + struct sof_ipc4_msg *msg = &cdata->msg; + + msg->primary |= fw_module->man4_module_entry.id; + } + } +} + static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) { struct sof_ipc4_available_audio_format *available_fmt; @@ -627,9 +645,6 @@ err: static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget) { struct snd_soc_component *scomp = swidget->scomp; - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - struct sof_ipc4_fw_module *fw_module; - struct snd_sof_control *scontrol; struct sof_ipc4_gain *gain; int ret; @@ -662,16 +677,7 @@ static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget) if (ret) goto err; - fw_module = swidget->module_info; - - /* update module ID for all kcontrols for this widget */ - list_for_each_entry(scontrol, &sdev->kcontrol_list, list) - if (scontrol->comp_id == swidget->comp_id) { - struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; - struct sof_ipc4_msg *msg = &cdata->msg; - - msg->primary |= fw_module->man4_module_entry.id; - } + sof_ipc4_widget_update_kcontrol_module_id(swidget); return 0; err: -- cgit From 7711a2bbc8447dd7185c6da9e405d89ce3ec2f0f Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Thu, 16 Mar 2023 17:11:33 +0200 Subject: ASoC: SOF: ipc4-topology: add effect widget support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the general support of IPC4 effect widgets. IPC4 effect widgets, known as process modules, can be EQFIR, EQIIR, KEYWORD_DETECT, KPB, CHAN_SELECTOR, SMART_AMP and etc. Signed-off-by: Libin Yang Reviewed-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230316151137.7598-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 124 ++++++++++++++++++++++++++++++++++++++++++ sound/soc/sof/ipc4-topology.h | 18 ++++++ 2 files changed, 142 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index c00df3956c02..76bd3487bf71 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -793,6 +793,69 @@ static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget) swidget->private = NULL; } +/* + * Add the process modules support. The process modules are defined as snd_soc_dapm_effect modules. + */ +static int sof_ipc4_widget_setup_comp_process(struct snd_sof_widget *swidget) +{ + struct snd_soc_component *scomp = swidget->scomp; + struct sof_ipc4_process *process; + int cfg_size; + void *cfg; + int ret; + + process = kzalloc(sizeof(*process), GFP_KERNEL); + if (!process) + return -ENOMEM; + + swidget->private = process; + + ret = sof_ipc4_get_audio_fmt(scomp, swidget, &process->available_fmt, + &process->base_config); + if (ret) + goto err; + + cfg_size = sizeof(struct sof_ipc4_base_module_cfg); + + cfg = kzalloc(cfg_size, GFP_KERNEL); + if (!cfg) { + ret = -ENOMEM; + goto free_available_fmt; + } + + process->ipc_config_data = cfg; + process->ipc_config_size = cfg_size; + ret = sof_ipc4_widget_setup_msg(swidget, &process->msg); + if (ret) + goto free_cfg_data; + + sof_ipc4_widget_update_kcontrol_module_id(swidget); + + return 0; +free_cfg_data: + kfree(process->ipc_config_data); + process->ipc_config_data = NULL; +free_available_fmt: + sof_ipc4_free_audio_fmt(&process->available_fmt); +err: + kfree(process); + swidget->private = NULL; + return ret; +} + +static void sof_ipc4_widget_free_comp_process(struct snd_sof_widget *swidget) +{ + struct sof_ipc4_process *process = swidget->private; + + if (!process) + return; + + kfree(process->ipc_config_data); + sof_ipc4_free_audio_fmt(&process->available_fmt); + kfree(swidget->private); + swidget->private = NULL; +} + static void sof_ipc4_update_pipeline_mem_usage(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, struct sof_ipc4_base_module_cfg *base_config) @@ -1454,6 +1517,38 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, return 0; } +static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, + struct snd_pcm_hw_params *fe_params, + struct snd_sof_platform_stream_params *platform_params, + struct snd_pcm_hw_params *pipeline_params, int dir) +{ + struct snd_soc_component *scomp = swidget->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct sof_ipc4_process *process = swidget->private; + struct sof_ipc4_available_audio_format *available_fmt = &process->available_fmt; + void *cfg = process->ipc_config_data; + int ret; + + ret = sof_ipc4_init_audio_fmt(sdev, swidget, &process->base_config, + pipeline_params, available_fmt, + available_fmt->input_pin_fmts, + available_fmt->num_input_formats); + if (ret < 0) + return ret; + + /* update pipeline memory usage */ + sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &process->base_config); + + /* + * ipc_config_data is composed of the base_config, optional output formats followed + * by the data required for module init in that order. + */ + memcpy(cfg, &process->base_config, sizeof(struct sof_ipc4_base_module_cfg)); + cfg += sizeof(struct sof_ipc4_base_module_cfg); + + return 0; +} + static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) { struct sof_ipc4_control_data *control_data; @@ -1652,6 +1747,22 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget msg = &src->msg; break; } + case snd_soc_dapm_effect: + { + struct sof_ipc4_process *process = swidget->private; + + if (!process->ipc_config_size) { + dev_err(sdev->dev, "module %s has no config data!\n", + swidget->widget->name); + return -EINVAL; + } + + ipc_size = process->ipc_config_size; + ipc_data = process->ipc_config_data; + + msg = &process->msg; + break; + } default: dev_err(sdev->dev, "widget type %d not supported", swidget->id); return -EINVAL; @@ -2257,6 +2368,14 @@ static enum sof_tokens src_token_list[] = { SOF_COMP_EXT_TOKENS, }; +static enum sof_tokens process_token_list[] = { + SOF_COMP_TOKENS, + SOF_AUDIO_FMT_NUM_TOKENS, + SOF_IN_AUDIO_FORMAT_TOKENS, + SOF_OUT_AUDIO_FORMAT_TOKENS, + SOF_COMP_EXT_TOKENS, +}; + static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = { [snd_soc_dapm_aif_in] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm, common_copier_token_list, ARRAY_SIZE(common_copier_token_list), @@ -2294,6 +2413,11 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TY src_token_list, ARRAY_SIZE(src_token_list), NULL, sof_ipc4_prepare_src_module, NULL}, + [snd_soc_dapm_effect] = {sof_ipc4_widget_setup_comp_process, + sof_ipc4_widget_free_comp_process, + process_token_list, ARRAY_SIZE(process_token_list), + NULL, sof_ipc4_prepare_process_module, + NULL}, }; const struct sof_ipc_tplg_ops ipc4_tplg_ops = { diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index fad7a628f782..9fcb978ebc63 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -347,4 +347,22 @@ struct sof_ipc4_src { struct sof_ipc4_msg msg; }; +/** + * struct sof_ipc4_process - process config data + * @base_config: IPC base config data + * @output_format: Output audio format + * @available_fmt: Available audio format + * @ipc_config_data: Process module config data + * @ipc_config_size: Size of process module config data + * @msg: IPC4 message struct containing header and data info + */ +struct sof_ipc4_process { + struct sof_ipc4_base_module_cfg base_config; + struct sof_ipc4_audio_format output_format; + struct sof_ipc4_available_audio_format available_fmt; + void *ipc_config_data; + uint32_t ipc_config_size; + struct sof_ipc4_msg msg; +}; + #endif -- cgit From d0be868c5a6e0dafb53d0ee9f0b9d66e40d963f6 Mon Sep 17 00:00:00 2001 From: Chao Song Date: Thu, 16 Mar 2023 17:11:34 +0200 Subject: ASoC: SOF: ipc4-topology: add base module config extension structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The modules currently supported by the SOF firmware use the base module config containing the audio format for the input/output pin 0 for initialization. But some processing modules with multiple input/output pins require the audio formats to be sent with the init instance IPC payload. Modules that require the base config extension will need to indicate this in the module information in the firmware manifest. Introduce a new struct sof_ipc4_base_module_cfg_ext which contains the pin formats for the input and output pins. This will be appended to the init instance IPC payload for modules that require it. Signed-off-by: Chao Song Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230316151137.7598-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 9fcb978ebc63..97264454b8a6 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -347,6 +347,23 @@ struct sof_ipc4_src { struct sof_ipc4_msg msg; }; +/** + * struct sof_ipc4_base_module_cfg_ext - base module config extension containing the pin format + * information for the module. Both @num_input_pin_fmts and @num_output_pin_fmts cannot be 0 for a + * module. + * @num_input_pin_fmts: number of input pin formats in the @pin_formats array + * @num_output_pin_fmts: number of output pin formats in the @pin_formats array + * @reserved: reserved for future use + * @pin_formats: flexible array consisting of @num_input_pin_fmts input pin format items followed + * by @num_output_pin_fmts output pin format items + */ +struct sof_ipc4_base_module_cfg_ext { + u16 num_input_pin_fmts; + u16 num_output_pin_fmts; + u8 reserved[12]; + DECLARE_FLEX_ARRAY(struct sof_ipc4_pin_format, pin_formats); +} __packed; + /** * struct sof_ipc4_process - process config data * @base_config: IPC base config data -- cgit From f9efae954905a07a9d152e9b30546a6632227eef Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 16 Mar 2023 17:11:35 +0200 Subject: ASoC: SOF: ipc4-topology: Add support for base config extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some processing modules need the audio formats for all their input and output pins appended to the base config during module init. So add support for building the base config extension using the available pin formats from topology. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230316151137.7598-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 147 +++++++++++++++++++++++++++++++++++++----- sound/soc/sof/ipc4-topology.h | 10 +++ 2 files changed, 142 insertions(+), 15 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 76bd3487bf71..efd53e855601 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -6,6 +6,7 @@ // Copyright(c) 2022 Intel Corporation. All rights reserved. // // +#include #include #include #include @@ -799,8 +800,8 @@ static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget) static int sof_ipc4_widget_setup_comp_process(struct snd_sof_widget *swidget) { struct snd_soc_component *scomp = swidget->scomp; + struct sof_ipc4_fw_module *fw_module; struct sof_ipc4_process *process; - int cfg_size; void *cfg; int ret; @@ -815,26 +816,50 @@ static int sof_ipc4_widget_setup_comp_process(struct snd_sof_widget *swidget) if (ret) goto err; - cfg_size = sizeof(struct sof_ipc4_base_module_cfg); + ret = sof_ipc4_widget_setup_msg(swidget, &process->msg); + if (ret) + goto err; - cfg = kzalloc(cfg_size, GFP_KERNEL); + /* parse process init module payload config type from module info */ + fw_module = swidget->module_info; + process->init_config = FIELD_GET(SOF_IPC4_MODULE_INIT_CONFIG_MASK, + fw_module->man4_module_entry.type); + + process->ipc_config_size = sizeof(struct sof_ipc4_base_module_cfg); + + /* allocate memory for base config extension if needed */ + if (process->init_config == SOF_IPC4_MODULE_INIT_CONFIG_TYPE_BASE_CFG_WITH_EXT) { + struct sof_ipc4_base_module_cfg_ext *base_cfg_ext; + u32 ext_size = struct_size(base_cfg_ext, pin_formats, + swidget->num_input_pins + swidget->num_output_pins); + + base_cfg_ext = kzalloc(ext_size, GFP_KERNEL); + if (!base_cfg_ext) { + ret = -ENOMEM; + goto free_available_fmt; + } + + base_cfg_ext->num_input_pin_fmts = swidget->num_input_pins; + base_cfg_ext->num_output_pin_fmts = swidget->num_output_pins; + process->base_config_ext = base_cfg_ext; + process->base_config_ext_size = ext_size; + process->ipc_config_size += ext_size; + } + + cfg = kzalloc(process->ipc_config_size, GFP_KERNEL); if (!cfg) { ret = -ENOMEM; - goto free_available_fmt; + goto free_base_cfg_ext; } process->ipc_config_data = cfg; - process->ipc_config_size = cfg_size; - ret = sof_ipc4_widget_setup_msg(swidget, &process->msg); - if (ret) - goto free_cfg_data; sof_ipc4_widget_update_kcontrol_module_id(swidget); return 0; -free_cfg_data: - kfree(process->ipc_config_data); - process->ipc_config_data = NULL; +free_base_cfg_ext: + kfree(process->base_config_ext); + process->base_config_ext = NULL; free_available_fmt: sof_ipc4_free_audio_fmt(&process->available_fmt); err: @@ -851,6 +876,7 @@ static void sof_ipc4_widget_free_comp_process(struct snd_sof_widget *swidget) return; kfree(process->ipc_config_data); + kfree(process->base_config_ext); sof_ipc4_free_audio_fmt(&process->available_fmt); kfree(swidget->private); swidget->private = NULL; @@ -1517,6 +1543,84 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, return 0; } +static int +sof_ipc4_process_set_pin_formats(struct snd_sof_widget *swidget, int pin_type) +{ + struct sof_ipc4_process *process = swidget->private; + struct sof_ipc4_base_module_cfg_ext *base_cfg_ext = process->base_config_ext; + struct sof_ipc4_available_audio_format *available_fmt = &process->available_fmt; + struct sof_ipc4_pin_format *pin_format, *format_list_to_search; + struct snd_soc_component *scomp = swidget->scomp; + int num_pins, format_list_count; + int pin_format_offset = 0; + int i, j; + + /* set number of pins, offset of pin format and format list to search based on pin type */ + if (pin_type == SOF_PIN_TYPE_INPUT) { + num_pins = swidget->num_input_pins; + format_list_to_search = available_fmt->input_pin_fmts; + format_list_count = available_fmt->num_input_formats; + } else { + num_pins = swidget->num_output_pins; + pin_format_offset = swidget->num_input_pins; + format_list_to_search = available_fmt->output_pin_fmts; + format_list_count = available_fmt->num_output_formats; + } + + for (i = pin_format_offset; i < num_pins + pin_format_offset; i++) { + pin_format = &base_cfg_ext->pin_formats[i]; + + /* Pin 0 audio formats are derived from the base config input/output format */ + if (i == pin_format_offset) { + if (pin_type == SOF_PIN_TYPE_INPUT) { + pin_format->buffer_size = process->base_config.ibs; + pin_format->audio_fmt = process->base_config.audio_fmt; + } else { + pin_format->buffer_size = process->base_config.obs; + pin_format->audio_fmt = process->output_format; + } + continue; + } + + /* + * For all other pins, find the pin formats from those set in topology. If there + * is more than one format specified for a pin, this will pick the first available + * one. + */ + for (j = 0; j < format_list_count; j++) { + struct sof_ipc4_pin_format *pin_format_item = &format_list_to_search[j]; + + if (pin_format_item->pin_index == i - pin_format_offset) { + *pin_format = *pin_format_item; + break; + } + } + + if (j == format_list_count) { + dev_err(scomp->dev, "%s pin %d format not found for %s\n", + (pin_type == SOF_PIN_TYPE_INPUT) ? "input" : "output", + i - pin_format_offset, swidget->widget->name); + return -EINVAL; + } + } + + return 0; +} + +static int sof_ipc4_process_add_base_cfg_extn(struct snd_sof_widget *swidget) +{ + int ret, i; + + /* copy input and output pin formats */ + for (i = 0; i <= SOF_PIN_TYPE_OUTPUT; i++) { + ret = sof_ipc4_process_set_pin_formats(swidget, i); + if (ret < 0) + return ret; + } + + return 0; +} + static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, struct snd_pcm_hw_params *fe_params, struct snd_sof_platform_stream_params *platform_params, @@ -1536,16 +1640,29 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, if (ret < 0) return ret; + /* copy Pin 0 output format */ + if (available_fmt->num_output_formats && ret < available_fmt->num_output_formats && + !available_fmt->output_pin_fmts[ret].pin_index) + memcpy(&process->output_format, &available_fmt->output_pin_fmts[ret].audio_fmt, + sizeof(struct sof_ipc4_audio_format)); + /* update pipeline memory usage */ sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &process->base_config); - /* - * ipc_config_data is composed of the base_config, optional output formats followed - * by the data required for module init in that order. - */ + /* ipc_config_data is composed of the base_config followed by an optional extension */ memcpy(cfg, &process->base_config, sizeof(struct sof_ipc4_base_module_cfg)); cfg += sizeof(struct sof_ipc4_base_module_cfg); + if (process->init_config == SOF_IPC4_MODULE_INIT_CONFIG_TYPE_BASE_CFG_WITH_EXT) { + struct sof_ipc4_base_module_cfg_ext *base_cfg_ext = process->base_config_ext; + + ret = sof_ipc4_process_add_base_cfg_extn(swidget); + if (ret < 0) + return ret; + + memcpy(cfg, base_cfg_ext, process->base_config_ext_size); + } + return 0; } diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 97264454b8a6..015027b23588 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -26,6 +26,10 @@ #define SOF_IPC4_MODULE_LL BIT(5) #define SOF_IPC4_MODULE_DP BIT(6) #define SOF_IPC4_MODULE_LIB_CODE BIT(7) +#define SOF_IPC4_MODULE_INIT_CONFIG_MASK GENMASK(11, 8) + +#define SOF_IPC4_MODULE_INIT_CONFIG_TYPE_BASE_CFG 0 +#define SOF_IPC4_MODULE_INIT_CONFIG_TYPE_BASE_CFG_WITH_EXT 1 #define SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE 12 #define SOF_IPC4_PIPELINE_OBJECT_SIZE 448 @@ -367,19 +371,25 @@ struct sof_ipc4_base_module_cfg_ext { /** * struct sof_ipc4_process - process config data * @base_config: IPC base config data + * @base_config_ext: Base config extension data for module init * @output_format: Output audio format * @available_fmt: Available audio format * @ipc_config_data: Process module config data * @ipc_config_size: Size of process module config data * @msg: IPC4 message struct containing header and data info + * @base_config_ext_size: Size of the base config extension data in bytes + * @init_config: Module init config type (SOF_IPC4_MODULE_INIT_CONFIG_TYPE_*) */ struct sof_ipc4_process { struct sof_ipc4_base_module_cfg base_config; + struct sof_ipc4_base_module_cfg_ext *base_config_ext; struct sof_ipc4_audio_format output_format; struct sof_ipc4_available_audio_format available_fmt; void *ipc_config_data; uint32_t ipc_config_size; struct sof_ipc4_msg msg; + u32 base_config_ext_size; + u32 init_config; }; #endif -- cgit From 648fea12847695d60ddeebea86597114885ee76e Mon Sep 17 00:00:00 2001 From: Chao Song Date: Thu, 16 Mar 2023 17:11:36 +0200 Subject: ASoC: SOF: ipc4-topology: set copier output format for process module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The copier output pin 0 format is set with module instance initialization, format for additional copier output pin should be set before the pin is used. If a process module is connected to additional copier output pin, the copier output pin format should be set according to the corresponding input pin format of the process module. Signed-off-by: Chao Song Co-developed-by: Ranjani Sridharan Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230316151137.7598-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 46 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index efd53e855601..962ec38b70cc 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -166,6 +166,37 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_fo } } +static const struct sof_ipc4_audio_format * +sof_ipc4_get_input_pin_audio_fmt(struct snd_sof_widget *swidget, int pin_index) +{ + struct sof_ipc4_base_module_cfg_ext *base_cfg_ext; + struct sof_ipc4_process *process; + int i; + + if (swidget->id != snd_soc_dapm_effect) { + struct sof_ipc4_base_module_cfg *base = swidget->private; + + /* For non-process modules, base module config format is used for all input pins */ + return &base->audio_fmt; + } + + process = swidget->private; + base_cfg_ext = process->base_config_ext; + + /* + * If there are multiple input formats available for a pin, the first available format + * is chosen. + */ + for (i = 0; i < base_cfg_ext->num_input_pin_fmts; i++) { + struct sof_ipc4_pin_format *pin_format = &base_cfg_ext->pin_formats[i]; + + if (pin_format->pin_index == pin_index) + return &pin_format->audio_fmt; + } + + return NULL; +} + /** * sof_ipc4_get_audio_fmt - get available audio formats from swidget->tuples * @scomp: pointer to pointer to SOC component @@ -2049,9 +2080,9 @@ static int sof_ipc4_set_copier_sink_format(struct snd_sof_dev *sdev, struct snd_sof_widget *sink_widget, int sink_id) { - struct sof_ipc4_base_module_cfg *sink_config = sink_widget->private; - struct sof_ipc4_base_module_cfg *src_config; struct sof_ipc4_copier_config_set_sink_format format; + struct sof_ipc4_base_module_cfg *src_config; + const struct sof_ipc4_audio_format *pin_fmt; struct sof_ipc4_fw_module *fw_module; struct sof_ipc4_msg msg = {{ 0 }}; u32 header, extension; @@ -2071,7 +2102,16 @@ static int sof_ipc4_set_copier_sink_format(struct snd_sof_dev *sdev, format.sink_id = sink_id; memcpy(&format.source_fmt, &src_config->audio_fmt, sizeof(format.source_fmt)); - memcpy(&format.sink_fmt, &sink_config->audio_fmt, sizeof(format.sink_fmt)); + + pin_fmt = sof_ipc4_get_input_pin_audio_fmt(sink_widget, sink_id); + if (!pin_fmt) { + dev_err(sdev->dev, "Unable to get pin %d format for %s", + sink_id, sink_widget->widget->name); + return -EINVAL; + } + + memcpy(&format.sink_fmt, pin_fmt, sizeof(format.sink_fmt)); + msg.data_size = sizeof(format); msg.data_ptr = &format; -- cgit From 811a742f2d4d1b0aee686bc2f4282b51534898a2 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Thu, 16 Mar 2023 17:11:37 +0200 Subject: ASoC: SOF: ipc4-topology: update pipeline_params in process prepare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some modules may modify the audio format during processing. So, update the pipeline params based on pin 0's output format during process prepare. Signed-off-by: Libin Yang Co-developed-by: Ranjani Sridharan Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Chao Song Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230316151137.7598-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 50 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 962ec38b70cc..963ec730381b 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -964,6 +964,48 @@ static int sof_ipc4_widget_assign_instance_id(struct snd_sof_dev *sdev, return 0; } +/* update hw_params based on the audio stream format */ +static int sof_ipc4_update_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params, + struct sof_ipc4_audio_format *fmt) +{ + snd_pcm_format_t snd_fmt; + struct snd_interval *i; + struct snd_mask *m; + int valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); + unsigned int channels, rate; + + switch (valid_bits) { + case 16: + snd_fmt = SNDRV_PCM_FORMAT_S16_LE; + break; + case 24: + snd_fmt = SNDRV_PCM_FORMAT_S24_LE; + break; + case 32: + snd_fmt = SNDRV_PCM_FORMAT_S32_LE; + break; + default: + dev_err(sdev->dev, "invalid PCM valid_bits %d\n", valid_bits); + return -EINVAL; + } + + m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + snd_mask_none(m); + snd_mask_set_format(m, snd_fmt); + + rate = fmt->sampling_frequency; + i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + i->min = rate; + i->max = rate; + + channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); + i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + i->min = channels; + i->max = channels; + + return 0; +} + static int sof_ipc4_init_audio_fmt(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, struct sof_ipc4_base_module_cfg *base_config, @@ -1673,10 +1715,16 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, /* copy Pin 0 output format */ if (available_fmt->num_output_formats && ret < available_fmt->num_output_formats && - !available_fmt->output_pin_fmts[ret].pin_index) + !available_fmt->output_pin_fmts[ret].pin_index) { memcpy(&process->output_format, &available_fmt->output_pin_fmts[ret].audio_fmt, sizeof(struct sof_ipc4_audio_format)); + /* modify the pipeline params with the pin 0 output format */ + ret = sof_ipc4_update_hw_params(sdev, pipeline_params, &process->output_format); + if (ret) + return ret; + } + /* update pipeline memory usage */ sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &process->base_config); -- cgit From ef51cd1ebab63bb92bfef050fbf12b2265f5c7a5 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 17 Mar 2023 08:35:24 +0200 Subject: ASoC: SOF: ipc4-topology: Initialize in_format to NULL in sof_ipc4_get_audio_fmt If the available_fmt->num_input_formats is 0 and there is a failure during the output format parsing then a kfree() would be called on the uninitialized in_format pointer. By initializing the in_format to NULL, this error can be avoided. Fixes: 7ab6b1e8302c ("ASoC: SOF: ipc4-topology: Modify the type of available input/output formats") Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230317063524.8280-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index e7b3bdc95dd7..2a2c4cda63fd 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -179,7 +179,8 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, struct sof_ipc4_available_audio_format *available_fmt, struct sof_ipc4_base_module_cfg *module_base_cfg) { - struct sof_ipc4_pin_format *out_format, *in_format; + struct sof_ipc4_pin_format *in_format = NULL; + struct sof_ipc4_pin_format *out_format; int ret; ret = sof_update_ipc_object(scomp, available_fmt, -- cgit From eb0b8481c2e03a5ae01f6bea60b42109bd12b6fe Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Wed, 8 Mar 2023 09:34:56 +0200 Subject: ASoC: tegra: Support coupled mic-hp detection This quirk is used for cases when there is GPIO which detects any type of 3.5 Jack insertion and actual type of jack is defined by other GPIO. 3.5 Jack GPIO generates interrupt and MIC GPIO indicates type of Jack only if 3.5 Jack GPIO is active. Signed-off-by: Svyatoslav Ryhel Link: https://lore.kernel.org/r/20230308073502.5421-3-clamor95@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_asoc_machine.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'sound') diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c index 2dc1f44c5a8b..84a719ecae7f 100644 --- a/sound/soc/tegra/tegra_asoc_machine.c +++ b/sound/soc/tegra/tegra_asoc_machine.c @@ -51,6 +51,17 @@ static struct snd_soc_jack_gpio tegra_machine_headset_jack_gpio = { }; /* Mic Jack */ +static int coupled_mic_hp_check(void *data) +{ + struct tegra_machine *machine = (struct tegra_machine *)data; + + /* Detect mic insertion only if 3.5 jack is in */ + if (gpiod_get_value_cansleep(machine->gpiod_hp_det) && + gpiod_get_value_cansleep(machine->gpiod_mic_det)) + return SND_JACK_MICROPHONE; + + return 0; +} static struct snd_soc_jack tegra_machine_mic_jack; @@ -183,8 +194,15 @@ int tegra_asoc_machine_init(struct snd_soc_pcm_runtime *rtd) return err; } + tegra_machine_mic_jack_gpio.data = machine; tegra_machine_mic_jack_gpio.desc = machine->gpiod_mic_det; + if (of_property_read_bool(card->dev->of_node, + "nvidia,coupled-mic-hp-det")) { + tegra_machine_mic_jack_gpio.desc = machine->gpiod_hp_det; + tegra_machine_mic_jack_gpio.jack_status_check = coupled_mic_hp_check; + }; + err = snd_soc_jack_add_gpios(&tegra_machine_mic_jack, 1, &tegra_machine_mic_jack_gpio); if (err) -- cgit From 44b2fc2edb61e956885b4305bddaaec7f05d93d2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Wed, 8 Mar 2023 09:34:59 +0200 Subject: ASoC: tegra: Support RT5631 by machine driver Add Realtek ALC5631/RT5631 codec support to the Tegra ASoC machine driver. The RT5631 codec is found on devices like ASUS Transformer TF201, TF700T and other Tegra-based Android tablets. Signed-off-by: Ion Agorria Signed-off-by: Svyatoslav Ryhel Link: https://lore.kernel.org/r/20230308073502.5421-6-clamor95@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/Kconfig | 9 ++++++ sound/soc/tegra/tegra_asoc_machine.c | 61 ++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) (limited to 'sound') diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 73a683d45526..dba70c7af150 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -189,6 +189,15 @@ config SND_SOC_TEGRA_AUDIO_GRAPH_CARD config SND_SOC_TEGRA_MACHINE_DRV tristate +config SND_SOC_TEGRA_RT5631 + tristate "SoC Audio support for Tegra boards using an RT5631 codec" + depends on SND_SOC_TEGRA && I2C && GPIOLIB + select SND_SOC_TEGRA_MACHINE_DRV + select SND_SOC_RT5631 + help + Say Y or M here if you want to add support for SoC audio on Tegra + boards using the RT5631 codec, such as Transformer. + config SND_SOC_TEGRA_RT5640 tristate "SoC Audio support for Tegra boards using an RT5640 codec" depends on I2C && GPIOLIB diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c index 84a719ecae7f..b8cf5ab74acf 100644 --- a/sound/soc/tegra/tegra_asoc_machine.c +++ b/sound/soc/tegra/tegra_asoc_machine.c @@ -256,6 +256,32 @@ static unsigned int tegra_machine_mclk_rate_12mhz(unsigned int srate) return mclk; } +static unsigned int tegra_machine_mclk_rate_6mhz(unsigned int srate) +{ + unsigned int mclk; + + switch (srate) { + case 8000: + case 16000: + case 64000: + mclk = 8192000; + break; + case 11025: + case 22050: + case 88200: + mclk = 11289600; + break; + case 96000: + mclk = 12288000; + break; + default: + mclk = 256 * srate; + break; + } + + return mclk; +} + static int tegra_machine_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -883,6 +909,40 @@ static const struct tegra_asoc_data tegra_rt5632_data = { .add_headset_jack = true, }; +/* RT5631 machine */ + +SND_SOC_DAILINK_DEFS(rt5631_hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5631-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +static struct snd_soc_dai_link tegra_rt5631_dai = { + .name = "RT5631", + .stream_name = "RT5631 PCM", + .init = tegra_asoc_machine_init, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(rt5631_hifi), +}; + +static struct snd_soc_card snd_soc_tegra_rt5631 = { + .components = "codec:rt5631", + .dai_link = &tegra_rt5631_dai, + .num_links = 1, + .fully_routed = true, +}; + +static const struct tegra_asoc_data tegra_rt5631_data = { + .mclk_rate = tegra_machine_mclk_rate_6mhz, + .card = &snd_soc_tegra_rt5631, + .add_common_dapm_widgets = true, + .add_common_controls = true, + .add_common_snd_ops = true, + .add_mic_jack = true, + .add_hp_jack = true, +}; + static const struct of_device_id tegra_machine_of_match[] = { { .compatible = "nvidia,tegra-audio-trimslice", .data = &tegra_trimslice_data }, { .compatible = "nvidia,tegra-audio-max98090", .data = &tegra_max98090_data }, @@ -892,6 +952,7 @@ static const struct of_device_id tegra_machine_of_match[] = { { .compatible = "nvidia,tegra-audio-rt5677", .data = &tegra_rt5677_data }, { .compatible = "nvidia,tegra-audio-rt5640", .data = &tegra_rt5640_data }, { .compatible = "nvidia,tegra-audio-alc5632", .data = &tegra_rt5632_data }, + { .compatible = "nvidia,tegra-audio-rt5631", .data = &tegra_rt5631_data }, {}, }; MODULE_DEVICE_TABLE(of, tegra_machine_of_match); -- cgit From d007a87bd7d181854b53b3e7fcbcf66c4bef86b2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Wed, 8 Mar 2023 09:35:02 +0200 Subject: ASoC: tegra: Support MAX9808x by machine driver Add Maxim MAX9808x codec support to the Tegra ASoC machine driver. This codec is found on LG T30 devices like Optimus 4X HD and Optimus Vu. Signed-off-by: Svyatoslav Ryhel Link: https://lore.kernel.org/r/20230308073502.5421-9-clamor95@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/Kconfig | 9 +++++++ sound/soc/tegra/tegra_asoc_machine.c | 46 ++++++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index dba70c7af150..74effc57a7a0 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -263,6 +263,15 @@ config SND_SOC_TEGRA_MAX98090 Say Y or M here if you want to add support for SoC audio on Tegra boards using the MAX98090 codec, such as Venice2. +config SND_SOC_TEGRA_MAX98088 + tristate "SoC Audio support for Tegra boards using a MAX9808x codec" + depends on I2C && GPIOLIB + select SND_SOC_TEGRA_MACHINE_DRV + select SND_SOC_MAX98088 + help + Say Y or M here if you want to add support for SoC audio on Tegra + boards using the MAX98088 codec, such as LG X3. + config SND_SOC_TEGRA_RT5677 tristate "SoC Audio support for Tegra boards using a RT5677 codec" depends on I2C && GPIOLIB diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c index b8cf5ab74acf..c2aaa496468c 100644 --- a/sound/soc/tegra/tegra_asoc_machine.c +++ b/sound/soc/tegra/tegra_asoc_machine.c @@ -86,11 +86,11 @@ static int tegra_machine_event(struct snd_soc_dapm_widget *w, gpiod_set_value_cansleep(machine->gpiod_spkr_en, SND_SOC_DAPM_EVENT_ON(event)); - if (!strcmp(w->name, "Mic Jack")) + if (!strcmp(w->name, "Mic Jack") || !strcmp(w->name, "Headset Mic")) gpiod_set_value_cansleep(machine->gpiod_ext_mic_en, SND_SOC_DAPM_EVENT_ON(event)); - if (!strcmp(w->name, "Int Mic")) + if (!strcmp(w->name, "Int Mic") || !strcmp(w->name, "Internal Mic 2")) gpiod_set_value_cansleep(machine->gpiod_int_mic_en, SND_SOC_DAPM_EVENT_ON(event)); @@ -108,11 +108,12 @@ static const struct snd_soc_dapm_widget tegra_machine_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphones", NULL), SND_SOC_DAPM_SPK("Speakers", tegra_machine_event), SND_SOC_DAPM_SPK("Int Spk", tegra_machine_event), + SND_SOC_DAPM_SPK("Earpiece", NULL), SND_SOC_DAPM_MIC("Int Mic", tegra_machine_event), SND_SOC_DAPM_MIC("Mic Jack", tegra_machine_event), SND_SOC_DAPM_MIC("Internal Mic 1", NULL), - SND_SOC_DAPM_MIC("Internal Mic 2", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Internal Mic 2", tegra_machine_event), + SND_SOC_DAPM_MIC("Headset Mic", tegra_machine_event), SND_SOC_DAPM_MIC("Digital Mic", NULL), SND_SOC_DAPM_MIC("Mic", NULL), SND_SOC_DAPM_LINE("Line In Jack", NULL), @@ -123,6 +124,7 @@ static const struct snd_soc_dapm_widget tegra_machine_dapm_widgets[] = { static const struct snd_kcontrol_new tegra_machine_controls[] = { SOC_DAPM_PIN_SWITCH("Speakers"), SOC_DAPM_PIN_SWITCH("Int Spk"), + SOC_DAPM_PIN_SWITCH("Earpiece"), SOC_DAPM_PIN_SWITCH("Int Mic"), SOC_DAPM_PIN_SWITCH("Headset Mic"), SOC_DAPM_PIN_SWITCH("Internal Mic 1"), @@ -718,6 +720,40 @@ static const struct tegra_asoc_data tegra_max98090_data = { .add_hp_jack = true, }; +/* MAX98088 machine */ + +SND_SOC_DAILINK_DEFS(max98088_hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +static struct snd_soc_dai_link tegra_max98088_dai = { + .name = "MAX98088", + .stream_name = "MAX98088 PCM", + .init = tegra_asoc_machine_init, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(max98088_hifi), +}; + +static struct snd_soc_card snd_soc_tegra_max98088 = { + .components = "codec:max98088", + .dai_link = &tegra_max98088_dai, + .num_links = 1, + .fully_routed = true, +}; + +static const struct tegra_asoc_data tegra_max98088_data = { + .mclk_rate = tegra_machine_mclk_rate_12mhz, + .card = &snd_soc_tegra_max98088, + .add_common_dapm_widgets = true, + .add_common_controls = true, + .add_common_snd_ops = true, + .add_mic_jack = true, + .add_hp_jack = true, +}; + /* SGTL5000 machine */ SND_SOC_DAILINK_DEFS(sgtl5000_hifi, @@ -946,6 +982,8 @@ static const struct tegra_asoc_data tegra_rt5631_data = { static const struct of_device_id tegra_machine_of_match[] = { { .compatible = "nvidia,tegra-audio-trimslice", .data = &tegra_trimslice_data }, { .compatible = "nvidia,tegra-audio-max98090", .data = &tegra_max98090_data }, + { .compatible = "nvidia,tegra-audio-max98088", .data = &tegra_max98088_data }, + { .compatible = "nvidia,tegra-audio-max98089", .data = &tegra_max98088_data }, { .compatible = "nvidia,tegra-audio-sgtl5000", .data = &tegra_sgtl5000_data }, { .compatible = "nvidia,tegra-audio-wm9712", .data = &tegra_wm9712_data }, { .compatible = "nvidia,tegra-audio-wm8753", .data = &tegra_wm8753_data }, -- cgit From e3a8459d726532be70fa917e39812570618b857e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:04:53 +0100 Subject: ALSA: sh: aica: Drop if blocks with always false condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit snd_aica_remove() is only called after a successful call to snd_aica_probe(). With the latter it's sure that platform_set_drvdata() was called with a non-NULL argument. So platform_get_drvdata() won't return NULL and the check can be dropped. This prepares converting platform driver remove callbacks to return void. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-2-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/sh/aica.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound') diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 6e9d6bd67369..459c907655d9 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c @@ -543,8 +543,6 @@ static int snd_aica_remove(struct platform_device *devptr) { struct snd_card_aica *dreamcastcard; dreamcastcard = platform_get_drvdata(devptr); - if (unlikely(!dreamcastcard)) - return -ENODEV; snd_card_free(dreamcastcard->card); kfree(dreamcastcard); return 0; -- cgit From 9ac0d69ee5891c2d0f0425acbb13993ceef9cd12 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:04:54 +0100 Subject: ASoC: amd: acp: rembrandt: Drop if blocks with always false condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rembrandt_audio_remove() is only called after a successful call to rembrandt_audio_probe(). With the latter it's sure that dev_get_platdata() returns a non-NULL value and also that ->base is non-NULL. So the corresponding check can be dropped. While touching these lines join declaration and assignment into a single line and make use of dev = &pdev->dev; This prepares converting platform driver remove callbacks to return void. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-3-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-rembrandt.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index 2b57c0ca4e99..15cd3f8cc82c 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -370,13 +370,7 @@ static int rembrandt_audio_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct acp_dev_data *adata = dev_get_drvdata(dev); - struct acp_chip_info *chip; - - chip = dev_get_platdata(&pdev->dev); - if (!chip || !chip->base) { - dev_err(&pdev->dev, "ACP chip data is NULL\n"); - return -ENODEV; - } + struct acp_chip_info *chip = dev_get_platdata(dev); rmb_acp_deinit(chip->base); -- cgit From 3210e62ab2f63b3ecdacc2c06ca8c8a91d1bf656 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:04:55 +0100 Subject: ALSA: pxa2xx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-4-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/arm/pxa2xx-ac97.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index c162086455ad..2d83ad91f968 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -262,7 +262,7 @@ err_dev: return ret; } -static int pxa2xx_ac97_remove(struct platform_device *dev) +static void pxa2xx_ac97_remove(struct platform_device *dev) { struct snd_card *card = platform_get_drvdata(dev); @@ -270,13 +270,11 @@ static int pxa2xx_ac97_remove(struct platform_device *dev) snd_card_free(card); pxa2xx_ac97_hw_remove(dev); } - - return 0; } static struct platform_driver pxa2xx_ac97_driver = { .probe = pxa2xx_ac97_probe, - .remove = pxa2xx_ac97_remove, + .remove_new = pxa2xx_ac97_remove, .driver = { .name = "pxa2xx-ac97", #ifdef CONFIG_PM_SLEEP -- cgit From 45cc35e81322117dfc27fbfded2e0263018175a0 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:04:56 +0100 Subject: ALSA: atmel: ac97: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-5-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/atmel/ac97c.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 66ecbd4d034e..c8912b8a1dc5 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -843,7 +843,7 @@ static SIMPLE_DEV_PM_OPS(atmel_ac97c_pm, atmel_ac97c_suspend, atmel_ac97c_resume #define ATMEL_AC97C_PM_OPS NULL #endif -static int atmel_ac97c_remove(struct platform_device *pdev) +static void atmel_ac97c_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); struct atmel_ac97c *chip = get_chip(card); @@ -858,13 +858,11 @@ static int atmel_ac97c_remove(struct platform_device *pdev) free_irq(chip->irq, chip); snd_card_free(card); - - return 0; } static struct platform_driver atmel_ac97c_driver = { .probe = atmel_ac97c_probe, - .remove = atmel_ac97c_remove, + .remove_new = atmel_ac97c_remove, .driver = { .name = "atmel_ac97c", .pm = ATMEL_AC97C_PM_OPS, -- cgit From 5909d9e5b6c927ea91ace61365049a2f365a7d7e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:04:57 +0100 Subject: ALSA: mts64: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-6-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/drivers/mts64.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index f0d34cf70c3e..5cfd0e99a13f 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c @@ -999,19 +999,17 @@ __err: return err; } -static int snd_mts64_remove(struct platform_device *pdev) +static void snd_mts64_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); if (card) snd_card_free(card); - - return 0; } static struct platform_driver snd_mts64_driver = { .probe = snd_mts64_probe, - .remove = snd_mts64_remove, + .remove_new = snd_mts64_remove, .driver = { .name = PLATFORM_DRIVER, } -- cgit From 962bdc9645036b1300c4930e147b5e9a0c587c81 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:04:58 +0100 Subject: ALSA: portman2x4: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-7-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/drivers/portman2x4.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index 52a656735365..a515c13a489f 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c @@ -795,20 +795,18 @@ __err: return err; } -static int snd_portman_remove(struct platform_device *pdev) +static void snd_portman_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); if (card) snd_card_free(card); - - return 0; } static struct platform_driver snd_portman_driver = { .probe = snd_portman_probe, - .remove = snd_portman_remove, + .remove_new = snd_portman_remove, .driver = { .name = PLATFORM_DRIVER, } -- cgit From b54a2377ec02d52b7bb5dab381e9a45ba0bc617a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:04:59 +0100 Subject: ALSA: mips/hal2: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-8-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/mips/hal2.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c index 9ac9b58d7c8c..3c26334227bb 100644 --- a/sound/mips/hal2.c +++ b/sound/mips/hal2.c @@ -877,17 +877,16 @@ static int hal2_probe(struct platform_device *pdev) return 0; } -static int hal2_remove(struct platform_device *pdev) +static void hal2_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); snd_card_free(card); - return 0; } static struct platform_driver hal2_driver = { .probe = hal2_probe, - .remove = hal2_remove, + .remove_new = hal2_remove, .driver = { .name = "sgihal2", } -- cgit From 0505c87c00e8e0adb64c9cfb97ea4882899bea3e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:00 +0100 Subject: ALSA: mips/sgio2audio: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-9-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/mips/sgio2audio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index 989f656e2de7..a8551ccdd1bf 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -908,17 +908,16 @@ static int snd_sgio2audio_probe(struct platform_device *pdev) return 0; } -static int snd_sgio2audio_remove(struct platform_device *pdev) +static void snd_sgio2audio_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); snd_card_free(card); - return 0; } static struct platform_driver sgio2audio_driver = { .probe = snd_sgio2audio_probe, - .remove = snd_sgio2audio_remove, + .remove_new = snd_sgio2audio_remove, .driver = { .name = "sgio2audio", } -- cgit From d8a3441b53682883c16d6997d059e1cc2ac739c8 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:01 +0100 Subject: ALSA: hda/tegra: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-10-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/pci/hda/hda_tegra.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index c2bf86781894..9d0ab043880b 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -580,12 +580,10 @@ static void hda_tegra_probe_work(struct work_struct *work) return; /* no error return from async probe */ } -static int hda_tegra_remove(struct platform_device *pdev) +static void hda_tegra_remove(struct platform_device *pdev) { snd_card_free(dev_get_drvdata(&pdev->dev)); pm_runtime_disable(&pdev->dev); - - return 0; } static void hda_tegra_shutdown(struct platform_device *pdev) @@ -607,7 +605,7 @@ static struct platform_driver tegra_platform_hda = { .of_match_table = hda_tegra_match, }, .probe = hda_tegra_probe, - .remove = hda_tegra_remove, + .remove_new = hda_tegra_remove, .shutdown = hda_tegra_shutdown, }; module_platform_driver(tegra_platform_hda); -- cgit From c3d8cb1929fc64e8c3d14f27e9540e72aee8ed08 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:02 +0100 Subject: ALSA: ppc/powermac: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-11-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/ppc/powermac.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index db414b61157e..e17af46abddd 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c @@ -130,10 +130,9 @@ __error: } -static int snd_pmac_remove(struct platform_device *devptr) +static void snd_pmac_remove(struct platform_device *devptr) { snd_card_free(platform_get_drvdata(devptr)); - return 0; } #ifdef CONFIG_PM_SLEEP @@ -161,7 +160,7 @@ static SIMPLE_DEV_PM_OPS(snd_pmac_pm, snd_pmac_driver_suspend, snd_pmac_driver_r static struct platform_driver snd_pmac_driver = { .probe = snd_pmac_probe, - .remove = snd_pmac_remove, + .remove_new = snd_pmac_remove, .driver = { .name = SND_PMAC_DRIVER, .pm = SND_PMAC_PM_OPS, -- cgit From de0f49b86d12384e8f3ddf7dc651a93c2c0c551b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:03 +0100 Subject: ALSA: sh: aica: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-12-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/sh/aica.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 459c907655d9..320ac792c7fe 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c @@ -539,13 +539,12 @@ static int add_aicamixer_controls(struct snd_card_aica *dreamcastcard) return 0; } -static int snd_aica_remove(struct platform_device *devptr) +static void snd_aica_remove(struct platform_device *devptr) { struct snd_card_aica *dreamcastcard; dreamcastcard = platform_get_drvdata(devptr); snd_card_free(dreamcastcard->card); kfree(dreamcastcard); - return 0; } static int snd_aica_probe(struct platform_device *devptr) @@ -592,7 +591,7 @@ static int snd_aica_probe(struct platform_device *devptr) static struct platform_driver snd_aica_driver = { .probe = snd_aica_probe, - .remove = snd_aica_remove, + .remove_new = snd_aica_remove, .driver = { .name = SND_AICA_DRIVER, }, -- cgit From a0f4aa0a9f841693a6487315751c12a2f5773574 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:04 +0100 Subject: ALSA: sh_dac_audio: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-13-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/sh/sh_dac_audio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c index 8ebd972846ac..8cf571955c9d 100644 --- a/sound/sh/sh_dac_audio.c +++ b/sound/sh/sh_dac_audio.c @@ -257,10 +257,9 @@ static int snd_sh_dac_pcm(struct snd_sh_dac *chip, int device) /* driver .remove -- destructor */ -static int snd_sh_dac_remove(struct platform_device *devptr) +static void snd_sh_dac_remove(struct platform_device *devptr) { snd_card_free(platform_get_drvdata(devptr)); - return 0; } /* free -- it has been defined by create */ @@ -403,7 +402,7 @@ probe_error: */ static struct platform_driver sh_dac_driver = { .probe = snd_sh_dac_probe, - .remove = snd_sh_dac_remove, + .remove_new = snd_sh_dac_remove, .driver = { .name = "dac_audio", }, -- cgit From 711c5b4e36a3345cd0de597a9c5b7f5911abfd51 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:05 +0100 Subject: ASoC: adi: axi-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-14-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/adi/axi-i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/adi/axi-i2s.c b/sound/soc/adi/axi-i2s.c index b1342351bff4..d5b6f5187f8e 100644 --- a/sound/soc/adi/axi-i2s.c +++ b/sound/soc/adi/axi-i2s.c @@ -274,13 +274,11 @@ err_clk_disable: return ret; } -static int axi_i2s_dev_remove(struct platform_device *pdev) +static void axi_i2s_dev_remove(struct platform_device *pdev) { struct axi_i2s *i2s = platform_get_drvdata(pdev); clk_disable_unprepare(i2s->clk); - - return 0; } static const struct of_device_id axi_i2s_of_match[] = { @@ -295,7 +293,7 @@ static struct platform_driver axi_i2s_driver = { .of_match_table = axi_i2s_of_match, }, .probe = axi_i2s_probe, - .remove = axi_i2s_dev_remove, + .remove_new = axi_i2s_dev_remove, }; module_platform_driver(axi_i2s_driver); -- cgit From a0d18db09ca5b43e832c913b2375f3f6d124cc3b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:06 +0100 Subject: ASoC: adi: axi-spdif: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-15-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/adi/axi-spdif.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/adi/axi-spdif.c b/sound/soc/adi/axi-spdif.c index 51b968ea21da..e4c99bbc9cdd 100644 --- a/sound/soc/adi/axi-spdif.c +++ b/sound/soc/adi/axi-spdif.c @@ -239,13 +239,11 @@ err_clk_disable: return ret; } -static int axi_spdif_dev_remove(struct platform_device *pdev) +static void axi_spdif_dev_remove(struct platform_device *pdev) { struct axi_spdif *spdif = platform_get_drvdata(pdev); clk_disable_unprepare(spdif->clk); - - return 0; } static const struct of_device_id axi_spdif_of_match[] = { @@ -260,7 +258,7 @@ static struct platform_driver axi_spdif_driver = { .of_match_table = axi_spdif_of_match, }, .probe = axi_spdif_probe, - .remove = axi_spdif_dev_remove, + .remove_new = axi_spdif_dev_remove, }; module_platform_driver(axi_spdif_driver); -- cgit From 6bbbbc24eb02518e3c5140b80144ec000bfa5bf7 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:07 +0100 Subject: ASoC: amd: acp-pcm-dma: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-16-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/acp-pcm-dma.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index 198358d28ea9..d41df316da58 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c @@ -1323,7 +1323,7 @@ static int acp_audio_probe(struct platform_device *pdev) return status; } -static int acp_audio_remove(struct platform_device *pdev) +static void acp_audio_remove(struct platform_device *pdev) { int status; struct audio_drv_data *adata = dev_get_drvdata(&pdev->dev); @@ -1332,8 +1332,6 @@ static int acp_audio_remove(struct platform_device *pdev) if (status) dev_err(&pdev->dev, "ACP Deinit failed status:%d\n", status); pm_runtime_disable(&pdev->dev); - - return 0; } static int acp_pcm_resume(struct device *dev) @@ -1428,7 +1426,7 @@ static const struct dev_pm_ops acp_pm_ops = { static struct platform_driver acp_dma_driver = { .probe = acp_audio_probe, - .remove = acp_audio_remove, + .remove_new = acp_audio_remove, .driver = { .name = DRV_NAME, .pm = &acp_pm_ops, -- cgit From 37846af6d08ccdca8308e3d4bfec9f6d97e8eec2 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:08 +0100 Subject: ASoC: amd: acp: rembrandt: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-17-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-rembrandt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index 15cd3f8cc82c..5c455cc04113 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -366,7 +366,7 @@ static int rembrandt_audio_probe(struct platform_device *pdev) return 0; } -static int rembrandt_audio_remove(struct platform_device *pdev) +static void rembrandt_audio_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct acp_dev_data *adata = dev_get_drvdata(dev); @@ -376,12 +376,11 @@ static int rembrandt_audio_remove(struct platform_device *pdev) acp6x_disable_interrupts(adata); acp_platform_unregister(dev); - return 0; } static struct platform_driver rembrandt_driver = { .probe = rembrandt_audio_probe, - .remove = rembrandt_audio_remove, + .remove_new = rembrandt_audio_remove, .driver = { .name = "acp_asoc_rembrandt", }, -- cgit From da8a3ceb45be5d711f109df5bb12261adb790391 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:09 +0100 Subject: ASoC: amd: acp: renoir: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-18-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-renoir.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c index 2a89a0d2e601..b3cbc7f19ec5 100644 --- a/sound/soc/amd/acp/acp-renoir.c +++ b/sound/soc/amd/acp/acp-renoir.c @@ -313,7 +313,7 @@ static int renoir_audio_probe(struct platform_device *pdev) return 0; } -static int renoir_audio_remove(struct platform_device *pdev) +static void renoir_audio_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct acp_dev_data *adata = dev_get_drvdata(dev); @@ -329,12 +329,11 @@ static int renoir_audio_remove(struct platform_device *pdev) dev_err(&pdev->dev, "ACP de-init Failed (%pe)\n", ERR_PTR(ret)); acp_platform_unregister(dev); - return 0; } static struct platform_driver renoir_driver = { .probe = renoir_audio_probe, - .remove = renoir_audio_remove, + .remove_new = renoir_audio_remove, .driver = { .name = "acp_asoc_renoir", }, -- cgit From 5b6bacfa1a7bc353d14189a628d8617a26e8381b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:10 +0100 Subject: ASoC: amd: ps: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-19-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/ps/ps-pdm-dma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/ps/ps-pdm-dma.c b/sound/soc/amd/ps/ps-pdm-dma.c index 454dab062e4f..46b91327168f 100644 --- a/sound/soc/amd/ps/ps-pdm-dma.c +++ b/sound/soc/amd/ps/ps-pdm-dma.c @@ -399,10 +399,9 @@ static int acp63_pdm_audio_probe(struct platform_device *pdev) return 0; } -static int acp63_pdm_audio_remove(struct platform_device *pdev) +static void acp63_pdm_audio_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static int __maybe_unused acp63_pdm_resume(struct device *dev) @@ -451,7 +450,7 @@ static const struct dev_pm_ops acp63_pdm_pm_ops = { static struct platform_driver acp63_pdm_dma_driver = { .probe = acp63_pdm_audio_probe, - .remove = acp63_pdm_audio_remove, + .remove_new = acp63_pdm_audio_remove, .driver = { .name = "acp_ps_pdm_dma", .pm = &acp63_pdm_pm_ops, -- cgit From 599914e146a772f7ceb39912a73565d90336e5e3 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:11 +0100 Subject: ASoC: amd: raven: acp3x-pcm-dma: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-20-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/raven/acp3x-pcm-dma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index 6aec11cf0a6a..7362dd15ad30 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -421,10 +421,9 @@ static int acp3x_audio_probe(struct platform_device *pdev) return 0; } -static int acp3x_audio_remove(struct platform_device *pdev) +static void acp3x_audio_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static int acp3x_resume(struct device *dev) @@ -509,7 +508,7 @@ static const struct dev_pm_ops acp3x_pm_ops = { static struct platform_driver acp3x_dma_driver = { .probe = acp3x_audio_probe, - .remove = acp3x_audio_remove, + .remove_new = acp3x_audio_remove, .driver = { .name = "acp3x_rv_i2s_dma", .pm = &acp3x_pm_ops, -- cgit From 725d4edfa528f07acfda3e080bf1827e5eea0399 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:12 +0100 Subject: ASoC: amd: raven: acp3x-pdm-dma: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-21-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/renoir/acp3x-pdm-dma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c index 0d8b693aecc9..4e299f96521f 100644 --- a/sound/soc/amd/renoir/acp3x-pdm-dma.c +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -435,10 +435,9 @@ static int acp_pdm_audio_probe(struct platform_device *pdev) return 0; } -static int acp_pdm_audio_remove(struct platform_device *pdev) +static void acp_pdm_audio_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static int acp_pdm_resume(struct device *dev) @@ -489,7 +488,7 @@ static const struct dev_pm_ops acp_pdm_pm_ops = { static struct platform_driver acp_pdm_dma_driver = { .probe = acp_pdm_audio_probe, - .remove = acp_pdm_audio_remove, + .remove_new = acp_pdm_audio_remove, .driver = { .name = "acp_rn_pdm_dma", .pm = &acp_pdm_pm_ops, -- cgit From 8564d4f22ce7cbf989af4ba004b44b1878d1b984 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:13 +0100 Subject: ASoC: amd: vangogh: acp5x-pcm-dma: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-22-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-pcm-dma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/vangogh/acp5x-pcm-dma.c b/sound/soc/amd/vangogh/acp5x-pcm-dma.c index d36bb718370f..29901ee4bfe3 100644 --- a/sound/soc/amd/vangogh/acp5x-pcm-dma.c +++ b/sound/soc/amd/vangogh/acp5x-pcm-dma.c @@ -415,10 +415,9 @@ static int acp5x_audio_probe(struct platform_device *pdev) return 0; } -static int acp5x_audio_remove(struct platform_device *pdev) +static void acp5x_audio_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static int __maybe_unused acp5x_pcm_resume(struct device *dev) @@ -500,7 +499,7 @@ static const struct dev_pm_ops acp5x_pm_ops = { static struct platform_driver acp5x_dma_driver = { .probe = acp5x_audio_probe, - .remove = acp5x_audio_remove, + .remove_new = acp5x_audio_remove, .driver = { .name = "acp5x_i2s_dma", .pm = &acp5x_pm_ops, -- cgit From 0e940c75e307f61fdf049ee7ac21d672f91883f3 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:14 +0100 Subject: ASoC: amd: yc: acp6x-pdm-dma: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-23-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/amd/yc/acp6x-pdm-dma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/yc/acp6x-pdm-dma.c b/sound/soc/amd/yc/acp6x-pdm-dma.c index 294dd7fb43c9..d818eba48546 100644 --- a/sound/soc/amd/yc/acp6x-pdm-dma.c +++ b/sound/soc/amd/yc/acp6x-pdm-dma.c @@ -388,10 +388,9 @@ static int acp6x_pdm_audio_probe(struct platform_device *pdev) return 0; } -static int acp6x_pdm_audio_remove(struct platform_device *pdev) +static void acp6x_pdm_audio_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static int __maybe_unused acp6x_pdm_resume(struct device *dev) @@ -440,7 +439,7 @@ static const struct dev_pm_ops acp6x_pdm_pm_ops = { static struct platform_driver acp6x_pdm_dma_driver = { .probe = acp6x_pdm_audio_probe, - .remove = acp6x_pdm_audio_remove, + .remove_new = acp6x_pdm_audio_remove, .driver = { .name = "acp_yc_pdm_dma", .pm = &acp6x_pdm_pm_ops, -- cgit From eb5a9cf29f1e5b6290e168d405eef98b42f158a4 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:15 +0100 Subject: ASoC: apple: mca: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-24-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/apple/mca.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c index 64750db9b963..ce77934f3eef 100644 --- a/sound/soc/apple/mca.c +++ b/sound/soc/apple/mca.c @@ -1159,13 +1159,12 @@ err_release: return ret; } -static int apple_mca_remove(struct platform_device *pdev) +static void apple_mca_remove(struct platform_device *pdev) { struct mca_data *mca = platform_get_drvdata(pdev); snd_soc_unregister_component(&pdev->dev); apple_mca_release(mca); - return 0; } static const struct of_device_id apple_mca_of_match[] = { @@ -1180,7 +1179,7 @@ static struct platform_driver apple_mca_driver = { .of_match_table = apple_mca_of_match, }, .probe = apple_mca_probe, - .remove = apple_mca_remove, + .remove_new = apple_mca_remove, }; module_platform_driver(apple_mca_driver); -- cgit From d0486266a6ba028fe0197c721994f3de5d21550a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:16 +0100 Subject: ASoC: atmel: atmel-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-25-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c index 425d66edbf86..49930baf5e4d 100644 --- a/sound/soc/atmel/atmel-i2s.c +++ b/sound/soc/atmel/atmel-i2s.c @@ -717,13 +717,11 @@ static int atmel_i2s_probe(struct platform_device *pdev) return 0; } -static int atmel_i2s_remove(struct platform_device *pdev) +static void atmel_i2s_remove(struct platform_device *pdev) { struct atmel_i2s_dev *dev = platform_get_drvdata(pdev); clk_disable_unprepare(dev->pclk); - - return 0; } static struct platform_driver atmel_i2s_driver = { @@ -732,7 +730,7 @@ static struct platform_driver atmel_i2s_driver = { .of_match_table = of_match_ptr(atmel_i2s_dt_ids), }, .probe = atmel_i2s_probe, - .remove = atmel_i2s_remove, + .remove_new = atmel_i2s_remove, }; module_platform_driver(atmel_i2s_driver); -- cgit From 0278eb3275df6121ecbab848269495f9ca7f5c7a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:17 +0100 Subject: ASoC: atmel: atmel_wm8904: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-26-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/atmel_wm8904.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c index 9c974c4e187d..00e98136bec2 100644 --- a/sound/soc/atmel/atmel_wm8904.c +++ b/sound/soc/atmel/atmel_wm8904.c @@ -161,7 +161,7 @@ err_set_audio: return ret; } -static int atmel_asoc_wm8904_remove(struct platform_device *pdev) +static void atmel_asoc_wm8904_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink; @@ -171,8 +171,6 @@ static int atmel_asoc_wm8904_remove(struct platform_device *pdev) snd_soc_unregister_card(card); atmel_ssc_put_audio(id); - - return 0; } #ifdef CONFIG_OF @@ -190,7 +188,7 @@ static struct platform_driver atmel_asoc_wm8904_driver = { .pm = &snd_soc_pm_ops, }, .probe = atmel_asoc_wm8904_probe, - .remove = atmel_asoc_wm8904_remove, + .remove_new = atmel_asoc_wm8904_remove, }; module_platform_driver(atmel_asoc_wm8904_driver); -- cgit From b0570709d123ee8bfed32f968d665366fb1a6d2d Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:18 +0100 Subject: ASoC: atmel: mchp-i2s-mcc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-27-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-i2s-mcc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c index 6dfb96c576ff..7c83d48ca1a0 100644 --- a/sound/soc/atmel/mchp-i2s-mcc.c +++ b/sound/soc/atmel/mchp-i2s-mcc.c @@ -1088,13 +1088,11 @@ static int mchp_i2s_mcc_probe(struct platform_device *pdev) return 0; } -static int mchp_i2s_mcc_remove(struct platform_device *pdev) +static void mchp_i2s_mcc_remove(struct platform_device *pdev) { struct mchp_i2s_mcc_dev *dev = platform_get_drvdata(pdev); clk_disable_unprepare(dev->pclk); - - return 0; } static struct platform_driver mchp_i2s_mcc_driver = { @@ -1103,7 +1101,7 @@ static struct platform_driver mchp_i2s_mcc_driver = { .of_match_table = of_match_ptr(mchp_i2s_mcc_dt_ids), }, .probe = mchp_i2s_mcc_probe, - .remove = mchp_i2s_mcc_remove, + .remove_new = mchp_i2s_mcc_remove, }; module_platform_driver(mchp_i2s_mcc_driver); -- cgit From 86fdd4825459db4ec831d2d41a5e27d45dff2641 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:19 +0100 Subject: ASoC: atmel: mchp-pdmc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-28-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-pdmc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c index 81bfa98fd516..da23855a0e40 100644 --- a/sound/soc/atmel/mchp-pdmc.c +++ b/sound/soc/atmel/mchp-pdmc.c @@ -1129,7 +1129,7 @@ pm_runtime_suspend: return ret; } -static int mchp_pdmc_remove(struct platform_device *pdev) +static void mchp_pdmc_remove(struct platform_device *pdev) { struct mchp_pdmc *dd = platform_get_drvdata(pdev); @@ -1137,8 +1137,6 @@ static int mchp_pdmc_remove(struct platform_device *pdev) mchp_pdmc_runtime_suspend(dd->dev); pm_runtime_disable(dd->dev); - - return 0; } static const struct of_device_id mchp_pdmc_of_match[] = { @@ -1163,7 +1161,7 @@ static struct platform_driver mchp_pdmc_driver = { .pm = pm_ptr(&mchp_pdmc_pm_ops), }, .probe = mchp_pdmc_probe, - .remove = mchp_pdmc_remove, + .remove_new = mchp_pdmc_remove, }; module_platform_driver(mchp_pdmc_driver); -- cgit From 879f2ce0a95701695f2b7648ca81aff543631b1d Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:20 +0100 Subject: ASoC: atmel: mchp-spdifrx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-29-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-spdifrx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/mchp-spdifrx.c b/sound/soc/atmel/mchp-spdifrx.c index eb0c0ef4541e..ff6aba143aee 100644 --- a/sound/soc/atmel/mchp-spdifrx.c +++ b/sound/soc/atmel/mchp-spdifrx.c @@ -1183,20 +1183,18 @@ pm_runtime_disable: return err; } -static int mchp_spdifrx_remove(struct platform_device *pdev) +static void mchp_spdifrx_remove(struct platform_device *pdev) { struct mchp_spdifrx_dev *dev = platform_get_drvdata(pdev); pm_runtime_disable(dev->dev); if (!pm_runtime_status_suspended(dev->dev)) mchp_spdifrx_runtime_suspend(dev->dev); - - return 0; } static struct platform_driver mchp_spdifrx_driver = { .probe = mchp_spdifrx_probe, - .remove = mchp_spdifrx_remove, + .remove_new = mchp_spdifrx_remove, .driver = { .name = "mchp_spdifrx", .of_match_table = of_match_ptr(mchp_spdifrx_dt_ids), -- cgit From c1d51c27d22af56e53e2d739cf533182c2a3fca3 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:21 +0100 Subject: ASoC: atmel: mchp-spdiftx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-30-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-spdiftx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c index 02a2fa7a42dd..1d3e17119888 100644 --- a/sound/soc/atmel/mchp-spdiftx.c +++ b/sound/soc/atmel/mchp-spdiftx.c @@ -876,7 +876,7 @@ pm_runtime_suspend: return err; } -static int mchp_spdiftx_remove(struct platform_device *pdev) +static void mchp_spdiftx_remove(struct platform_device *pdev) { struct mchp_spdiftx_dev *dev = platform_get_drvdata(pdev); @@ -884,13 +884,11 @@ static int mchp_spdiftx_remove(struct platform_device *pdev) mchp_spdiftx_runtime_suspend(dev->dev); pm_runtime_disable(dev->dev); - - return 0; } static struct platform_driver mchp_spdiftx_driver = { .probe = mchp_spdiftx_probe, - .remove = mchp_spdiftx_remove, + .remove_new = mchp_spdiftx_remove, .driver = { .name = "mchp_spdiftx", .of_match_table = of_match_ptr(mchp_spdiftx_dt_ids), -- cgit From 2328c4871bd33ce3be5c56a413a79c6b23535217 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:22 +0100 Subject: ASoC: atmel: mikroe-proto: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-31-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/mikroe-proto.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/mikroe-proto.c b/sound/soc/atmel/mikroe-proto.c index 954460719aa3..30c87c2c1b0b 100644 --- a/sound/soc/atmel/mikroe-proto.c +++ b/sound/soc/atmel/mikroe-proto.c @@ -155,11 +155,9 @@ put_codec_node: return ret; } -static int snd_proto_remove(struct platform_device *pdev) +static void snd_proto_remove(struct platform_device *pdev) { snd_soc_unregister_card(&snd_proto); - - return 0; } static const struct of_device_id snd_proto_of_match[] = { @@ -174,7 +172,7 @@ static struct platform_driver snd_proto_driver = { .of_match_table = snd_proto_of_match, }, .probe = snd_proto_probe, - .remove = snd_proto_remove, + .remove_new = snd_proto_remove, }; module_platform_driver(snd_proto_driver); -- cgit From a186762b817329d6d55fb94419b534cb06aca3a7 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:23 +0100 Subject: ASoC: atmel: sam9g20_wm8731: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-32-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/sam9g20_wm8731.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 785b9d01d8af..baf38964b491 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -186,14 +186,12 @@ err: return ret; } -static int at91sam9g20ek_audio_remove(struct platform_device *pdev) +static void at91sam9g20ek_audio_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); snd_soc_unregister_card(card); atmel_ssc_put_audio(0); - - return 0; } #ifdef CONFIG_OF @@ -210,7 +208,7 @@ static struct platform_driver at91sam9g20ek_audio_driver = { .of_match_table = of_match_ptr(at91sam9g20ek_wm8731_dt_ids), }, .probe = at91sam9g20ek_audio_probe, - .remove = at91sam9g20ek_audio_remove, + .remove_new = at91sam9g20ek_audio_remove, }; module_platform_driver(at91sam9g20ek_audio_driver); -- cgit From c79ddc74c50979665d95382137aec0b4c81a61d8 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:24 +0100 Subject: ASoC: atmel: sam9x5_wm8731: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-33-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/sam9x5_wm8731.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c index 99310e40e7a6..cd1d59a90e02 100644 --- a/sound/soc/atmel/sam9x5_wm8731.c +++ b/sound/soc/atmel/sam9x5_wm8731.c @@ -176,14 +176,12 @@ out: return ret; } -static int sam9x5_wm8731_driver_remove(struct platform_device *pdev) +static void sam9x5_wm8731_driver_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct sam9x5_drvdata *priv = card->drvdata; atmel_ssc_put_audio(priv->ssc_id); - - return 0; } static const struct of_device_id sam9x5_wm8731_of_match[] = { @@ -198,7 +196,7 @@ static struct platform_driver sam9x5_wm8731_driver = { .of_match_table = of_match_ptr(sam9x5_wm8731_of_match), }, .probe = sam9x5_wm8731_driver_probe, - .remove = sam9x5_wm8731_driver_remove, + .remove_new = sam9x5_wm8731_driver_remove, }; module_platform_driver(sam9x5_wm8731_driver); -- cgit From d2679d8529096d7e6af2e3a36086075343b586dd Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:25 +0100 Subject: ASoC: atmel: tse850-pcm5142: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Acked-by: Peter Rosin Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-34-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/atmel/tse850-pcm5142.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c index ef537de7719c..efead272d92b 100644 --- a/sound/soc/atmel/tse850-pcm5142.c +++ b/sound/soc/atmel/tse850-pcm5142.c @@ -412,15 +412,13 @@ err_disable_ana: return ret; } -static int tse850_remove(struct platform_device *pdev) +static void tse850_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card); snd_soc_unregister_card(card); regulator_disable(tse850->ana); - - return 0; } static const struct of_device_id tse850_dt_ids[] = { @@ -435,7 +433,7 @@ static struct platform_driver tse850_driver = { .of_match_table = of_match_ptr(tse850_dt_ids), }, .probe = tse850_probe, - .remove = tse850_remove, + .remove_new = tse850_remove, }; module_platform_driver(tse850_driver); -- cgit From a69f0329d49be4b3a46f2e7b4b241f67be73d831 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:26 +0100 Subject: ASoC: au1x: ac97c: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-35-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/au1x/ac97c.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c index b18512ca2578..a11d6841afc2 100644 --- a/sound/soc/au1x/ac97c.c +++ b/sound/soc/au1x/ac97c.c @@ -285,7 +285,7 @@ static int au1xac97c_drvprobe(struct platform_device *pdev) return 0; } -static int au1xac97c_drvremove(struct platform_device *pdev) +static void au1xac97c_drvremove(struct platform_device *pdev) { struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev); @@ -294,8 +294,6 @@ static int au1xac97c_drvremove(struct platform_device *pdev) WR(ctx, AC97_ENABLE, EN_D); /* clock off, disable */ ac97c_workdata = NULL; /* MDEV */ - - return 0; } #ifdef CONFIG_PM @@ -338,7 +336,7 @@ static struct platform_driver au1xac97c_driver = { .pm = AU1XPSCAC97_PMOPS, }, .probe = au1xac97c_drvprobe, - .remove = au1xac97c_drvremove, + .remove_new = au1xac97c_drvremove, }; module_platform_driver(au1xac97c_driver); -- cgit From ea7f61db28e24d328d0dcf28a07b6251f7beae26 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:27 +0100 Subject: ASoC: au1x: i2sc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-36-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/au1x/i2sc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c index b15c8baa9ee4..064406080d72 100644 --- a/sound/soc/au1x/i2sc.c +++ b/sound/soc/au1x/i2sc.c @@ -270,15 +270,13 @@ static int au1xi2s_drvprobe(struct platform_device *pdev) &au1xi2s_dai_driver, 1); } -static int au1xi2s_drvremove(struct platform_device *pdev) +static void au1xi2s_drvremove(struct platform_device *pdev) { struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev); snd_soc_unregister_component(&pdev->dev); WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */ - - return 0; } #ifdef CONFIG_PM @@ -315,7 +313,7 @@ static struct platform_driver au1xi2s_driver = { .pm = AU1XI2SC_PMOPS, }, .probe = au1xi2s_drvprobe, - .remove = au1xi2s_drvremove, + .remove_new = au1xi2s_drvremove, }; module_platform_driver(au1xi2s_driver); -- cgit From c167a43dce9426bb244ca0be50d8e71b94b70532 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:28 +0100 Subject: ASoC: au1x: psc-ac97: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-37-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/au1x/psc-ac97.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index b536394b9ca0..9fd91aea7d1a 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c @@ -421,7 +421,7 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) return 0; } -static int au1xpsc_ac97_drvremove(struct platform_device *pdev) +static void au1xpsc_ac97_drvremove(struct platform_device *pdev) { struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); @@ -434,8 +434,6 @@ static int au1xpsc_ac97_drvremove(struct platform_device *pdev) wmb(); /* drain writebuffer */ au1xpsc_ac97_workdata = NULL; /* MDEV */ - - return 0; } #ifdef CONFIG_PM @@ -488,7 +486,7 @@ static struct platform_driver au1xpsc_ac97_driver = { .pm = AU1XPSCAC97_PMOPS, }, .probe = au1xpsc_ac97_drvprobe, - .remove = au1xpsc_ac97_drvremove, + .remove_new = au1xpsc_ac97_drvremove, }; module_platform_driver(au1xpsc_ac97_driver); -- cgit From 045b9b33d5614b83150d33db688c9238bf370521 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:29 +0100 Subject: ASoC: au1x: psc-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-38-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/au1x/psc-i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index 79b5ae4e494c..52734dec8247 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c @@ -344,7 +344,7 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev) &au1xpsc_i2s_component, &wd->dai_drv, 1); } -static int au1xpsc_i2s_drvremove(struct platform_device *pdev) +static void au1xpsc_i2s_drvremove(struct platform_device *pdev) { struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); @@ -352,8 +352,6 @@ static int au1xpsc_i2s_drvremove(struct platform_device *pdev) wmb(); /* drain writebuffer */ __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd)); wmb(); /* drain writebuffer */ - - return 0; } #ifdef CONFIG_PM @@ -406,7 +404,7 @@ static struct platform_driver au1xpsc_i2s_driver = { .pm = AU1XPSCI2S_PMOPS, }, .probe = au1xpsc_i2s_drvprobe, - .remove = au1xpsc_i2s_drvremove, + .remove_new = au1xpsc_i2s_drvremove, }; module_platform_driver(au1xpsc_i2s_driver); -- cgit From ee357de34391b4d1a926c7ef736f1723d07feb9e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:30 +0100 Subject: ASoC: bcm: bcm63xx-i2s-whistler: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-39-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/bcm/bcm63xx-i2s-whistler.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/bcm/bcm63xx-i2s-whistler.c b/sound/soc/bcm/bcm63xx-i2s-whistler.c index 2da1384ffe91..18c51dbbc8dc 100644 --- a/sound/soc/bcm/bcm63xx-i2s-whistler.c +++ b/sound/soc/bcm/bcm63xx-i2s-whistler.c @@ -289,10 +289,9 @@ static int bcm63xx_i2s_dev_probe(struct platform_device *pdev) return ret; } -static int bcm63xx_i2s_dev_remove(struct platform_device *pdev) +static void bcm63xx_i2s_dev_remove(struct platform_device *pdev) { bcm63xx_soc_platform_remove(pdev); - return 0; } #ifdef CONFIG_OF @@ -308,7 +307,7 @@ static struct platform_driver bcm63xx_i2s_driver = { .of_match_table = of_match_ptr(snd_soc_bcm_audio_match), }, .probe = bcm63xx_i2s_dev_probe, - .remove = bcm63xx_i2s_dev_remove, + .remove_new = bcm63xx_i2s_dev_remove, }; module_platform_driver(bcm63xx_i2s_driver); -- cgit From cf004d9a2abaa70f36194274424031dd7c8b71c7 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:31 +0100 Subject: ASoC: bcm: cygnus-ssp: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-40-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/bcm/cygnus-ssp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/bcm/cygnus-ssp.c b/sound/soc/bcm/cygnus-ssp.c index 2a92e33e1fbf..8638bf22ef5c 100644 --- a/sound/soc/bcm/cygnus-ssp.c +++ b/sound/soc/bcm/cygnus-ssp.c @@ -1377,11 +1377,9 @@ static int cygnus_ssp_probe(struct platform_device *pdev) return 0; } -static int cygnus_ssp_remove(struct platform_device *pdev) +static void cygnus_ssp_remove(struct platform_device *pdev) { cygnus_soc_platform_unregister(&pdev->dev); - - return 0; } static const struct of_device_id cygnus_ssp_of_match[] = { @@ -1392,7 +1390,7 @@ MODULE_DEVICE_TABLE(of, cygnus_ssp_of_match); static struct platform_driver cygnus_ssp_driver = { .probe = cygnus_ssp_probe, - .remove = cygnus_ssp_remove, + .remove_new = cygnus_ssp_remove, .driver = { .name = "cygnus-ssp", .of_match_table = cygnus_ssp_of_match, -- cgit From e711b0fd45d861cb8a19fb5ce0dfc2d21eaefc3f Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:32 +0100 Subject: ASoC: cirrus: edb93xx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-41-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/cirrus/edb93xx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/cirrus/edb93xx.c b/sound/soc/cirrus/edb93xx.c index 385290202912..f49caab21a25 100644 --- a/sound/soc/cirrus/edb93xx.c +++ b/sound/soc/cirrus/edb93xx.c @@ -93,14 +93,12 @@ static int edb93xx_probe(struct platform_device *pdev) return ret; } -static int edb93xx_remove(struct platform_device *pdev) +static void edb93xx_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); snd_soc_unregister_card(card); ep93xx_i2s_release(); - - return 0; } static struct platform_driver edb93xx_driver = { @@ -108,7 +106,7 @@ static struct platform_driver edb93xx_driver = { .name = "edb93xx-audio", }, .probe = edb93xx_probe, - .remove = edb93xx_remove, + .remove_new = edb93xx_remove, }; module_platform_driver(edb93xx_driver); -- cgit From 4b1bb8fd7ba5ddcf54cfc9e5568236a734e07f6e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:33 +0100 Subject: ASoC: cirrus: ep93xx-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Alexander Sverdlin Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-42-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/cirrus/ep93xx-i2s.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 70840f27d4a7..9760453d9d79 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -495,19 +495,18 @@ fail: return err; } -static int ep93xx_i2s_remove(struct platform_device *pdev) +static void ep93xx_i2s_remove(struct platform_device *pdev) { struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev); clk_put(info->lrclk); clk_put(info->sclk); clk_put(info->mclk); - return 0; } static struct platform_driver ep93xx_i2s_driver = { .probe = ep93xx_i2s_probe, - .remove = ep93xx_i2s_remove, + .remove_new = ep93xx_i2s_remove, .driver = { .name = "ep93xx-i2s", }, -- cgit From f57c2cf8d3bd4023347303f195b0ff991324ee2c Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:34 +0100 Subject: ASoC: codecs: cs47l15: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-43-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l15.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c index 06c4214382e3..a6538dab6639 100644 --- a/sound/soc/codecs/cs47l15.c +++ b/sound/soc/codecs/cs47l15.c @@ -1468,7 +1468,7 @@ error_core: return ret; } -static int cs47l15_remove(struct platform_device *pdev) +static void cs47l15_remove(struct platform_device *pdev) { struct cs47l15 *cs47l15 = platform_get_drvdata(pdev); @@ -1482,8 +1482,6 @@ static int cs47l15_remove(struct platform_device *pdev) madera_free_irq(cs47l15->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l15); madera_free_overheat(&cs47l15->core); madera_core_free(&cs47l15->core); - - return 0; } static struct platform_driver cs47l15_codec_driver = { @@ -1491,7 +1489,7 @@ static struct platform_driver cs47l15_codec_driver = { .name = "cs47l15-codec", }, .probe = &cs47l15_probe, - .remove = &cs47l15_remove, + .remove_new = cs47l15_remove, }; module_platform_driver(cs47l15_codec_driver); -- cgit From 90fc2cd0c12535462fe7f71db909b6139a012b95 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:35 +0100 Subject: ASoC: codecs: cs47l24: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-44-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l24.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index f9a2b865d717..a07b621d463e 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -1319,7 +1319,7 @@ err_dsp_irq: return ret; } -static int cs47l24_remove(struct platform_device *pdev) +static void cs47l24_remove(struct platform_device *pdev) { struct cs47l24_priv *cs47l24 = platform_get_drvdata(pdev); struct arizona *arizona = cs47l24->core.arizona; @@ -1333,8 +1333,6 @@ static int cs47l24_remove(struct platform_device *pdev) arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, cs47l24); - - return 0; } static struct platform_driver cs47l24_codec_driver = { @@ -1342,7 +1340,7 @@ static struct platform_driver cs47l24_codec_driver = { .name = "cs47l24-codec", }, .probe = cs47l24_probe, - .remove = cs47l24_remove, + .remove_new = cs47l24_remove, }; module_platform_driver(cs47l24_codec_driver); -- cgit From b9cc4f89852811c6af6de7653e68ee99cf4e524e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:36 +0100 Subject: ASoC: codecs: cs47l35: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-45-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l35.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c index c1032d6c9143..c05c80c16c84 100644 --- a/sound/soc/codecs/cs47l35.c +++ b/sound/soc/codecs/cs47l35.c @@ -1744,7 +1744,7 @@ error_core: return ret; } -static int cs47l35_remove(struct platform_device *pdev) +static void cs47l35_remove(struct platform_device *pdev) { struct cs47l35 *cs47l35 = platform_get_drvdata(pdev); int i; @@ -1758,8 +1758,6 @@ static int cs47l35_remove(struct platform_device *pdev) madera_free_irq(cs47l35->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l35); madera_free_overheat(&cs47l35->core); madera_core_free(&cs47l35->core); - - return 0; } static struct platform_driver cs47l35_codec_driver = { @@ -1767,7 +1765,7 @@ static struct platform_driver cs47l35_codec_driver = { .name = "cs47l35-codec", }, .probe = &cs47l35_probe, - .remove = &cs47l35_remove, + .remove_new = cs47l35_remove, }; module_platform_driver(cs47l35_codec_driver); -- cgit From f71d98e5c6a979476bcf366b9764573c3fe578cf Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:37 +0100 Subject: ASoC: codecs: cs47l85: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-46-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l85.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c index 215d8211aa59..dd7997a53e70 100644 --- a/sound/soc/codecs/cs47l85.c +++ b/sound/soc/codecs/cs47l85.c @@ -2695,7 +2695,7 @@ error_core: return ret; } -static int cs47l85_remove(struct platform_device *pdev) +static void cs47l85_remove(struct platform_device *pdev) { struct cs47l85 *cs47l85 = platform_get_drvdata(pdev); int i; @@ -2709,8 +2709,6 @@ static int cs47l85_remove(struct platform_device *pdev) madera_free_irq(cs47l85->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l85); madera_free_overheat(&cs47l85->core); madera_core_free(&cs47l85->core); - - return 0; } static struct platform_driver cs47l85_codec_driver = { @@ -2718,7 +2716,7 @@ static struct platform_driver cs47l85_codec_driver = { .name = "cs47l85-codec", }, .probe = &cs47l85_probe, - .remove = &cs47l85_remove, + .remove_new = cs47l85_remove, }; module_platform_driver(cs47l85_codec_driver); -- cgit From acd39a3729829587128a0d58dbd13c1b23066259 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:38 +0100 Subject: ASoC: codecs: cs47l90: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-47-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l90.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c index 1ad6526c7871..cdd5e7e20b5d 100644 --- a/sound/soc/codecs/cs47l90.c +++ b/sound/soc/codecs/cs47l90.c @@ -2618,7 +2618,7 @@ error_core: return ret; } -static int cs47l90_remove(struct platform_device *pdev) +static void cs47l90_remove(struct platform_device *pdev) { struct cs47l90 *cs47l90 = platform_get_drvdata(pdev); int i; @@ -2633,8 +2633,6 @@ static int cs47l90_remove(struct platform_device *pdev) madera_set_irq_wake(cs47l90->core.madera, MADERA_IRQ_DSP_IRQ1, 0); madera_free_irq(cs47l90->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l90); madera_core_free(&cs47l90->core); - - return 0; } static struct platform_driver cs47l90_codec_driver = { @@ -2642,7 +2640,7 @@ static struct platform_driver cs47l90_codec_driver = { .name = "cs47l90-codec", }, .probe = &cs47l90_probe, - .remove = &cs47l90_remove, + .remove_new = cs47l90_remove, }; module_platform_driver(cs47l90_codec_driver); -- cgit From 516ef43d40e976e16b4eb1c51a7b96e579a297bb Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:39 +0100 Subject: ASoC: codecs: cs47l92: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-48-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l92.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c index fe576d64e089..bc4d311d4778 100644 --- a/sound/soc/codecs/cs47l92.c +++ b/sound/soc/codecs/cs47l92.c @@ -2068,7 +2068,7 @@ error_core: return ret; } -static int cs47l92_remove(struct platform_device *pdev) +static void cs47l92_remove(struct platform_device *pdev) { struct cs47l92 *cs47l92 = platform_get_drvdata(pdev); @@ -2081,8 +2081,6 @@ static int cs47l92_remove(struct platform_device *pdev) madera_free_irq(cs47l92->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l92); madera_core_free(&cs47l92->core); - - return 0; } static struct platform_driver cs47l92_codec_driver = { @@ -2090,7 +2088,7 @@ static struct platform_driver cs47l92_codec_driver = { .name = "cs47l92-codec", }, .probe = &cs47l92_probe, - .remove = &cs47l92_remove, + .remove_new = cs47l92_remove, }; module_platform_driver(cs47l92_codec_driver); -- cgit From 8756b2ecbd2aa22d6981f6a48a804f0d2cec68a8 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:40 +0100 Subject: ASoC: codecs: inno_rk3036: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-49-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/inno_rk3036.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c index 8222cde6e3b9..11320423c69c 100644 --- a/sound/soc/codecs/inno_rk3036.c +++ b/sound/soc/codecs/inno_rk3036.c @@ -457,13 +457,11 @@ static int rk3036_codec_platform_probe(struct platform_device *pdev) return ret; } -static int rk3036_codec_platform_remove(struct platform_device *pdev) +static void rk3036_codec_platform_remove(struct platform_device *pdev) { struct rk3036_codec_priv *priv = dev_get_drvdata(&pdev->dev); clk_disable_unprepare(priv->pclk); - - return 0; } static const struct of_device_id rk3036_codec_of_match[] __maybe_unused = { @@ -478,7 +476,7 @@ static struct platform_driver rk3036_codec_platform_driver = { .of_match_table = of_match_ptr(rk3036_codec_of_match), }, .probe = rk3036_codec_platform_probe, - .remove = rk3036_codec_platform_remove, + .remove_new = rk3036_codec_platform_remove, }; module_platform_driver(rk3036_codec_platform_driver); -- cgit From 5b06877205882a92aaf5ced177476697849fd1fe Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:41 +0100 Subject: ASoC: codecs: lpass-rx-macro: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-50-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-rx-macro.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index a73a7d7a1c0a..9e0a4e8a46c3 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -3639,7 +3639,7 @@ err: return ret; } -static int rx_macro_remove(struct platform_device *pdev) +static void rx_macro_remove(struct platform_device *pdev) { struct rx_macro *rx = dev_get_drvdata(&pdev->dev); @@ -3650,8 +3650,6 @@ static int rx_macro_remove(struct platform_device *pdev) clk_disable_unprepare(rx->dcodec); lpass_macro_pds_exit(rx->pds); - - return 0; } static const struct of_device_id rx_macro_dt_match[] = { @@ -3723,7 +3721,7 @@ static struct platform_driver rx_macro_driver = { .pm = &rx_macro_pm_ops, }, .probe = rx_macro_probe, - .remove = rx_macro_remove, + .remove_new = rx_macro_remove, }; module_platform_driver(rx_macro_driver); -- cgit From 10b4f1ed0499bb1cf8335d3956bd82da59314534 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:42 +0100 Subject: ASoC: codecs: lpass-tx-macro: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-51-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-tx-macro.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index 473d3cd39554..b044c9c6f89b 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -2076,7 +2076,7 @@ err: return ret; } -static int tx_macro_remove(struct platform_device *pdev) +static void tx_macro_remove(struct platform_device *pdev) { struct tx_macro *tx = dev_get_drvdata(&pdev->dev); @@ -2087,8 +2087,6 @@ static int tx_macro_remove(struct platform_device *pdev) clk_disable_unprepare(tx->fsgen); lpass_macro_pds_exit(tx->pds); - - return 0; } static int __maybe_unused tx_macro_runtime_suspend(struct device *dev) @@ -2160,7 +2158,7 @@ static struct platform_driver tx_macro_driver = { .pm = &tx_macro_pm_ops, }, .probe = tx_macro_probe, - .remove = tx_macro_remove, + .remove_new = tx_macro_remove, }; module_platform_driver(tx_macro_driver); -- cgit From b84affc1b4e2a9cec0720eea729c0f4d0490a0c2 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:43 +0100 Subject: ASoC: codecs: lpass-va-macro: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-52-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-va-macro.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index fd62817d29a0..74724448da50 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -1575,7 +1575,7 @@ err: return ret; } -static int va_macro_remove(struct platform_device *pdev) +static void va_macro_remove(struct platform_device *pdev) { struct va_macro *va = dev_get_drvdata(&pdev->dev); @@ -1584,8 +1584,6 @@ static int va_macro_remove(struct platform_device *pdev) clk_disable_unprepare(va->macro); lpass_macro_pds_exit(va->pds); - - return 0; } static int __maybe_unused va_macro_runtime_suspend(struct device *dev) @@ -1639,7 +1637,7 @@ static struct platform_driver va_macro_driver = { .pm = &va_macro_pm_ops, }, .probe = va_macro_probe, - .remove = va_macro_remove, + .remove_new = va_macro_remove, }; module_platform_driver(va_macro_driver); -- cgit From 23a3ef6545a91abc78249e72107a13b43a68d4f9 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:44 +0100 Subject: ASoC: codecs: lpass-wsa-macro: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-53-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-wsa-macro.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index ba7480f3831e..728f26d12ab0 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -2486,7 +2486,7 @@ err: } -static int wsa_macro_remove(struct platform_device *pdev) +static void wsa_macro_remove(struct platform_device *pdev) { struct wsa_macro *wsa = dev_get_drvdata(&pdev->dev); @@ -2495,8 +2495,6 @@ static int wsa_macro_remove(struct platform_device *pdev) clk_disable_unprepare(wsa->mclk); clk_disable_unprepare(wsa->npl); clk_disable_unprepare(wsa->fsgen); - - return 0; } static int __maybe_unused wsa_macro_runtime_suspend(struct device *dev) @@ -2568,7 +2566,7 @@ static struct platform_driver wsa_macro_driver = { .pm = &wsa_macro_pm_ops, }, .probe = wsa_macro_probe, - .remove = wsa_macro_remove, + .remove_new = wsa_macro_remove, }; module_platform_driver(wsa_macro_driver); -- cgit From 22b27fafbfaf398c1014726b679d5d1e8389d704 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:45 +0100 Subject: ASoC: codecs: msm8916-wcd-analog: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-54-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/msm8916-wcd-analog.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index 78e543eb3c83..cec90cf920ff 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -1276,13 +1276,11 @@ err_disable_clk: return ret; } -static int pm8916_wcd_analog_spmi_remove(struct platform_device *pdev) +static void pm8916_wcd_analog_spmi_remove(struct platform_device *pdev) { struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(&pdev->dev); clk_disable_unprepare(priv->mclk); - - return 0; } static const struct of_device_id pm8916_wcd_analog_spmi_match_table[] = { @@ -1298,7 +1296,7 @@ static struct platform_driver pm8916_wcd_analog_spmi_driver = { .of_match_table = pm8916_wcd_analog_spmi_match_table, }, .probe = pm8916_wcd_analog_spmi_probe, - .remove = pm8916_wcd_analog_spmi_remove, + .remove_new = pm8916_wcd_analog_spmi_remove, }; module_platform_driver(pm8916_wcd_analog_spmi_driver); -- cgit From 004967ba3e8820ef8c48779ae9491cc1c6729b7c Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:46 +0100 Subject: ASoC: codecs: msm8916-wcd-digital: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-55-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/msm8916-wcd-digital.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/msm8916-wcd-digital.c b/sound/soc/codecs/msm8916-wcd-digital.c index d490a0f18675..978c4d056e81 100644 --- a/sound/soc/codecs/msm8916-wcd-digital.c +++ b/sound/soc/codecs/msm8916-wcd-digital.c @@ -1220,14 +1220,12 @@ err_clk: return ret; } -static int msm8916_wcd_digital_remove(struct platform_device *pdev) +static void msm8916_wcd_digital_remove(struct platform_device *pdev) { struct msm8916_wcd_digital_priv *priv = dev_get_drvdata(&pdev->dev); clk_disable_unprepare(priv->mclk); clk_disable_unprepare(priv->ahbclk); - - return 0; } static const struct of_device_id msm8916_wcd_digital_match_table[] = { @@ -1243,7 +1241,7 @@ static struct platform_driver msm8916_wcd_digital_driver = { .of_match_table = msm8916_wcd_digital_match_table, }, .probe = msm8916_wcd_digital_probe, - .remove = msm8916_wcd_digital_remove, + .remove_new = msm8916_wcd_digital_remove, }; module_platform_driver(msm8916_wcd_digital_driver); -- cgit From 68dadf3eceb2d3d60d3364006a5b72da4050bdcf Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:47 +0100 Subject: ASoC: codecs: rk817_codec: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-56-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/rk817_codec.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c index 2a5b274bfc0f..d4da98469f8b 100644 --- a/sound/soc/codecs/rk817_codec.c +++ b/sound/soc/codecs/rk817_codec.c @@ -518,13 +518,11 @@ err_: return ret; } -static int rk817_platform_remove(struct platform_device *pdev) +static void rk817_platform_remove(struct platform_device *pdev) { struct rk817_codec_priv *rk817 = platform_get_drvdata(pdev); clk_disable_unprepare(rk817->mclk); - - return 0; } static struct platform_driver rk817_codec_driver = { @@ -532,7 +530,7 @@ static struct platform_driver rk817_codec_driver = { .name = "rk817-codec", }, .probe = rk817_platform_probe, - .remove = rk817_platform_remove, + .remove_new = rk817_platform_remove, }; module_platform_driver(rk817_codec_driver); -- cgit From 7cd686a59b36860511965882dad1f76df2c25766 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:48 +0100 Subject: ASoC: codecs: wcd938x: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-57-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/wcd938x.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index fcac763b04d1..f033f79ed238 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -4529,11 +4529,9 @@ static int wcd938x_probe(struct platform_device *pdev) return 0; } -static int wcd938x_remove(struct platform_device *pdev) +static void wcd938x_remove(struct platform_device *pdev) { component_master_del(&pdev->dev, &wcd938x_comp_ops); - - return 0; } #if defined(CONFIG_OF) @@ -4547,7 +4545,7 @@ MODULE_DEVICE_TABLE(of, wcd938x_dt_match); static struct platform_driver wcd938x_codec_driver = { .probe = wcd938x_probe, - .remove = wcd938x_remove, + .remove_new = wcd938x_remove, .driver = { .name = "wcd938x_codec", .of_match_table = of_match_ptr(wcd938x_dt_match), -- cgit From 25a4c2697c1cb3ed1f1395f9fee4de4aed8d7503 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:49 +0100 Subject: ASoC: codecs: wm5102: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-58-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index adaf886b0a9d..3bdbdf3770b5 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -2148,7 +2148,7 @@ err_jack_codec_dev: return ret; } -static int wm5102_remove(struct platform_device *pdev) +static void wm5102_remove(struct platform_device *pdev) { struct wm5102_priv *wm5102 = platform_get_drvdata(pdev); struct arizona *arizona = wm5102->core.arizona; @@ -2163,8 +2163,6 @@ static int wm5102_remove(struct platform_device *pdev) arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102); arizona_jack_codec_dev_remove(&wm5102->core); - - return 0; } static struct platform_driver wm5102_codec_driver = { @@ -2172,7 +2170,7 @@ static struct platform_driver wm5102_codec_driver = { .name = "wm5102-codec", }, .probe = wm5102_probe, - .remove = wm5102_remove, + .remove_new = wm5102_remove, }; module_platform_driver(wm5102_codec_driver); -- cgit From d1535277bf69de5e72e76a2fef15ff6ccd0ea1f7 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:50 +0100 Subject: ASoC: codecs: wm5110: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-59-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm5110.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index e0b971620d0f..ad670300de8d 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -2506,7 +2506,7 @@ err_jack_codec_dev: return ret; } -static int wm5110_remove(struct platform_device *pdev) +static void wm5110_remove(struct platform_device *pdev) { struct wm5110_priv *wm5110 = platform_get_drvdata(pdev); struct arizona *arizona = wm5110->core.arizona; @@ -2523,8 +2523,6 @@ static int wm5110_remove(struct platform_device *pdev) arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5110); arizona_jack_codec_dev_remove(&wm5110->core); - - return 0; } static struct platform_driver wm5110_codec_driver = { @@ -2532,7 +2530,7 @@ static struct platform_driver wm5110_codec_driver = { .name = "wm5110-codec", }, .probe = wm5110_probe, - .remove = wm5110_remove, + .remove_new = wm5110_remove, }; module_platform_driver(wm5110_codec_driver); -- cgit From 63d3f580d95901e5b250105f3637b8e865219864 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:51 +0100 Subject: ASoC: codecs: wm8994: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-60-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 8fe9a75d1235..bca3ebe0dac4 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -4657,11 +4657,9 @@ static int wm8994_probe(struct platform_device *pdev) return ret; } -static int wm8994_remove(struct platform_device *pdev) +static void wm8994_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -4701,7 +4699,7 @@ static struct platform_driver wm8994_codec_driver = { .pm = &wm8994_pm_ops, }, .probe = wm8994_probe, - .remove = wm8994_remove, + .remove_new = wm8994_remove, }; module_platform_driver(wm8994_codec_driver); -- cgit From e1df73df807721ce0f7be9c58ef6c751112f2aab Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:52 +0100 Subject: ASoC: codecs: wm8997: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-61-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm8997.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index c0207e9a7d53..87442840f0af 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -1193,7 +1193,7 @@ err_jack_codec_dev: return ret; } -static int wm8997_remove(struct platform_device *pdev) +static void wm8997_remove(struct platform_device *pdev) { struct wm8997_priv *wm8997 = platform_get_drvdata(pdev); struct arizona *arizona = wm8997->core.arizona; @@ -1203,8 +1203,6 @@ static int wm8997_remove(struct platform_device *pdev) arizona_free_spk_irqs(arizona); arizona_jack_codec_dev_remove(&wm8997->core); - - return 0; } static struct platform_driver wm8997_codec_driver = { @@ -1212,7 +1210,7 @@ static struct platform_driver wm8997_codec_driver = { .name = "wm8997-codec", }, .probe = wm8997_probe, - .remove = wm8997_remove, + .remove_new = wm8997_remove, }; module_platform_driver(wm8997_codec_driver); -- cgit From 52675c1e9bfaaecc9999b39caf1305a2688df6dd Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:53 +0100 Subject: ASoC: codecs: wm8998: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-62-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm8998.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index 79fc6bbaa3aa..3c2c4d12c08e 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c @@ -1409,7 +1409,7 @@ err_pm_disable: return ret; } -static int wm8998_remove(struct platform_device *pdev) +static void wm8998_remove(struct platform_device *pdev) { struct wm8998_priv *wm8998 = platform_get_drvdata(pdev); struct arizona *arizona = wm8998->core.arizona; @@ -1419,8 +1419,6 @@ static int wm8998_remove(struct platform_device *pdev) arizona_free_spk_irqs(arizona); arizona_jack_codec_dev_remove(&wm8998->core); - - return 0; } static struct platform_driver wm8998_codec_driver = { @@ -1428,7 +1426,7 @@ static struct platform_driver wm8998_codec_driver = { .name = "wm8998-codec", }, .probe = wm8998_probe, - .remove = wm8998_remove, + .remove_new = wm8998_remove, }; module_platform_driver(wm8998_codec_driver); -- cgit From db3a56667e84503a7908a307cf74bf7f4e3f4fa5 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:54 +0100 Subject: ASoC: dwc: dwc-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-63-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/dwc/dwc-i2s.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c index 7f7dd07c63b2..acdf98b2ee9c 100644 --- a/sound/soc/dwc/dwc-i2s.c +++ b/sound/soc/dwc/dwc-i2s.c @@ -730,7 +730,7 @@ err_clk_disable: return ret; } -static int dw_i2s_remove(struct platform_device *pdev) +static void dw_i2s_remove(struct platform_device *pdev) { struct dw_i2s_dev *dev = dev_get_drvdata(&pdev->dev); @@ -738,7 +738,6 @@ static int dw_i2s_remove(struct platform_device *pdev) clk_disable_unprepare(dev->clk); pm_runtime_disable(&pdev->dev); - return 0; } #ifdef CONFIG_OF @@ -756,7 +755,7 @@ static const struct dev_pm_ops dwc_pm_ops = { static struct platform_driver dw_i2s_driver = { .probe = dw_i2s_probe, - .remove = dw_i2s_remove, + .remove_new = dw_i2s_remove, .driver = { .name = "designware-i2s", .of_match_table = of_match_ptr(dw_i2s_of_match), -- cgit From 01192ad23b06216c9abdca07ef9e7add33c69a72 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:55 +0100 Subject: ASoC: fsl: eukrea-tlv320: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-64-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/eukrea-tlv320.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 9af4c4a35eb1..e65a85feba78 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -205,11 +205,9 @@ err: return ret; } -static int eukrea_tlv320_remove(struct platform_device *pdev) +static void eukrea_tlv320_remove(struct platform_device *pdev) { snd_soc_unregister_card(&eukrea_tlv320); - - return 0; } static const struct of_device_id imx_tlv320_dt_ids[] = { @@ -224,7 +222,7 @@ static struct platform_driver eukrea_tlv320_driver = { .of_match_table = imx_tlv320_dt_ids, }, .probe = eukrea_tlv320_probe, - .remove = eukrea_tlv320_remove, + .remove_new = eukrea_tlv320_remove, }; module_platform_driver(eukrea_tlv320_driver); -- cgit From 7a2d15b9322b4233cfe6bd7f747ec89672d17889 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:56 +0100 Subject: ASoC: fsl: fsl_asrc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-65-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index e16e7b3fa96c..adb8a59de2bd 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -1252,13 +1252,11 @@ err_pm_disable: return ret; } -static int fsl_asrc_remove(struct platform_device *pdev) +static void fsl_asrc_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) fsl_asrc_runtime_suspend(&pdev->dev); - - return 0; } static int fsl_asrc_runtime_resume(struct device *dev) @@ -1394,7 +1392,7 @@ MODULE_DEVICE_TABLE(of, fsl_asrc_ids); static struct platform_driver fsl_asrc_driver = { .probe = fsl_asrc_probe, - .remove = fsl_asrc_remove, + .remove_new = fsl_asrc_remove, .driver = { .name = "fsl-asrc", .of_match_table = fsl_asrc_ids, -- cgit From 2a41b19201c8f22e10eebc6fc016cef5e6915ffb Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:57 +0100 Subject: ASoC: fsl: fsl_aud2htx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-66-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_aud2htx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_aud2htx.c b/sound/soc/fsl/fsl_aud2htx.c index 1e421d9a03fb..46b0c5dcc4a5 100644 --- a/sound/soc/fsl/fsl_aud2htx.c +++ b/sound/soc/fsl/fsl_aud2htx.c @@ -257,11 +257,9 @@ static int fsl_aud2htx_probe(struct platform_device *pdev) return ret; } -static int fsl_aud2htx_remove(struct platform_device *pdev) +static void fsl_aud2htx_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static int __maybe_unused fsl_aud2htx_runtime_suspend(struct device *dev) @@ -300,7 +298,7 @@ static const struct dev_pm_ops fsl_aud2htx_pm_ops = { static struct platform_driver fsl_aud2htx_driver = { .probe = fsl_aud2htx_probe, - .remove = fsl_aud2htx_remove, + .remove_new = fsl_aud2htx_remove, .driver = { .name = "fsl-aud2htx", .pm = &fsl_aud2htx_pm_ops, -- cgit From fd24dfc35b49ee029ac8d3cc45cd4420ae1b455b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:58 +0100 Subject: ASoC: fsl: fsl_audmix: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-67-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_audmix.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 672148dd4b23..0ab2c1962117 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -506,7 +506,7 @@ err_disable_pm: return ret; } -static int fsl_audmix_remove(struct platform_device *pdev) +static void fsl_audmix_remove(struct platform_device *pdev) { struct fsl_audmix *priv = dev_get_drvdata(&pdev->dev); @@ -514,8 +514,6 @@ static int fsl_audmix_remove(struct platform_device *pdev) if (priv->pdev) platform_device_unregister(priv->pdev); - - return 0; } #ifdef CONFIG_PM @@ -558,7 +556,7 @@ static const struct dev_pm_ops fsl_audmix_pm = { static struct platform_driver fsl_audmix_driver = { .probe = fsl_audmix_probe, - .remove = fsl_audmix_remove, + .remove_new = fsl_audmix_remove, .driver = { .name = "fsl-audmix", .of_match_table = fsl_audmix_ids, -- cgit From 2c8a5de60d210093dd4b98fb4d8cdbd637450bac Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:05:59 +0100 Subject: ASoC: fsl: fsl_dma: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-68-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_dma.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 808fb61a7a0f..963f9774c883 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -890,15 +890,13 @@ static int fsl_soc_dma_probe(struct platform_device *pdev) return 0; } -static int fsl_soc_dma_remove(struct platform_device *pdev) +static void fsl_soc_dma_remove(struct platform_device *pdev) { struct dma_object *dma = dev_get_drvdata(&pdev->dev); iounmap(dma->channel); irq_dispose_mapping(dma->irq); kfree(dma); - - return 0; } static const struct of_device_id fsl_soc_dma_ids[] = { @@ -913,7 +911,7 @@ static struct platform_driver fsl_soc_dma_driver = { .of_match_table = fsl_soc_dma_ids, }, .probe = fsl_soc_dma_probe, - .remove = fsl_soc_dma_remove, + .remove_new = fsl_soc_dma_remove, }; module_platform_driver(fsl_soc_dma_driver); -- cgit From 0c880ae7c01402e09a62d34356da3b03933c6603 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:00 +0100 Subject: ASoC: fsl: fsl_easrc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-69-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_easrc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index 3153d19136b2..670cbdb361b6 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -1979,11 +1979,9 @@ static int fsl_easrc_probe(struct platform_device *pdev) return 0; } -static int fsl_easrc_remove(struct platform_device *pdev) +static void fsl_easrc_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static __maybe_unused int fsl_easrc_runtime_suspend(struct device *dev) @@ -2093,7 +2091,7 @@ static const struct dev_pm_ops fsl_easrc_pm_ops = { static struct platform_driver fsl_easrc_driver = { .probe = fsl_easrc_probe, - .remove = fsl_easrc_remove, + .remove_new = fsl_easrc_remove, .driver = { .name = "fsl-easrc", .pm = &fsl_easrc_pm_ops, -- cgit From 0c85719ee2c6320ab2fdea7852a1008ac51a05f1 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:01 +0100 Subject: ASoC: fsl: fsl_esai: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-70-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 17fefd27ec90..936f0cd4b06d 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -1101,7 +1101,7 @@ err_pm_disable: return ret; } -static int fsl_esai_remove(struct platform_device *pdev) +static void fsl_esai_remove(struct platform_device *pdev) { struct fsl_esai *esai_priv = platform_get_drvdata(pdev); @@ -1110,8 +1110,6 @@ static int fsl_esai_remove(struct platform_device *pdev) fsl_esai_runtime_suspend(&pdev->dev); cancel_work_sync(&esai_priv->work); - - return 0; } static const struct of_device_id fsl_esai_dt_ids[] = { @@ -1200,7 +1198,7 @@ static const struct dev_pm_ops fsl_esai_pm_ops = { static struct platform_driver fsl_esai_driver = { .probe = fsl_esai_probe, - .remove = fsl_esai_remove, + .remove_new = fsl_esai_remove, .driver = { .name = "fsl-esai-dai", .pm = &fsl_esai_pm_ops, -- cgit From 4ff299cb33ae40367d38e66c5cba15242cbbe33c Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:02 +0100 Subject: ASoC: fsl: fsl_mqs: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-71-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_mqs.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c index 4922e6795b73..3fb3d3e4d09a 100644 --- a/sound/soc/fsl/fsl_mqs.c +++ b/sound/soc/fsl/fsl_mqs.c @@ -261,10 +261,9 @@ err_free_gpr_np: return ret; } -static int fsl_mqs_remove(struct platform_device *pdev) +static void fsl_mqs_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } #ifdef CONFIG_PM @@ -360,7 +359,7 @@ MODULE_DEVICE_TABLE(of, fsl_mqs_dt_ids); static struct platform_driver fsl_mqs_driver = { .probe = fsl_mqs_probe, - .remove = fsl_mqs_remove, + .remove_new = fsl_mqs_remove, .driver = { .name = "fsl-mqs", .of_match_table = fsl_mqs_dt_ids, -- cgit From 126ce4328be219c12458e308feade8168dff588d Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:03 +0100 Subject: ASoC: fsl: fsl_rpmsg: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-72-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_rpmsg.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c index 46c7868a2653..15b48b5ea856 100644 --- a/sound/soc/fsl/fsl_rpmsg.c +++ b/sound/soc/fsl/fsl_rpmsg.c @@ -247,14 +247,12 @@ static int fsl_rpmsg_probe(struct platform_device *pdev) return 0; } -static int fsl_rpmsg_remove(struct platform_device *pdev) +static void fsl_rpmsg_remove(struct platform_device *pdev) { struct fsl_rpmsg *rpmsg = platform_get_drvdata(pdev); if (rpmsg->card_pdev) platform_device_unregister(rpmsg->card_pdev); - - return 0; } #ifdef CONFIG_PM @@ -302,7 +300,7 @@ static const struct dev_pm_ops fsl_rpmsg_pm_ops = { static struct platform_driver fsl_rpmsg_driver = { .probe = fsl_rpmsg_probe, - .remove = fsl_rpmsg_remove, + .remove_new = fsl_rpmsg_remove, .driver = { .name = "fsl_rpmsg", .pm = &fsl_rpmsg_pm_ops, -- cgit From 78c2698dd557e2c69d1ecfc2f458eeaff0adfed3 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:04 +0100 Subject: ASoC: fsl: fsl_sai: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-73-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 4e6b75f1ddd0..07d13dca852e 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -1489,13 +1489,11 @@ err_pm_disable: return ret; } -static int fsl_sai_remove(struct platform_device *pdev) +static void fsl_sai_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) fsl_sai_runtime_suspend(&pdev->dev); - - return 0; } static const struct fsl_sai_soc_data fsl_sai_vf610_data = { @@ -1696,7 +1694,7 @@ static const struct dev_pm_ops fsl_sai_pm_ops = { static struct platform_driver fsl_sai_driver = { .probe = fsl_sai_probe, - .remove = fsl_sai_remove, + .remove_new = fsl_sai_remove, .driver = { .name = "fsl-sai", .pm = &fsl_sai_pm_ops, -- cgit From c8c0bd47cf83c48d422b68b3cfb808f569d7453d Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:05 +0100 Subject: ASoC: fsl: fsl_spdif: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-74-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_spdif.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 275aba8e0c46..015c3708aa04 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -1659,11 +1659,9 @@ err_pm_disable: return ret; } -static int fsl_spdif_remove(struct platform_device *pdev) +static void fsl_spdif_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } #ifdef CONFIG_PM @@ -1765,7 +1763,7 @@ static struct platform_driver fsl_spdif_driver = { .pm = &fsl_spdif_pm, }, .probe = fsl_spdif_probe, - .remove = fsl_spdif_remove, + .remove_new = fsl_spdif_remove, }; module_platform_driver(fsl_spdif_driver); -- cgit From 2d1c82c460f2602282749825d5599688a46363ad Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:06 +0100 Subject: ASoC: fsl: fsl_ssi: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-75-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_ssi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 6af00b62a60f..53ed3701b0b0 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1671,7 +1671,7 @@ error_ac97_ops: return ret; } -static int fsl_ssi_remove(struct platform_device *pdev) +static void fsl_ssi_remove(struct platform_device *pdev) { struct fsl_ssi *ssi = dev_get_drvdata(&pdev->dev); @@ -1690,8 +1690,6 @@ static int fsl_ssi_remove(struct platform_device *pdev) snd_soc_set_ac97_ops(NULL); mutex_destroy(&ssi->ac97_reg_lock); } - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1737,7 +1735,7 @@ static struct platform_driver fsl_ssi_driver = { .pm = &fsl_ssi_pm, }, .probe = fsl_ssi_probe, - .remove = fsl_ssi_remove, + .remove_new = fsl_ssi_remove, }; module_platform_driver(fsl_ssi_driver); -- cgit From aefe902ea8d538a86d9eb7128d5878e0b838241f Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:07 +0100 Subject: ASoC: fsl: fsl_xcvr: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-76-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_xcvr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index 2a78243df752..318fe77683f5 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -1339,10 +1339,9 @@ static int fsl_xcvr_probe(struct platform_device *pdev) return ret; } -static int fsl_xcvr_remove(struct platform_device *pdev) +static void fsl_xcvr_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static __maybe_unused int fsl_xcvr_runtime_suspend(struct device *dev) @@ -1478,7 +1477,7 @@ static struct platform_driver fsl_xcvr_driver = { .pm = &fsl_xcvr_pm_ops, .of_match_table = fsl_xcvr_dt_ids, }, - .remove = fsl_xcvr_remove, + .remove_new = fsl_xcvr_remove, }; module_platform_driver(fsl_xcvr_driver); -- cgit From 51451f46d1f3134235f3a332f919e2b7af87fd49 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:08 +0100 Subject: ASoC: fsl: imx-audmux: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-77-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmux.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index 582f1e2431ee..be003a117b39 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -315,12 +315,10 @@ static int imx_audmux_probe(struct platform_device *pdev) return 0; } -static int imx_audmux_remove(struct platform_device *pdev) +static void imx_audmux_remove(struct platform_device *pdev) { if (audmux_type == IMX31_AUDMUX) audmux_debugfs_remove(); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -359,7 +357,7 @@ static const struct dev_pm_ops imx_audmux_pm = { static struct platform_driver imx_audmux_driver = { .probe = imx_audmux_probe, - .remove = imx_audmux_remove, + .remove_new = imx_audmux_remove, .driver = { .name = DRIVER_NAME, .pm = &imx_audmux_pm, -- cgit From a064945698110e2aa283026bd4f31e3c34e00e93 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:09 +0100 Subject: ASoC: fsl: imx-pcm-rpmsg: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-78-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/imx-pcm-rpmsg.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c index 6614b3447649..765dad607bf6 100644 --- a/sound/soc/fsl/imx-pcm-rpmsg.c +++ b/sound/soc/fsl/imx-pcm-rpmsg.c @@ -743,14 +743,12 @@ fail: return ret; } -static int imx_rpmsg_pcm_remove(struct platform_device *pdev) +static void imx_rpmsg_pcm_remove(struct platform_device *pdev) { struct rpmsg_info *info = platform_get_drvdata(pdev); if (info->rpmsg_wq) destroy_workqueue(info->rpmsg_wq); - - return 0; } #ifdef CONFIG_PM @@ -821,7 +819,7 @@ static const struct dev_pm_ops imx_rpmsg_pcm_pm_ops = { static struct platform_driver imx_pcm_rpmsg_driver = { .probe = imx_rpmsg_pcm_probe, - .remove = imx_rpmsg_pcm_remove, + .remove_new = imx_rpmsg_pcm_remove, .driver = { .name = IMX_PCM_DRV_NAME, .pm = &imx_rpmsg_pcm_pm_ops, -- cgit From b8a148daa7969839c6bfbdd223dffa476dee4325 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:10 +0100 Subject: ASoC: fsl: imx-sgtl5000: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-79-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/imx-sgtl5000.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 580a0d963f0e..26c22783927b 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -193,14 +193,12 @@ fail: return ret; } -static int imx_sgtl5000_remove(struct platform_device *pdev) +static void imx_sgtl5000_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct imx_sgtl5000_data *data = snd_soc_card_get_drvdata(card); clk_put(data->codec_clk); - - return 0; } static const struct of_device_id imx_sgtl5000_dt_ids[] = { @@ -216,7 +214,7 @@ static struct platform_driver imx_sgtl5000_driver = { .of_match_table = imx_sgtl5000_dt_ids, }, .probe = imx_sgtl5000_probe, - .remove = imx_sgtl5000_remove, + .remove_new = imx_sgtl5000_remove, }; module_platform_driver(imx_sgtl5000_driver); -- cgit From 5ccf4bee004073af36e454c3f263a03d7a6ac72b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:11 +0100 Subject: ASoC: fsl: mpc5200_psc_ac97: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-80-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/mpc5200_psc_ac97.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index a082ae636a4f..40a4a2667394 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -311,12 +311,11 @@ static int psc_ac97_of_probe(struct platform_device *op) return 0; } -static int psc_ac97_of_remove(struct platform_device *op) +static void psc_ac97_of_remove(struct platform_device *op) { mpc5200_audio_dma_destroy(op); snd_soc_unregister_component(&op->dev); snd_soc_set_ac97_ops(NULL); - return 0; } /* Match table for of_platform binding */ @@ -329,7 +328,7 @@ MODULE_DEVICE_TABLE(of, psc_ac97_match); static struct platform_driver psc_ac97_driver = { .probe = psc_ac97_of_probe, - .remove = psc_ac97_of_remove, + .remove_new = psc_ac97_of_remove, .driver = { .name = "mpc5200-psc-ac97", .of_match_table = psc_ac97_match, -- cgit From 295dc79cfc05959f252546e34f0bddcc52aa7d8a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:12 +0100 Subject: ASoC: fsl: mpc5200_psc_i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-81-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/mpc5200_psc_i2s.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 73f3e61f208a..413df413b5eb 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -210,11 +210,10 @@ static int psc_i2s_of_probe(struct platform_device *op) } -static int psc_i2s_of_remove(struct platform_device *op) +static void psc_i2s_of_remove(struct platform_device *op) { mpc5200_audio_dma_destroy(op); snd_soc_unregister_component(&op->dev); - return 0; } /* Match table for of_platform binding */ @@ -227,7 +226,7 @@ MODULE_DEVICE_TABLE(of, psc_i2s_match); static struct platform_driver psc_i2s_driver = { .probe = psc_i2s_of_probe, - .remove = psc_i2s_of_remove, + .remove_new = psc_i2s_of_remove, .driver = { .name = "mpc5200-psc-i2s", .of_match_table = psc_i2s_match, -- cgit From 9c4d8f48ac4f38dbb23a546b8a5489d37f04f926 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:13 +0100 Subject: ASoC: fsl: mpc8610_hpcd: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-82-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/mpc8610_hpcd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index e71a992fbf93..ea2076ea8afe 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -387,7 +387,7 @@ error_alloc: * * This function is called when the platform device is removed. */ -static int mpc8610_hpcd_remove(struct platform_device *pdev) +static void mpc8610_hpcd_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct mpc8610_hpcd_data *machine_data = @@ -395,13 +395,11 @@ static int mpc8610_hpcd_remove(struct platform_device *pdev) snd_soc_unregister_card(card); kfree(machine_data); - - return 0; } static struct platform_driver mpc8610_hpcd_driver = { .probe = mpc8610_hpcd_probe, - .remove = mpc8610_hpcd_remove, + .remove_new = mpc8610_hpcd_remove, .driver = { /* The name must match 'compatible' property in the device tree, * in lowercase letters. -- cgit From 6a442e72940039bd69081320acdd4d7666f30a36 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:14 +0100 Subject: ASoC: fsl: p1022_ds: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-83-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/p1022_ds.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index b45742931b0d..0b1418abeb9c 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -396,7 +396,7 @@ error_put: * * This function is called when the platform device is removed. */ -static int p1022_ds_remove(struct platform_device *pdev) +static void p1022_ds_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct machine_data *mdata = @@ -404,13 +404,11 @@ static int p1022_ds_remove(struct platform_device *pdev) snd_soc_unregister_card(card); kfree(mdata); - - return 0; } static struct platform_driver p1022_ds_driver = { .probe = p1022_ds_probe, - .remove = p1022_ds_remove, + .remove_new = p1022_ds_remove, .driver = { /* * The name must match 'compatible' property in the device tree, -- cgit From ca4957d3b1f08c04e3ea510ebb419feda7b959c9 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:15 +0100 Subject: ASoC: fsl: p1022_rdk: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-84-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/p1022_rdk.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c index b395adabe823..4d85b742114c 100644 --- a/sound/soc/fsl/p1022_rdk.c +++ b/sound/soc/fsl/p1022_rdk.c @@ -345,7 +345,7 @@ error_put: * * This function is called when the platform device is removed. */ -static int p1022_rdk_remove(struct platform_device *pdev) +static void p1022_rdk_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct machine_data *mdata = @@ -353,13 +353,11 @@ static int p1022_rdk_remove(struct platform_device *pdev) snd_soc_unregister_card(card); kfree(mdata); - - return 0; } static struct platform_driver p1022_rdk_driver = { .probe = p1022_rdk_probe, - .remove = p1022_rdk_remove, + .remove_new = p1022_rdk_remove, .driver = { /* * The name must match 'compatible' property in the device tree, -- cgit From b7f036b9ff7f6accced758b21d4194d184709d95 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:16 +0100 Subject: ASoC: fsl: pcm030-audio-fabric: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-85-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/pcm030-audio-fabric.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index 997c3e66c636..d24c02e90878 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -109,14 +109,12 @@ static int pcm030_fabric_probe(struct platform_device *op) } -static int pcm030_fabric_remove(struct platform_device *op) +static void pcm030_fabric_remove(struct platform_device *op) { struct pcm030_audio_data *pdata = platform_get_drvdata(op); snd_soc_unregister_card(pdata->card); platform_device_unregister(pdata->codec_device); - - return 0; } static const struct of_device_id pcm030_audio_match[] = { @@ -127,7 +125,7 @@ MODULE_DEVICE_TABLE(of, pcm030_audio_match); static struct platform_driver pcm030_fabric_driver = { .probe = pcm030_fabric_probe, - .remove = pcm030_fabric_remove, + .remove_new = pcm030_fabric_remove, .driver = { .name = DRV_NAME, .of_match_table = pcm030_audio_match, -- cgit From 53946256cb7e9b4093f533fd42118cb6eda9ebb7 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:17 +0100 Subject: ASoC: generic: test-component: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-86-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/generic/test-component.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/generic/test-component.c b/sound/soc/generic/test-component.c index 98c8990596a8..e10e5bf28432 100644 --- a/sound/soc/generic/test-component.c +++ b/sound/soc/generic/test-component.c @@ -635,11 +635,9 @@ static int test_driver_probe(struct platform_device *pdev) return 0; } -static int test_driver_remove(struct platform_device *pdev) +static void test_driver_remove(struct platform_device *pdev) { mile_stone_x(&pdev->dev); - - return 0; } static struct platform_driver test_driver = { @@ -648,7 +646,7 @@ static struct platform_driver test_driver = { .of_match_table = test_of_match, }, .probe = test_driver_probe, - .remove = test_driver_remove, + .remove_new = test_driver_remove, }; module_platform_driver(test_driver); -- cgit From 4c9c73d88f927e7549852136ac82b8eb9978ceeb Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:18 +0100 Subject: ASoC: img: img-i2s-in: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-87-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/img/img-i2s-in.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c index 56bb7bbd3976..b7ab8467b5cf 100644 --- a/sound/soc/img/img-i2s-in.c +++ b/sound/soc/img/img-i2s-in.c @@ -532,13 +532,11 @@ err_pm_disable: return ret; } -static int img_i2s_in_dev_remove(struct platform_device *pdev) +static void img_i2s_in_dev_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) img_i2s_in_runtime_suspend(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -609,7 +607,7 @@ static struct platform_driver img_i2s_in_driver = { .pm = &img_i2s_in_pm_ops }, .probe = img_i2s_in_probe, - .remove = img_i2s_in_dev_remove + .remove_new = img_i2s_in_dev_remove }; module_platform_driver(img_i2s_in_driver); -- cgit From 3573bca8286daaaf191aece525e617415b88dfcb Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:19 +0100 Subject: ASoC: img: img-i2s-out: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-88-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/img/img-i2s-out.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/img/img-i2s-out.c b/sound/soc/img/img-i2s-out.c index abeff7829310..fe95ddfb8407 100644 --- a/sound/soc/img/img-i2s-out.c +++ b/sound/soc/img/img-i2s-out.c @@ -532,13 +532,11 @@ err_pm_disable: return ret; } -static int img_i2s_out_dev_remove(struct platform_device *pdev) +static void img_i2s_out_dev_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) img_i2s_out_runtime_suspend(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -609,7 +607,7 @@ static struct platform_driver img_i2s_out_driver = { .pm = &img_i2s_out_pm_ops }, .probe = img_i2s_out_probe, - .remove = img_i2s_out_dev_remove + .remove_new = img_i2s_out_dev_remove }; module_platform_driver(img_i2s_out_driver); -- cgit From 6a5e4aafe0fd1523f75974af1aec50c35a17dbb5 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:20 +0100 Subject: ASoC: img: img-parallel-out: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-89-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/img/img-parallel-out.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/img/img-parallel-out.c b/sound/soc/img/img-parallel-out.c index 08506b05e226..df1291ee2b3b 100644 --- a/sound/soc/img/img-parallel-out.c +++ b/sound/soc/img/img-parallel-out.c @@ -282,7 +282,7 @@ err_pm_disable: return ret; } -static int img_prl_out_dev_remove(struct platform_device *pdev) +static void img_prl_out_dev_remove(struct platform_device *pdev) { struct img_prl_out *prl = platform_get_drvdata(pdev); @@ -291,8 +291,6 @@ static int img_prl_out_dev_remove(struct platform_device *pdev) img_prl_out_suspend(&pdev->dev); clk_disable_unprepare(prl->clk_sys); - - return 0; } static const struct of_device_id img_prl_out_of_match[] = { @@ -313,7 +311,7 @@ static struct platform_driver img_prl_out_driver = { .pm = &img_prl_out_pm_ops }, .probe = img_prl_out_probe, - .remove = img_prl_out_dev_remove + .remove_new = img_prl_out_dev_remove }; module_platform_driver(img_prl_out_driver); -- cgit From 029a00ae9718571520f18ebdfb9ac5a633205d16 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:21 +0100 Subject: ASoC: img: img-spdif-in: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-90-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/img/img-spdif-in.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/img/img-spdif-in.c b/sound/soc/img/img-spdif-in.c index 3f1d1a7e8735..558062a1804a 100644 --- a/sound/soc/img/img-spdif-in.c +++ b/sound/soc/img/img-spdif-in.c @@ -810,13 +810,11 @@ err_pm_disable: return ret; } -static int img_spdif_in_dev_remove(struct platform_device *pdev) +static void img_spdif_in_dev_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) img_spdif_in_runtime_suspend(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -880,7 +878,7 @@ static struct platform_driver img_spdif_in_driver = { .pm = &img_spdif_in_pm_ops }, .probe = img_spdif_in_probe, - .remove = img_spdif_in_dev_remove + .remove_new = img_spdif_in_dev_remove }; module_platform_driver(img_spdif_in_driver); -- cgit From 4e894b2ec67c5c11cf9aa3d7c758102f02a3d08a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:22 +0100 Subject: ASoC: img: img-spdif-out: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-91-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/img/img-spdif-out.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/img/img-spdif-out.c b/sound/soc/img/img-spdif-out.c index 983761d3fa7e..b13e128e50d6 100644 --- a/sound/soc/img/img-spdif-out.c +++ b/sound/soc/img/img-spdif-out.c @@ -402,13 +402,11 @@ err_pm_disable: return ret; } -static int img_spdif_out_dev_remove(struct platform_device *pdev) +static void img_spdif_out_dev_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) img_spdif_out_runtime_suspend(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -470,7 +468,7 @@ static struct platform_driver img_spdif_out_driver = { .pm = &img_spdif_out_pm_ops }, .probe = img_spdif_out_probe, - .remove = img_spdif_out_dev_remove + .remove_new = img_spdif_out_dev_remove }; module_platform_driver(img_spdif_out_driver); -- cgit From ab44348955bfc3b9ca127dfb36d0c3231adacf07 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:23 +0100 Subject: ASoC: img: pistachio-internal-dac: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-92-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/img/pistachio-internal-dac.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/img/pistachio-internal-dac.c b/sound/soc/img/pistachio-internal-dac.c index e3b858643bd5..da6251680e41 100644 --- a/sound/soc/img/pistachio-internal-dac.c +++ b/sound/soc/img/pistachio-internal-dac.c @@ -215,15 +215,13 @@ err_regulator: return ret; } -static int pistachio_internal_dac_remove(struct platform_device *pdev) +static void pistachio_internal_dac_remove(struct platform_device *pdev) { struct pistachio_internal_dac *dac = dev_get_drvdata(&pdev->dev); pm_runtime_disable(&pdev->dev); pistachio_internal_dac_pwr_off(dac); regulator_disable(dac->supply); - - return 0; } #ifdef CONFIG_PM @@ -273,7 +271,7 @@ static struct platform_driver pistachio_internal_dac_plat_driver = { .pm = &pistachio_internal_dac_pm_ops }, .probe = pistachio_internal_dac_probe, - .remove = pistachio_internal_dac_remove + .remove_new = pistachio_internal_dac_remove }; module_platform_driver(pistachio_internal_dac_plat_driver); -- cgit From 0d31e8adf3e01cd344070ca33e51dac61b833bd0 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:24 +0100 Subject: ASoC: Intel: sst-mfld-platform-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-93-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst-mfld-platform-pcm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index c75616a5fd0a..ba4597bdf32e 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -741,10 +741,9 @@ static int sst_platform_probe(struct platform_device *pdev) return ret; } -static int sst_platform_remove(struct platform_device *pdev) +static void sst_platform_remove(struct platform_device *pdev) { dev_dbg(&pdev->dev, "sst_platform_remove success\n"); - return 0; } #ifdef CONFIG_PM_SLEEP @@ -813,7 +812,7 @@ static struct platform_driver sst_platform_driver = { .pm = &sst_platform_pm, }, .probe = sst_platform_probe, - .remove = sst_platform_remove, + .remove_new = sst_platform_remove, }; module_platform_driver(sst_platform_driver); -- cgit From c524f1674fc765b4adffd9329e89591169922269 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:25 +0100 Subject: ASoC: Intel: sst: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-94-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst/sst_acpi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index 3be64430c256..d3973936426a 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c @@ -335,14 +335,13 @@ static int sst_acpi_probe(struct platform_device *pdev) * This function is called by OS when a device is unloaded * This frees the interrupt etc */ -static int sst_acpi_remove(struct platform_device *pdev) +static void sst_acpi_remove(struct platform_device *pdev) { struct intel_sst_drv *ctx; ctx = platform_get_drvdata(pdev); sst_context_cleanup(ctx); platform_set_drvdata(pdev, NULL); - return 0; } static const struct acpi_device_id sst_acpi_ids[] = { @@ -360,7 +359,7 @@ static struct platform_driver sst_acpi_driver = { .pm = &intel_sst_pm, }, .probe = sst_acpi_probe, - .remove = sst_acpi_remove, + .remove_new = sst_acpi_remove, }; module_platform_driver(sst_acpi_driver); -- cgit From 9c5b13d50b2eb039a43af2d06a31813bff717fa7 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:26 +0100 Subject: ASoC: Intel: bytcht_es8316: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-95-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcht_es8316.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index df157b01df8b..7a30d2d36f19 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -628,7 +628,7 @@ err_put_codec: return ret; } -static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev) +static void snd_byt_cht_es8316_mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card); @@ -636,7 +636,6 @@ static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev) gpiod_put(priv->speaker_en_gpio); device_remove_software_node(priv->codec_dev); put_device(priv->codec_dev); - return 0; } static struct platform_driver snd_byt_cht_es8316_mc_driver = { @@ -644,7 +643,7 @@ static struct platform_driver snd_byt_cht_es8316_mc_driver = { .name = "bytcht_es8316", }, .probe = snd_byt_cht_es8316_mc_probe, - .remove = snd_byt_cht_es8316_mc_remove, + .remove_new = snd_byt_cht_es8316_mc_remove, }; module_platform_driver(snd_byt_cht_es8316_mc_driver); -- cgit From 2dc1d3c55d96973ded9c7fab8a22b7e323ae43e3 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:27 +0100 Subject: ASoC: Intel: bytcr_rt5640: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-96-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 79e0039c79a3..789609eb0884 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -1844,7 +1844,7 @@ err_device: return ret_val; } -static int snd_byt_rt5640_mc_remove(struct platform_device *pdev) +static void snd_byt_rt5640_mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); @@ -1854,7 +1854,6 @@ static int snd_byt_rt5640_mc_remove(struct platform_device *pdev) device_remove_software_node(priv->codec_dev); put_device(priv->codec_dev); - return 0; } static struct platform_driver snd_byt_rt5640_mc_driver = { @@ -1862,7 +1861,7 @@ static struct platform_driver snd_byt_rt5640_mc_driver = { .name = "bytcr_rt5640", }, .probe = snd_byt_rt5640_mc_probe, - .remove = snd_byt_rt5640_mc_remove, + .remove_new = snd_byt_rt5640_mc_remove, }; module_platform_driver(snd_byt_rt5640_mc_driver); -- cgit From 00f2ac22d63c54fbe2cc0a98a4f25c640b224b44 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:28 +0100 Subject: ASoC: Intel: boards: bytcr_rt5651: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-97-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5651.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 8fca9b82d4d0..805afaf47b29 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -1127,14 +1127,13 @@ err_device: return ret_val; } -static int snd_byt_rt5651_mc_remove(struct platform_device *pdev) +static void snd_byt_rt5651_mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card); device_remove_software_node(priv->codec_dev); put_device(priv->codec_dev); - return 0; } static struct platform_driver snd_byt_rt5651_mc_driver = { @@ -1142,7 +1141,7 @@ static struct platform_driver snd_byt_rt5651_mc_driver = { .name = "bytcr_rt5651", }, .probe = snd_byt_rt5651_mc_probe, - .remove = snd_byt_rt5651_mc_remove, + .remove_new = snd_byt_rt5651_mc_remove, }; module_platform_driver(snd_byt_rt5651_mc_driver); -- cgit From 2cd3f347aa0b82ab1c7ed8afe7e22234ac1b06f2 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:29 +0100 Subject: ASoC: Intel: bytcr_wm5102: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-98-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_wm5102.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c index c0706537f673..f2382d4cb76f 100644 --- a/sound/soc/intel/boards/bytcr_wm5102.c +++ b/sound/soc/intel/boards/bytcr_wm5102.c @@ -466,13 +466,12 @@ out_put_gpio: return ret; } -static int snd_byt_wm5102_mc_remove(struct platform_device *pdev) +static void snd_byt_wm5102_mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card); gpiod_put(priv->spkvdd_en_gpio); - return 0; } static struct platform_driver snd_byt_wm5102_mc_driver = { @@ -480,7 +479,7 @@ static struct platform_driver snd_byt_wm5102_mc_driver = { .name = "bytcr_wm5102", }, .probe = snd_byt_wm5102_mc_probe, - .remove = snd_byt_wm5102_mc_remove, + .remove_new = snd_byt_wm5102_mc_remove, }; module_platform_driver(snd_byt_wm5102_mc_driver); -- cgit From 76a32d30dce2b101592ac76b4d74ae9fc9b9309b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:30 +0100 Subject: ASoC: Intel: cht_bsw_max98090_ti: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-99-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_max98090_ti.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 2c086e901aae..850310de774b 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -623,15 +623,13 @@ static int snd_cht_mc_probe(struct platform_device *pdev) return ret_val; } -static int snd_cht_mc_remove(struct platform_device *pdev) +static void snd_cht_mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card); if (ctx->quirks & QUIRK_PMC_PLT_CLK_0) clk_disable_unprepare(ctx->mclk); - - return 0; } static struct platform_driver snd_cht_mc_driver = { @@ -639,7 +637,7 @@ static struct platform_driver snd_cht_mc_driver = { .name = "cht-bsw-max98090", }, .probe = snd_cht_mc_probe, - .remove = snd_cht_mc_remove, + .remove_new = snd_cht_mc_remove, }; module_platform_driver(snd_cht_mc_driver) -- cgit From c1f0f19e3f206354c7f5759456f0789776394d17 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:31 +0100 Subject: ASoC: Intel: sof_es8336: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-100-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_es8336.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c index 894b6610b9e2..adf5852b2c9a 100644 --- a/sound/soc/intel/boards/sof_es8336.c +++ b/sound/soc/intel/boards/sof_es8336.c @@ -780,7 +780,7 @@ err_put_codec: return ret; } -static int sof_es8336_remove(struct platform_device *pdev) +static void sof_es8336_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card); @@ -789,8 +789,6 @@ static int sof_es8336_remove(struct platform_device *pdev) gpiod_put(priv->gpio_speakers); device_remove_software_node(priv->codec_dev); put_device(priv->codec_dev); - - return 0; } static const struct platform_device_id board_ids[] = { @@ -817,7 +815,7 @@ static struct platform_driver sof_es8336_driver = { .pm = &snd_soc_pm_ops, }, .probe = sof_es8336_probe, - .remove = sof_es8336_remove, + .remove_new = sof_es8336_remove, .id_table = board_ids, }; module_platform_driver(sof_es8336_driver); -- cgit From b6c85e141938c353ff390c112d7b226872712429 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:32 +0100 Subject: ASoC: Intel: sof_pcm512x: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-101-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_pcm512x.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c index d4c67d5340a9..5192e02b3cee 100644 --- a/sound/soc/intel/boards/sof_pcm512x.c +++ b/sound/soc/intel/boards/sof_pcm512x.c @@ -416,7 +416,7 @@ static int sof_audio_probe(struct platform_device *pdev) &sof_audio_card_pcm512x); } -static int sof_pcm512x_remove(struct platform_device *pdev) +static void sof_pcm512x_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct snd_soc_component *component; @@ -427,13 +427,11 @@ static int sof_pcm512x_remove(struct platform_device *pdev) break; } } - - return 0; } static struct platform_driver sof_audio = { .probe = sof_audio_probe, - .remove = sof_pcm512x_remove, + .remove_new = sof_pcm512x_remove, .driver = { .name = "sof_pcm512x", .pm = &snd_soc_pm_ops, -- cgit From 51a4a7ecd85f9a714b47caa4d8c2ee7ea1e5b81f Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:33 +0100 Subject: ASoC: Intel: sof_sdw: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-102-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index d2ed807abde9..4ea69197791c 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1602,13 +1602,11 @@ static int mc_probe(struct platform_device *pdev) return ret; } -static int mc_remove(struct platform_device *pdev) +static void mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); mc_dailink_exit_loop(card); - - return 0; } static struct platform_driver sof_sdw_driver = { @@ -1617,7 +1615,7 @@ static struct platform_driver sof_sdw_driver = { .pm = &snd_soc_pm_ops, }, .probe = mc_probe, - .remove = mc_remove, + .remove_new = mc_remove, }; module_platform_driver(sof_sdw_driver); -- cgit From 674dd2c5f2b9466d9e8dfcd5e6f7a68d26fbc923 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:34 +0100 Subject: ASoC: Intel: sof_wm8804: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-103-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_wm8804.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_wm8804.c b/sound/soc/intel/boards/sof_wm8804.c index fbad5a73de44..17224d26d9d6 100644 --- a/sound/soc/intel/boards/sof_wm8804.c +++ b/sound/soc/intel/boards/sof_wm8804.c @@ -278,11 +278,10 @@ static int sof_wm8804_probe(struct platform_device *pdev) return devm_snd_soc_register_card(&pdev->dev, card); } -static int sof_wm8804_remove(struct platform_device *pdev) +static void sof_wm8804_remove(struct platform_device *pdev) { if (sof_wm8804_quirk & SOF_WM8804_UP2_QUIRK) gpiod_remove_lookup_table(&up2_gpios_table); - return 0; } static struct platform_driver sof_wm8804_driver = { @@ -291,7 +290,7 @@ static struct platform_driver sof_wm8804_driver = { .pm = &snd_soc_pm_ops, }, .probe = sof_wm8804_probe, - .remove = sof_wm8804_remove, + .remove_new = sof_wm8804_remove, }; module_platform_driver(sof_wm8804_driver); -- cgit From 4b6f92559390e016b6264b5f6d25f192ea83acba Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:35 +0100 Subject: ASoC: Intel: catpt: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-104-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/catpt/device.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/catpt/device.c b/sound/soc/intel/catpt/device.c index d5d08bd766c7..cac3dffbd0d9 100644 --- a/sound/soc/intel/catpt/device.c +++ b/sound/soc/intel/catpt/device.c @@ -293,7 +293,7 @@ static int catpt_acpi_probe(struct platform_device *pdev) return catpt_probe_components(cdev); } -static int catpt_acpi_remove(struct platform_device *pdev) +static void catpt_acpi_remove(struct platform_device *pdev) { struct catpt_dev *cdev = platform_get_drvdata(pdev); @@ -305,8 +305,6 @@ static int catpt_acpi_remove(struct platform_device *pdev) catpt_sram_free(&cdev->iram); catpt_sram_free(&cdev->dram); - - return 0; } static struct snd_soc_acpi_mach lpt_machines[] = { @@ -376,7 +374,7 @@ MODULE_DEVICE_TABLE(acpi, catpt_ids); static struct platform_driver catpt_acpi_driver = { .probe = catpt_acpi_probe, - .remove = catpt_acpi_remove, + .remove_new = catpt_acpi_remove, .driver = { .name = "intel_catpt", .acpi_match_table = catpt_ids, -- cgit From 394b2a11d9c238eb23e4fc087cc69f797b365f4b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:36 +0100 Subject: ASoC: Intel: skl-ssp-clk: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-105-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-ssp-clk.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/skylake/skl-ssp-clk.c b/sound/soc/intel/skylake/skl-ssp-clk.c index a3a73c26f9aa..50e93c3707e8 100644 --- a/sound/soc/intel/skylake/skl-ssp-clk.c +++ b/sound/soc/intel/skylake/skl-ssp-clk.c @@ -402,15 +402,13 @@ err_unreg_skl_clk: return ret; } -static int skl_clk_dev_remove(struct platform_device *pdev) +static void skl_clk_dev_remove(struct platform_device *pdev) { struct skl_clk_data *data; data = platform_get_drvdata(pdev); unregister_src_clk(data); unregister_parent_src_clk(data->parent, SKL_MAX_CLK_SRC); - - return 0; } static struct platform_driver skl_clk_driver = { @@ -418,7 +416,7 @@ static struct platform_driver skl_clk_driver = { .name = "skl-ssp-clk", }, .probe = skl_clk_dev_probe, - .remove = skl_clk_dev_remove, + .remove_new = skl_clk_dev_remove, }; module_platform_driver(skl_clk_driver); -- cgit From 8c078706e9862c7cd8bcb22d34133262024c26bf Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:37 +0100 Subject: ASoC: kirkwood: kirkwood-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Andrew Lunn Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-106-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/kirkwood/kirkwood-i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index afdf7d61e4c5..d1eb90310afa 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c @@ -736,7 +736,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev) return err; } -static int kirkwood_i2s_dev_remove(struct platform_device *pdev) +static void kirkwood_i2s_dev_remove(struct platform_device *pdev) { struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); @@ -744,8 +744,6 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev) if (!IS_ERR(priv->extclk)) clk_disable_unprepare(priv->extclk); clk_disable_unprepare(priv->clk); - - return 0; } #ifdef CONFIG_OF @@ -761,7 +759,7 @@ MODULE_DEVICE_TABLE(of, mvebu_audio_of_match); static struct platform_driver kirkwood_i2s_driver = { .probe = kirkwood_i2s_dev_probe, - .remove = kirkwood_i2s_dev_remove, + .remove_new = kirkwood_i2s_dev_remove, .driver = { .name = DRV_NAME, .of_match_table = of_match_ptr(mvebu_audio_of_match), -- cgit From 09f8cf0495b03dee0d567cebd4f47294c6293cd4 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:38 +0100 Subject: ASoC: mediatek: mtk-btcvsd: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-107-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-btcvsd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/common/mtk-btcvsd.c b/sound/soc/mediatek/common/mtk-btcvsd.c index 1c28b41e4311..1ba0633e542f 100644 --- a/sound/soc/mediatek/common/mtk-btcvsd.c +++ b/sound/soc/mediatek/common/mtk-btcvsd.c @@ -1387,13 +1387,12 @@ unmap_pkv_err: return ret; } -static int mtk_btcvsd_snd_remove(struct platform_device *pdev) +static void mtk_btcvsd_snd_remove(struct platform_device *pdev) { struct mtk_btcvsd_snd *btcvsd = dev_get_drvdata(&pdev->dev); iounmap(btcvsd->bt_pkv_base); iounmap(btcvsd->bt_sram_bank2_base); - return 0; } static const struct of_device_id mtk_btcvsd_snd_dt_match[] = { @@ -1408,7 +1407,7 @@ static struct platform_driver mtk_btcvsd_snd_driver = { .of_match_table = mtk_btcvsd_snd_dt_match, }, .probe = mtk_btcvsd_snd_probe, - .remove = mtk_btcvsd_snd_remove, + .remove_new = mtk_btcvsd_snd_remove, }; module_platform_driver(mtk_btcvsd_snd_driver); -- cgit From b3dff59e57a2d7c319590afe127a541917a06e1f Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:39 +0100 Subject: ASoC: mediatek: mt2701-afe-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-108-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c index 0f178de92a0f..c9d4420e9b4c 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c @@ -1439,14 +1439,12 @@ err_pm_disable: return ret; } -static int mt2701_afe_pcm_dev_remove(struct platform_device *pdev) +static void mt2701_afe_pcm_dev_remove(struct platform_device *pdev) { pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) mt2701_afe_runtime_suspend(&pdev->dev); - - return 0; } static const struct mt2701_soc_variants mt2701_soc_v1 = { @@ -1477,7 +1475,7 @@ static struct platform_driver mt2701_afe_pcm_driver = { .pm = &mt2701_afe_pm_ops, }, .probe = mt2701_afe_pcm_dev_probe, - .remove = mt2701_afe_pcm_dev_remove, + .remove_new = mt2701_afe_pcm_dev_remove, }; module_platform_driver(mt2701_afe_pcm_driver); -- cgit From edd8a5cde6c73d436b7970635b14a974b9a6e45c Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:40 +0100 Subject: ASoC: mediatek: mt6797-afe-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-109-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt6797/mt6797-afe-pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c index fb4abec9aa5f..43038444c43d 100644 --- a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c +++ b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c @@ -876,14 +876,12 @@ err_pm_disable: return ret; } -static int mt6797_afe_pcm_dev_remove(struct platform_device *pdev) +static void mt6797_afe_pcm_dev_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) mt6797_afe_runtime_suspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); - - return 0; } static const struct of_device_id mt6797_afe_pcm_dt_match[] = { @@ -904,7 +902,7 @@ static struct platform_driver mt6797_afe_pcm_driver = { .pm = &mt6797_afe_pm_ops, }, .probe = mt6797_afe_pcm_dev_probe, - .remove = mt6797_afe_pcm_dev_remove, + .remove_new = mt6797_afe_pcm_dev_remove, }; module_platform_driver(mt6797_afe_pcm_driver); -- cgit From 98a11bf9e7d904803fd4d91b909e3cad43719fba Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:41 +0100 Subject: ASoC: mediatek: mt8173-afe-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-110-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c index bc155dd937e0..f93c2ec8beb7 100644 --- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c @@ -1195,14 +1195,13 @@ err_pm_disable: return ret; } -static int mt8173_afe_pcm_dev_remove(struct platform_device *pdev) +static void mt8173_afe_pcm_dev_remove(struct platform_device *pdev) { snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) mt8173_afe_runtime_suspend(&pdev->dev); - return 0; } static const struct of_device_id mt8173_afe_pcm_dt_match[] = { @@ -1223,7 +1222,7 @@ static struct platform_driver mt8173_afe_pcm_driver = { .pm = &mt8173_afe_pm_ops, }, .probe = mt8173_afe_pcm_dev_probe, - .remove = mt8173_afe_pcm_dev_remove, + .remove_new = mt8173_afe_pcm_dev_remove, }; module_platform_driver(mt8173_afe_pcm_driver); -- cgit From 718041d46c4c69f86135f3e38c7295a41523d7bf Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:42 +0100 Subject: ASoC: mediatek: mt8183-afe-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-111-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c index 86c8a523fe9e..90422ed2bbcc 100644 --- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c +++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c @@ -1255,13 +1255,11 @@ err_pm_disable: return ret; } -static int mt8183_afe_pcm_dev_remove(struct platform_device *pdev) +static void mt8183_afe_pcm_dev_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) mt8183_afe_runtime_suspend(&pdev->dev); - - return 0; } static const struct of_device_id mt8183_afe_pcm_dt_match[] = { @@ -1282,7 +1280,7 @@ static struct platform_driver mt8183_afe_pcm_driver = { .pm = &mt8183_afe_pm_ops, }, .probe = mt8183_afe_pcm_dev_probe, - .remove = mt8183_afe_pcm_dev_remove, + .remove_new = mt8183_afe_pcm_dev_remove, }; module_platform_driver(mt8183_afe_pcm_driver); -- cgit From bb5ba5fe26ac53de23f1c85e97cb8cef31df343f Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:43 +0100 Subject: ASoC: mediatek: mt8188-afe-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Trevor Wu Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-112-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8188/mt8188-afe-pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c index e8e84de86542..e5f9373bed56 100644 --- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c +++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c @@ -3323,11 +3323,9 @@ err_pm_put: return ret; } -static int mt8188_afe_pcm_dev_remove(struct platform_device *pdev) +static void mt8188_afe_pcm_dev_remove(struct platform_device *pdev) { snd_soc_unregister_component(&pdev->dev); - - return 0; } static const struct of_device_id mt8188_afe_pcm_dt_match[] = { @@ -3348,7 +3346,7 @@ static struct platform_driver mt8188_afe_pcm_driver = { .pm = &mt8188_afe_pm_ops, }, .probe = mt8188_afe_pcm_dev_probe, - .remove = mt8188_afe_pcm_dev_remove, + .remove_new = mt8188_afe_pcm_dev_remove, }; module_platform_driver(mt8188_afe_pcm_driver); -- cgit From 26530339aca3e55cf44895303344ea6a91fa8bb1 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:44 +0100 Subject: ASoC: mediatek: mt8192-afe-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-113-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c index 333e0ee98c5a..d0520e7e1d79 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c @@ -2349,7 +2349,7 @@ err_pm_disable: return ret; } -static int mt8192_afe_pcm_dev_remove(struct platform_device *pdev) +static void mt8192_afe_pcm_dev_remove(struct platform_device *pdev) { struct mtk_base_afe *afe = platform_get_drvdata(pdev); @@ -2359,7 +2359,6 @@ static int mt8192_afe_pcm_dev_remove(struct platform_device *pdev) /* disable afe clock */ mt8192_afe_disable_clock(afe); - return 0; } static const struct of_device_id mt8192_afe_pcm_dt_match[] = { @@ -2380,7 +2379,7 @@ static struct platform_driver mt8192_afe_pcm_driver = { .pm = &mt8192_afe_pm_ops, }, .probe = mt8192_afe_pcm_dev_probe, - .remove = mt8192_afe_pcm_dev_remove, + .remove_new = mt8192_afe_pcm_dev_remove, }; module_platform_driver(mt8192_afe_pcm_driver); -- cgit From 6461fee68064ba970e3ba90241fe5f5e038aa9d4 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:45 +0100 Subject: ASoC: mediatek: mt8195-afe-pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: AngeloGioacchino Del Regno Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-114-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8195/mt8195-afe-pcm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c index 72b2c6d629b9..9e45efeada55 100644 --- a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c +++ b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c @@ -3253,7 +3253,7 @@ err_pm_put: return ret; } -static int mt8195_afe_pcm_dev_remove(struct platform_device *pdev) +static void mt8195_afe_pcm_dev_remove(struct platform_device *pdev) { struct mtk_base_afe *afe = platform_get_drvdata(pdev); @@ -3264,7 +3264,6 @@ static int mt8195_afe_pcm_dev_remove(struct platform_device *pdev) mt8195_afe_runtime_suspend(&pdev->dev); mt8195_afe_deinit_clock(afe); - return 0; } static const struct of_device_id mt8195_afe_pcm_dt_match[] = { @@ -3285,7 +3284,7 @@ static struct platform_driver mt8195_afe_pcm_driver = { .pm = &mt8195_afe_pm_ops, }, .probe = mt8195_afe_pcm_dev_probe, - .remove = mt8195_afe_pcm_dev_remove, + .remove_new = mt8195_afe_pcm_dev_remove, }; module_platform_driver(mt8195_afe_pcm_driver); -- cgit From ed354c69dd370ebac8c438d3570aade296afce05 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:46 +0100 Subject: ASoC: meson: aiu: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Martin Blumenstingl Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-115-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/meson/aiu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c index 88e611e64d14..da351a60df0c 100644 --- a/sound/soc/meson/aiu.c +++ b/sound/soc/meson/aiu.c @@ -331,11 +331,9 @@ err: return ret; } -static int aiu_remove(struct platform_device *pdev) +static void aiu_remove(struct platform_device *pdev) { snd_soc_unregister_component(&pdev->dev); - - return 0; } static const struct aiu_platform_data aiu_gxbb_pdata = { @@ -364,7 +362,7 @@ MODULE_DEVICE_TABLE(of, aiu_of_match); static struct platform_driver aiu_pdrv = { .probe = aiu_probe, - .remove = aiu_remove, + .remove_new = aiu_remove, .driver = { .name = "meson-aiu", .of_match_table = aiu_of_match, -- cgit From 75c1ed916145ecb5ae8a5e4a282aaea84fa9724e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:47 +0100 Subject: ASoC: mxs: mxs-sgtl5000: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-116-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-sgtl5000.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index a55e7256a4c3..457c3a72a414 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -169,11 +169,9 @@ static int mxs_sgtl5000_probe(struct platform_device *pdev) return 0; } -static int mxs_sgtl5000_remove(struct platform_device *pdev) +static void mxs_sgtl5000_remove(struct platform_device *pdev) { mxs_saif_put_mclk(0); - - return 0; } static const struct of_device_id mxs_sgtl5000_dt_ids[] = { @@ -188,7 +186,7 @@ static struct platform_driver mxs_sgtl5000_audio_driver = { .of_match_table = mxs_sgtl5000_dt_ids, }, .probe = mxs_sgtl5000_probe, - .remove = mxs_sgtl5000_remove, + .remove_new = mxs_sgtl5000_remove, }; module_platform_driver(mxs_sgtl5000_audio_driver); -- cgit From 15c71a4c84ba66f95c49b50fa934ab0395a1010f Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:48 +0100 Subject: ASoC: pxa: mmp-sspa: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-117-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index b3c1744eff91..a1ed141b8795 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -545,7 +545,7 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) return 0; } -static int asoc_mmp_sspa_remove(struct platform_device *pdev) +static void asoc_mmp_sspa_remove(struct platform_device *pdev) { struct sspa_priv *sspa = platform_get_drvdata(pdev); @@ -553,11 +553,10 @@ static int asoc_mmp_sspa_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); if (pdev->dev.of_node) - return 0; + return; clk_put(sspa->audio_clk); clk_put(sspa->sysclk); - return 0; } #ifdef CONFIG_OF @@ -575,7 +574,7 @@ static struct platform_driver asoc_mmp_sspa_driver = { .of_match_table = of_match_ptr(mmp_sspa_of_match), }, .probe = asoc_mmp_sspa_probe, - .remove = asoc_mmp_sspa_remove, + .remove_new = asoc_mmp_sspa_remove, }; module_platform_driver(asoc_mmp_sspa_driver); -- cgit From acb6a6982d6b83c08014f5110b443f4e8bca459b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:49 +0100 Subject: ASoC: pxa: pxa2xx-ac97: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-118-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/pxa/pxa2xx-ac97.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 809ea34736ed..e73bd62c033c 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -263,13 +263,12 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) pxa_ac97_dai_driver, ARRAY_SIZE(pxa_ac97_dai_driver)); } -static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) +static void pxa2xx_ac97_dev_remove(struct platform_device *pdev) { struct ac97_controller *ctrl = platform_get_drvdata(pdev); snd_ac97_controller_unregister(ctrl); pxa2xx_ac97_hw_remove(pdev); - return 0; } #ifdef CONFIG_PM_SLEEP @@ -289,7 +288,7 @@ static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops, static struct platform_driver pxa2xx_ac97_driver = { .probe = pxa2xx_ac97_dev_probe, - .remove = pxa2xx_ac97_dev_remove, + .remove_new = pxa2xx_ac97_dev_remove, .driver = { .name = "pxa2xx-ac97", #ifdef CONFIG_PM_SLEEP -- cgit From 60835c5c7d014cdb73166ee9e1b678d53562e3e1 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:50 +0100 Subject: ASoC: qcom: qdsp6: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-119-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6routing.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c index 928fd23e2c27..bba07899f8fc 100644 --- a/sound/soc/qcom/qdsp6/q6routing.c +++ b/sound/soc/qcom/qdsp6/q6routing.c @@ -1140,12 +1140,10 @@ static int q6pcm_routing_probe(struct platform_device *pdev) NULL, 0); } -static int q6pcm_routing_remove(struct platform_device *pdev) +static void q6pcm_routing_remove(struct platform_device *pdev) { kfree(routing_data); routing_data = NULL; - - return 0; } #ifdef CONFIG_OF @@ -1162,7 +1160,7 @@ static struct platform_driver q6pcm_routing_platform_driver = { .of_match_table = of_match_ptr(q6pcm_routing_device_id), }, .probe = q6pcm_routing_probe, - .remove = q6pcm_routing_remove, + .remove_new = q6pcm_routing_remove, }; module_platform_driver(q6pcm_routing_platform_driver); -- cgit From f348dd337e20e2e82b655062e613dbc63a6d4d01 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:51 +0100 Subject: ASoC: rockchip: rockchip_i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-120-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index a8758ad68442..79abec24a5a2 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -850,7 +850,7 @@ err_clk: return ret; } -static int rockchip_i2s_remove(struct platform_device *pdev) +static void rockchip_i2s_remove(struct platform_device *pdev) { struct rk_i2s_dev *i2s = dev_get_drvdata(&pdev->dev); @@ -859,8 +859,6 @@ static int rockchip_i2s_remove(struct platform_device *pdev) i2s_runtime_suspend(&pdev->dev); clk_disable_unprepare(i2s->hclk); - - return 0; } static const struct dev_pm_ops rockchip_i2s_pm_ops = { @@ -870,7 +868,7 @@ static const struct dev_pm_ops rockchip_i2s_pm_ops = { static struct platform_driver rockchip_i2s_driver = { .probe = rockchip_i2s_probe, - .remove = rockchip_i2s_remove, + .remove_new = rockchip_i2s_remove, .driver = { .name = DRV_NAME, .of_match_table = of_match_ptr(rockchip_i2s_match), -- cgit From 61785600e2b9513fe782857dd53ae9f920d6ff85 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:53 +0100 Subject: ASoC: rockchip: rockchip_pdm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-122-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_pdm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c index 6ce92b1db790..52f9aae60be8 100644 --- a/sound/soc/rockchip/rockchip_pdm.c +++ b/sound/soc/rockchip/rockchip_pdm.c @@ -661,7 +661,7 @@ err_pm_disable: return ret; } -static int rockchip_pdm_remove(struct platform_device *pdev) +static void rockchip_pdm_remove(struct platform_device *pdev) { struct rk_pdm_dev *pdm = dev_get_drvdata(&pdev->dev); @@ -671,8 +671,6 @@ static int rockchip_pdm_remove(struct platform_device *pdev) clk_disable_unprepare(pdm->clk); clk_disable_unprepare(pdm->hclk); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -710,7 +708,7 @@ static const struct dev_pm_ops rockchip_pdm_pm_ops = { static struct platform_driver rockchip_pdm_driver = { .probe = rockchip_pdm_probe, - .remove = rockchip_pdm_remove, + .remove_new = rockchip_pdm_remove, .driver = { .name = "rockchip-pdm", .of_match_table = of_match_ptr(rockchip_pdm_match), -- cgit From ed1e0f5a273c2dcbfede81831aa14c1039ad6930 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:54 +0100 Subject: ASoC: rockchip: rockchip_rt5645: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-123-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_rt5645.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/rockchip/rockchip_rt5645.c b/sound/soc/rockchip/rockchip_rt5645.c index d07cc5c813f2..e73a342b7953 100644 --- a/sound/soc/rockchip/rockchip_rt5645.c +++ b/sound/soc/rockchip/rockchip_rt5645.c @@ -206,14 +206,12 @@ put_codec_of_node: return ret; } -static int snd_rk_mc_remove(struct platform_device *pdev) +static void snd_rk_mc_remove(struct platform_device *pdev) { of_node_put(rk_dailink.cpus->of_node); rk_dailink.cpus->of_node = NULL; of_node_put(rk_dailink.codecs->of_node); rk_dailink.codecs->of_node = NULL; - - return 0; } static const struct of_device_id rockchip_rt5645_of_match[] = { @@ -225,7 +223,7 @@ MODULE_DEVICE_TABLE(of, rockchip_rt5645_of_match); static struct platform_driver snd_rk_mc_driver = { .probe = snd_rk_mc_probe, - .remove = snd_rk_mc_remove, + .remove_new = snd_rk_mc_remove, .driver = { .name = DRV_NAME, .pm = &snd_soc_pm_ops, -- cgit From cdce778344bc7f6c8b52027deab3f35cc05c4b3b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:55 +0100 Subject: ASoC: rockchip: rockchip_spdif: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-124-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_spdif.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c index 2d937fcf357d..0b73fe94e4bb 100644 --- a/sound/soc/rockchip/rockchip_spdif.c +++ b/sound/soc/rockchip/rockchip_spdif.c @@ -367,13 +367,11 @@ err_pm_runtime: return ret; } -static int rk_spdif_remove(struct platform_device *pdev) +static void rk_spdif_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) rk_spdif_runtime_suspend(&pdev->dev); - - return 0; } static const struct dev_pm_ops rk_spdif_pm_ops = { @@ -383,7 +381,7 @@ static const struct dev_pm_ops rk_spdif_pm_ops = { static struct platform_driver rk_spdif_driver = { .probe = rk_spdif_probe, - .remove = rk_spdif_remove, + .remove_new = rk_spdif_remove, .driver = { .name = "rockchip-spdif", .of_match_table = of_match_ptr(rk_spdif_match), -- cgit From 2149a1afa7f0d24164c7ae4ef66fdb98c607325c Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:56 +0100 Subject: ASoC: samsung: arndale: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-125-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/samsung/arndale.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/samsung/arndale.c b/sound/soc/samsung/arndale.c index a5dc640d0d76..fdff83e72d29 100644 --- a/sound/soc/samsung/arndale.c +++ b/sound/soc/samsung/arndale.c @@ -185,12 +185,11 @@ err_put_of_nodes: return ret; } -static int arndale_audio_remove(struct platform_device *pdev) +static void arndale_audio_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); arndale_put_of_nodes(card); - return 0; } static const struct of_device_id arndale_audio_of_match[] = { @@ -208,7 +207,7 @@ static struct platform_driver arndale_audio_driver = { .of_match_table = arndale_audio_of_match, }, .probe = arndale_audio_probe, - .remove = arndale_audio_remove, + .remove_new = arndale_audio_remove, }; module_platform_driver(arndale_audio_driver); -- cgit From 0b309358b8e461f3d99235d6b8b75cbffb61de57 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:57 +0100 Subject: ASoC: samsung: i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-126-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 083e278aa021..f3d98abd5f0d 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1560,13 +1560,13 @@ err_disable_clk: return ret; } -static int samsung_i2s_remove(struct platform_device *pdev) +static void samsung_i2s_remove(struct platform_device *pdev) { struct samsung_i2s_priv *priv = dev_get_drvdata(&pdev->dev); /* The secondary device has no driver data assigned */ if (!priv) - return 0; + return; pm_runtime_get_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -1576,8 +1576,6 @@ static int samsung_i2s_remove(struct platform_device *pdev) clk_disable_unprepare(priv->clk); pm_runtime_put_noidle(&pdev->dev); - - return 0; } static void fsd_i2s_fixup_early(struct snd_pcm_substream *substream, @@ -1746,7 +1744,7 @@ static const struct dev_pm_ops samsung_i2s_pm = { static struct platform_driver samsung_i2s_driver = { .probe = samsung_i2s_probe, - .remove = samsung_i2s_remove, + .remove_new = samsung_i2s_remove, .id_table = samsung_i2s_driver_ids, .driver = { .name = "samsung-i2s", -- cgit From d530e675e0189f68fc644668209eafc835d50efb Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:58 +0100 Subject: ASoC: samsung: odroid: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-127-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/samsung/odroid.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index 1e0fefa89ad5..fd95a79cc9fa 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -331,15 +331,13 @@ err_put_node: return ret; } -static int odroid_audio_remove(struct platform_device *pdev) +static void odroid_audio_remove(struct platform_device *pdev) { struct odroid_priv *priv = platform_get_drvdata(pdev); snd_soc_of_put_dai_link_codecs(&priv->card.dai_link[1]); clk_put(priv->sclk_i2s); clk_put(priv->clk_i2s_bus); - - return 0; } static const struct of_device_id odroid_audio_of_match[] = { @@ -358,7 +356,7 @@ static struct platform_driver odroid_audio_driver = { .pm = &snd_soc_pm_ops, }, .probe = odroid_audio_probe, - .remove = odroid_audio_remove, + .remove_new = odroid_audio_remove, }; module_platform_driver(odroid_audio_driver); -- cgit From 9f82db9dbb53567fc4c8de7a9fb41a8b6b4ea0e1 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:06:59 +0100 Subject: ASoC: samsung: pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-128-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/samsung/pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index e859252ae5e6..335fe5cb9cfc 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -579,20 +579,18 @@ err_dis_cclk: return ret; } -static int s3c_pcm_dev_remove(struct platform_device *pdev) +static void s3c_pcm_dev_remove(struct platform_device *pdev) { struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; pm_runtime_disable(&pdev->dev); clk_disable_unprepare(pcm->cclk); clk_disable_unprepare(pcm->pclk); - - return 0; } static struct platform_driver s3c_pcm_driver = { .probe = s3c_pcm_dev_probe, - .remove = s3c_pcm_dev_remove, + .remove_new = s3c_pcm_dev_remove, .driver = { .name = "samsung-pcm", }, -- cgit From 3224f4407d67c9504d9c779ebe79cd90be887cec Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:00 +0100 Subject: ASoC: samsung: snow: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-129-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/samsung/snow.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index da342da03880..334080e631af 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c @@ -219,7 +219,7 @@ static int snow_probe(struct platform_device *pdev) return 0; } -static int snow_remove(struct platform_device *pdev) +static void snow_remove(struct platform_device *pdev) { struct snow_priv *priv = platform_get_drvdata(pdev); struct snd_soc_dai_link *link = &priv->dai_link; @@ -229,8 +229,6 @@ static int snow_remove(struct platform_device *pdev) snd_soc_of_put_dai_link_codecs(link); clk_put(priv->clk_i2s_bus); - - return 0; } static const struct of_device_id snow_of_match[] = { @@ -248,7 +246,7 @@ static struct platform_driver snow_driver = { .of_match_table = snow_of_match, }, .probe = snow_probe, - .remove = snow_remove, + .remove_new = snow_remove, }; module_platform_driver(snow_driver); -- cgit From 7695582fd463ef3158d21253130cd2f1510c4e9a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:01 +0100 Subject: ASoC: samsung: spdif: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-130-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/samsung/spdif.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index 7d815e237e5c..28dc1bbfc8e7 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c @@ -460,7 +460,7 @@ err0: return ret; } -static int spdif_remove(struct platform_device *pdev) +static void spdif_remove(struct platform_device *pdev) { struct samsung_spdif_info *spdif = &spdif_info; struct resource *mem_res; @@ -472,13 +472,11 @@ static int spdif_remove(struct platform_device *pdev) clk_disable_unprepare(spdif->sclk); clk_disable_unprepare(spdif->pclk); - - return 0; } static struct platform_driver samsung_spdif_driver = { .probe = spdif_probe, - .remove = spdif_remove, + .remove_new = spdif_remove, .driver = { .name = "samsung-spdif", }, -- cgit From 08719f469b638c09c642896878a1e7c2b7e046c4 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:02 +0100 Subject: ASoC: sh: fsi: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Kuninori Morimoto Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-131-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sh/fsi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 9f3f1af6349f..1051c306292f 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -2030,7 +2030,7 @@ exit_fsia: return ret; } -static int fsi_remove(struct platform_device *pdev) +static void fsi_remove(struct platform_device *pdev) { struct fsi_master *master; @@ -2040,8 +2040,6 @@ static int fsi_remove(struct platform_device *pdev) fsi_stream_remove(&master->fsia); fsi_stream_remove(&master->fsib); - - return 0; } static void __fsi_suspend(struct fsi_priv *fsi, @@ -2108,7 +2106,7 @@ static struct platform_driver fsi_driver = { .of_match_table = fsi_of_match, }, .probe = fsi_probe, - .remove = fsi_remove, + .remove_new = fsi_remove, .id_table = fsi_id_table, }; -- cgit From 9baee32e889a646bba175fd365c4f807e42c4123 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:03 +0100 Subject: ASoC: sh: hac: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-132-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sh/hac.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c index 46d145cbaf29..cc200f45826c 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c @@ -323,10 +323,9 @@ static int hac_soc_platform_probe(struct platform_device *pdev) sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); } -static int hac_soc_platform_remove(struct platform_device *pdev) +static void hac_soc_platform_remove(struct platform_device *pdev) { snd_soc_set_ac97_ops(NULL); - return 0; } static struct platform_driver hac_pcm_driver = { @@ -335,7 +334,7 @@ static struct platform_driver hac_pcm_driver = { }, .probe = hac_soc_platform_probe, - .remove = hac_soc_platform_remove, + .remove_new = hac_soc_platform_remove, }; module_platform_driver(hac_pcm_driver); -- cgit From 5310f0a3315b7c7c6757b0d4b01733efd537049e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:04 +0100 Subject: ASoC: sh: rcar: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Kuninori Morimoto Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-133-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index cb17f7d0cf0c..6a522e6dd85a 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1987,7 +1987,7 @@ exit_snd_probe: return ret; } -static int rsnd_remove(struct platform_device *pdev) +static void rsnd_remove(struct platform_device *pdev) { struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); struct rsnd_dai *rdai; @@ -2019,8 +2019,6 @@ static int rsnd_remove(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(remove_func); i++) remove_func[i](priv); - - return 0; } static int __maybe_unused rsnd_suspend(struct device *dev) @@ -2052,7 +2050,7 @@ static struct platform_driver rsnd_driver = { .of_match_table = rsnd_of_match, }, .probe = rsnd_probe, - .remove = rsnd_remove, + .remove_new = rsnd_remove, }; module_platform_driver(rsnd_driver); -- cgit From b89438c71d72a9afbf72836630bfc995fed59e68 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:05 +0100 Subject: ASoC: sh: rz-ssi: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-134-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sh/rz-ssi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c index d502aa55c5a8..fe79eb90e1e5 100644 --- a/sound/soc/sh/rz-ssi.c +++ b/sound/soc/sh/rz-ssi.c @@ -1075,7 +1075,7 @@ err_reset: return ret; } -static int rz_ssi_remove(struct platform_device *pdev) +static void rz_ssi_remove(struct platform_device *pdev) { struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev); @@ -1084,8 +1084,6 @@ static int rz_ssi_remove(struct platform_device *pdev) pm_runtime_put(ssi->dev); pm_runtime_disable(ssi->dev); reset_control_assert(ssi->rstc); - - return 0; } static const struct of_device_id rz_ssi_of_match[] = { @@ -1100,7 +1098,7 @@ static struct platform_driver rz_ssi_driver = { .of_match_table = rz_ssi_of_match, }, .probe = rz_ssi_probe, - .remove = rz_ssi_remove, + .remove_new = rz_ssi_remove, }; module_platform_driver(rz_ssi_driver); -- cgit From 4136b45d25b2120355bbb8f35cc5102ec7e5b428 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:06 +0100 Subject: ASoC: sh: siu_dai: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-135-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sh/siu_dai.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c index f2a386fcd92e..84e1b14e68e4 100644 --- a/sound/soc/sh/siu_dai.c +++ b/sound/soc/sh/siu_dai.c @@ -778,10 +778,9 @@ static int siu_probe(struct platform_device *pdev) return 0; } -static int siu_remove(struct platform_device *pdev) +static void siu_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - return 0; } static struct platform_driver siu_driver = { @@ -789,7 +788,7 @@ static struct platform_driver siu_driver = { .name = "siu-pcm-audio", }, .probe = siu_probe, - .remove = siu_remove, + .remove_new = siu_remove, }; module_platform_driver(siu_driver); -- cgit From ed771e2beafa5687eba623fbde24d88ec61aa9aa Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:07 +0100 Subject: ASoC: sprd: sprd-mcdt: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-136-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sprd/sprd-mcdt.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sprd/sprd-mcdt.c b/sound/soc/sprd/sprd-mcdt.c index f6a55fa60c1b..688419c6b092 100644 --- a/sound/soc/sprd/sprd-mcdt.c +++ b/sound/soc/sprd/sprd-mcdt.c @@ -973,7 +973,7 @@ static int sprd_mcdt_probe(struct platform_device *pdev) return 0; } -static int sprd_mcdt_remove(struct platform_device *pdev) +static void sprd_mcdt_remove(struct platform_device *pdev) { struct sprd_mcdt_chan *chan, *temp; @@ -983,8 +983,6 @@ static int sprd_mcdt_remove(struct platform_device *pdev) list_del(&chan->list); mutex_unlock(&sprd_mcdt_list_mutex); - - return 0; } static const struct of_device_id sprd_mcdt_of_match[] = { @@ -995,7 +993,7 @@ MODULE_DEVICE_TABLE(of, sprd_mcdt_of_match); static struct platform_driver sprd_mcdt_driver = { .probe = sprd_mcdt_probe, - .remove = sprd_mcdt_remove, + .remove_new = sprd_mcdt_remove, .driver = { .name = "sprd-mcdt", .of_match_table = sprd_mcdt_of_match, -- cgit From 6cd293d206ad4b3c42854685a00b5e5d10a10aee Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:08 +0100 Subject: ASoC: stm: stm32_adfsdm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-137-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/stm/stm32_adfsdm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c index 837c1848d9bf..a8fff7378641 100644 --- a/sound/soc/stm/stm32_adfsdm.c +++ b/sound/soc/stm/stm32_adfsdm.c @@ -386,12 +386,10 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) return ret; } -static int stm32_adfsdm_remove(struct platform_device *pdev) +static void stm32_adfsdm_remove(struct platform_device *pdev) { snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static struct platform_driver stm32_adfsdm_driver = { @@ -400,7 +398,7 @@ static struct platform_driver stm32_adfsdm_driver = { .of_match_table = stm32_adfsdm_of_match, }, .probe = stm32_adfsdm_probe, - .remove = stm32_adfsdm_remove, + .remove_new = stm32_adfsdm_remove, }; module_platform_driver(stm32_adfsdm_driver); -- cgit From 607e4cf57396ebd5d4f45dfdf18933207704b1e5 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:09 +0100 Subject: ASoC: stm: stm32_i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-138-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/stm/stm32_i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index 9dad85ecb93f..387130701960 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -1097,13 +1097,11 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, return 0; } -static int stm32_i2s_remove(struct platform_device *pdev) +static void stm32_i2s_remove(struct platform_device *pdev) { snd_dmaengine_pcm_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static int stm32_i2s_probe(struct platform_device *pdev) @@ -1221,7 +1219,7 @@ static struct platform_driver stm32_i2s_driver = { .pm = &stm32_i2s_pm_ops, }, .probe = stm32_i2s_probe, - .remove = stm32_i2s_remove, + .remove_new = stm32_i2s_remove, }; module_platform_driver(stm32_i2s_driver); -- cgit From a3bd37e2e2bce4fb1757a940fa985d556662ba80 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:10 +0100 Subject: ASoC: stm: stm32_sai_sub: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-139-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai_sub.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 8ba4206f751d..f6695dee353b 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1559,7 +1559,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) return 0; } -static int stm32_sai_sub_remove(struct platform_device *pdev) +static void stm32_sai_sub_remove(struct platform_device *pdev) { struct stm32_sai_sub_data *sai = dev_get_drvdata(&pdev->dev); @@ -1567,8 +1567,6 @@ static int stm32_sai_sub_remove(struct platform_device *pdev) snd_dmaengine_pcm_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1618,7 +1616,7 @@ static struct platform_driver stm32_sai_sub_driver = { .pm = &stm32_sai_sub_pm_ops, }, .probe = stm32_sai_sub_probe, - .remove = stm32_sai_sub_remove, + .remove_new = stm32_sai_sub_remove, }; module_platform_driver(stm32_sai_sub_driver); -- cgit From c4d4ce48f8f59a464e4351258d2160a5215bb350 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:11 +0100 Subject: ASoC: stm: stm32_spdifrx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-140-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/stm/stm32_spdifrx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c index d399c906bb92..a4066f271f2d 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c @@ -939,7 +939,7 @@ static int stm32_spdifrx_parse_of(struct platform_device *pdev, return 0; } -static int stm32_spdifrx_remove(struct platform_device *pdev) +static void stm32_spdifrx_remove(struct platform_device *pdev) { struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev); @@ -952,8 +952,6 @@ static int stm32_spdifrx_remove(struct platform_device *pdev) snd_dmaengine_pcm_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static int stm32_spdifrx_probe(struct platform_device *pdev) @@ -1078,7 +1076,7 @@ static struct platform_driver stm32_spdifrx_driver = { .pm = &stm32_spdifrx_pm_ops, }, .probe = stm32_spdifrx_probe, - .remove = stm32_spdifrx_remove, + .remove_new = stm32_spdifrx_remove, }; module_platform_driver(stm32_spdifrx_driver); -- cgit From f56a1b1026ff2e04d6f8ac83d31be3bf163888ed Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:12 +0100 Subject: ASoC: sunxi: sun4i-codec: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Jernej Skrabec Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-141-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-codec.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 835dc3404367..55328850aef5 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -1821,7 +1821,7 @@ err_clk_disable: return ret; } -static int sun4i_codec_remove(struct platform_device *pdev) +static void sun4i_codec_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card); @@ -1830,8 +1830,6 @@ static int sun4i_codec_remove(struct platform_device *pdev) if (scodec->rst) reset_control_assert(scodec->rst); clk_disable_unprepare(scodec->clk_apb); - - return 0; } static struct platform_driver sun4i_codec_driver = { @@ -1840,7 +1838,7 @@ static struct platform_driver sun4i_codec_driver = { .of_match_table = sun4i_codec_of_match, }, .probe = sun4i_codec_probe, - .remove = sun4i_codec_remove, + .remove_new = sun4i_codec_remove, }; module_platform_driver(sun4i_codec_driver); -- cgit From 5423c00ee28f6cc3013b74bd1ac4090c625e91c2 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:13 +0100 Subject: ASoC: sunxi: sun4i-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Jernej Skrabec Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-142-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 6028871825ba..669d712bbe9f 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -1606,7 +1606,7 @@ err_pm_disable: return ret; } -static int sun4i_i2s_remove(struct platform_device *pdev) +static void sun4i_i2s_remove(struct platform_device *pdev) { struct sun4i_i2s *i2s = dev_get_drvdata(&pdev->dev); @@ -1616,8 +1616,6 @@ static int sun4i_i2s_remove(struct platform_device *pdev) if (!IS_ERR(i2s->rst)) reset_control_assert(i2s->rst); - - return 0; } static const struct of_device_id sun4i_i2s_match[] = { @@ -1660,7 +1658,7 @@ static const struct dev_pm_ops sun4i_i2s_pm_ops = { static struct platform_driver sun4i_i2s_driver = { .probe = sun4i_i2s_probe, - .remove = sun4i_i2s_remove, + .remove_new = sun4i_i2s_remove, .driver = { .name = "sun4i-i2s", .of_match_table = sun4i_i2s_match, -- cgit From b9d01c8254899d176ef4a387232bd8166ff769b6 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:14 +0100 Subject: ASoC: sunxi: sun4i-spdif: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Jernej Skrabec Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-143-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-spdif.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index bcceebca915a..ff18d4113aac 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -703,13 +703,11 @@ err_unregister: return ret; } -static int sun4i_spdif_remove(struct platform_device *pdev) +static void sun4i_spdif_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) sun4i_spdif_runtime_suspend(&pdev->dev); - - return 0; } static const struct dev_pm_ops sun4i_spdif_pm = { @@ -724,7 +722,7 @@ static struct platform_driver sun4i_spdif_driver = { .pm = &sun4i_spdif_pm, }, .probe = sun4i_spdif_probe, - .remove = sun4i_spdif_remove, + .remove_new = sun4i_spdif_remove, }; module_platform_driver(sun4i_spdif_driver); -- cgit From 116d6c70fa3da6123e1529c071b521ad16af3fa5 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:15 +0100 Subject: ASoC: sunxi: sun50i-dmic: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Ban Tao Acked-by: Jernej Skrabec Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-144-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sunxi/sun50i-dmic.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sunxi/sun50i-dmic.c b/sound/soc/sunxi/sun50i-dmic.c index 069c993acb31..c10439b9e0a2 100644 --- a/sound/soc/sunxi/sun50i-dmic.c +++ b/sound/soc/sunxi/sun50i-dmic.c @@ -373,13 +373,11 @@ err_disable_runtime_pm: return ret; } -static int sun50i_dmic_remove(struct platform_device *pdev) +static void sun50i_dmic_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) sun50i_dmic_runtime_suspend(&pdev->dev); - - return 0; } static const struct dev_pm_ops sun50i_dmic_pm = { @@ -394,7 +392,7 @@ static struct platform_driver sun50i_dmic_driver = { .pm = &sun50i_dmic_pm, }, .probe = sun50i_dmic_probe, - .remove = sun50i_dmic_remove, + .remove_new = sun50i_dmic_remove, }; module_platform_driver(sun50i_dmic_driver); -- cgit From a594f423aed833bbc1d8d25dc1f9e387d2c7fddb Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:16 +0100 Subject: ASoC: sunxi: sun8i-codec: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Jernej Skrabec Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-145-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/sunxi/sun8i-codec.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 9844978d91e6..4c0d0d7d3e58 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -1349,13 +1349,11 @@ err_pm_disable: return ret; } -static int sun8i_codec_remove(struct platform_device *pdev) +static void sun8i_codec_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) sun8i_codec_runtime_suspend(&pdev->dev); - - return 0; } static const struct sun8i_codec_quirks sun8i_a33_quirks = { @@ -1385,7 +1383,7 @@ static struct platform_driver sun8i_codec_driver = { .pm = &sun8i_codec_pm_ops, }, .probe = sun8i_codec_probe, - .remove = sun8i_codec_remove, + .remove_new = sun8i_codec_remove, }; module_platform_driver(sun8i_codec_driver); -- cgit From 1e482d82b813ab0ec1fb4c28f54f8728580eb515 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:17 +0100 Subject: ASoC: tegra: tegra186_asrc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-146-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra186_asrc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra186_asrc.c b/sound/soc/tegra/tegra186_asrc.c index 9f12faaa609d..e016a6a7f7c4 100644 --- a/sound/soc/tegra/tegra186_asrc.c +++ b/sound/soc/tegra/tegra186_asrc.c @@ -1016,11 +1016,9 @@ static int tegra186_asrc_platform_probe(struct platform_device *pdev) return 0; } -static int tegra186_asrc_platform_remove(struct platform_device *pdev) +static void tegra186_asrc_platform_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra186_asrc_pm_ops = { @@ -1037,7 +1035,7 @@ static struct platform_driver tegra186_asrc_driver = { .pm = &tegra186_asrc_pm_ops, }, .probe = tegra186_asrc_platform_probe, - .remove = tegra186_asrc_platform_remove, + .remove_new = tegra186_asrc_platform_remove, }; module_platform_driver(tegra186_asrc_driver) -- cgit From e04913cba6a651f9fbdfec397735a6df53ec0212 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:18 +0100 Subject: ASoC: tegra: tegra186_dspk: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-147-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra186_dspk.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c index a74c980ee775..a0ce7eb11de9 100644 --- a/sound/soc/tegra/tegra186_dspk.c +++ b/sound/soc/tegra/tegra186_dspk.c @@ -524,11 +524,9 @@ static int tegra186_dspk_platform_probe(struct platform_device *pdev) return 0; } -static int tegra186_dspk_platform_remove(struct platform_device *pdev) +static void tegra186_dspk_platform_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra186_dspk_pm_ops = { @@ -545,7 +543,7 @@ static struct platform_driver tegra186_dspk_driver = { .pm = &tegra186_dspk_pm_ops, }, .probe = tegra186_dspk_platform_probe, - .remove = tegra186_dspk_platform_remove, + .remove_new = tegra186_dspk_platform_remove, }; module_platform_driver(tegra186_dspk_driver); -- cgit From 41067828420de3250df957b2b0c50a33ba8e569e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:19 +0100 Subject: ASoC: tegra: tegra20_ac97: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-148-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_ac97.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index d23d88a10899..fea6955f7f43 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c @@ -429,7 +429,7 @@ err: return ret; } -static int tegra20_ac97_platform_remove(struct platform_device *pdev) +static void tegra20_ac97_platform_remove(struct platform_device *pdev) { struct tegra20_ac97 *ac97 = dev_get_drvdata(&pdev->dev); @@ -439,8 +439,6 @@ static int tegra20_ac97_platform_remove(struct platform_device *pdev) clk_disable_unprepare(ac97->clk_ac97); snd_soc_set_ac97_ops(NULL); - - return 0; } static const struct of_device_id tegra20_ac97_of_match[] = { @@ -454,7 +452,7 @@ static struct platform_driver tegra20_ac97_driver = { .of_match_table = tegra20_ac97_of_match, }, .probe = tegra20_ac97_platform_probe, - .remove = tegra20_ac97_platform_remove, + .remove_new = tegra20_ac97_platform_remove, }; module_platform_driver(tegra20_ac97_driver); -- cgit From 81ab73dbfe6864efbcf2c7d8effff0225cac286e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:20 +0100 Subject: ASoC: tegra: tegra20_i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-149-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index d37a9f2603e8..e1a0f50969c1 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -475,13 +475,11 @@ err: return ret; } -static int tegra20_i2s_platform_remove(struct platform_device *pdev) +static void tegra20_i2s_platform_remove(struct platform_device *pdev) { tegra_pcm_platform_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static const struct of_device_id tegra20_i2s_of_match[] = { @@ -503,7 +501,7 @@ static struct platform_driver tegra20_i2s_driver = { .pm = &tegra20_i2s_pm_ops, }, .probe = tegra20_i2s_platform_probe, - .remove = tegra20_i2s_platform_remove, + .remove_new = tegra20_i2s_platform_remove, }; module_platform_driver(tegra20_i2s_driver); -- cgit From 8097e8afb9f6ec2a5c47a325f66e0163eadcdd5a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:21 +0100 Subject: ASoC: tegra: tegra210_admaif: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-150-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_admaif.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c index 100a2b6e6063..6868508585a0 100644 --- a/sound/soc/tegra/tegra210_admaif.c +++ b/sound/soc/tegra/tegra210_admaif.c @@ -842,11 +842,9 @@ static int tegra_admaif_probe(struct platform_device *pdev) return 0; } -static int tegra_admaif_remove(struct platform_device *pdev) +static void tegra_admaif_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra_admaif_pm_ops = { @@ -858,7 +856,7 @@ static const struct dev_pm_ops tegra_admaif_pm_ops = { static struct platform_driver tegra_admaif_driver = { .probe = tegra_admaif_probe, - .remove = tegra_admaif_remove, + .remove_new = tegra_admaif_remove, .driver = { .name = "tegra210-admaif", .of_match_table = tegra_admaif_of_match, -- cgit From f129152cbce6ea54ff4a4cc05a263c2c2f105c06 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:22 +0100 Subject: ASoC: tegra: tegra210_adx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-151-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_adx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra210_adx.c b/sound/soc/tegra/tegra210_adx.c index 49691d2cce50..41117c1d61fb 100644 --- a/sound/soc/tegra/tegra210_adx.c +++ b/sound/soc/tegra/tegra210_adx.c @@ -504,11 +504,9 @@ static int tegra210_adx_platform_probe(struct platform_device *pdev) return 0; } -static int tegra210_adx_platform_remove(struct platform_device *pdev) +static void tegra210_adx_platform_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra210_adx_pm_ops = { @@ -525,7 +523,7 @@ static struct platform_driver tegra210_adx_driver = { .pm = &tegra210_adx_pm_ops, }, .probe = tegra210_adx_platform_probe, - .remove = tegra210_adx_platform_remove, + .remove_new = tegra210_adx_platform_remove, }; module_platform_driver(tegra210_adx_driver); -- cgit From f1790c464b21c42cbf5d56138c4f8791b25193f1 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:23 +0100 Subject: ASoC: tegra: tegra210_ahub: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-152-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_ahub.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c index b38d205b69cc..8c00c09eeefb 100644 --- a/sound/soc/tegra/tegra210_ahub.c +++ b/sound/soc/tegra/tegra210_ahub.c @@ -1410,11 +1410,9 @@ static int tegra_ahub_probe(struct platform_device *pdev) return 0; } -static int tegra_ahub_remove(struct platform_device *pdev) +static void tegra_ahub_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra_ahub_pm_ops = { @@ -1426,7 +1424,7 @@ static const struct dev_pm_ops tegra_ahub_pm_ops = { static struct platform_driver tegra_ahub_driver = { .probe = tegra_ahub_probe, - .remove = tegra_ahub_remove, + .remove_new = tegra_ahub_remove, .driver = { .name = "tegra210-ahub", .of_match_table = tegra_ahub_of_match, -- cgit From f3ac69d50c58340640b4e15466cbf32c0f040f67 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:24 +0100 Subject: ASoC: tegra: tegra210_amx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-153-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_amx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra210_amx.c b/sound/soc/tegra/tegra210_amx.c index d064cc67fea6..782a141b65c0 100644 --- a/sound/soc/tegra/tegra210_amx.c +++ b/sound/soc/tegra/tegra210_amx.c @@ -573,11 +573,9 @@ static int tegra210_amx_platform_probe(struct platform_device *pdev) return 0; } -static int tegra210_amx_platform_remove(struct platform_device *pdev) +static void tegra210_amx_platform_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra210_amx_pm_ops = { @@ -594,7 +592,7 @@ static struct platform_driver tegra210_amx_driver = { .pm = &tegra210_amx_pm_ops, }, .probe = tegra210_amx_platform_probe, - .remove = tegra210_amx_platform_remove, + .remove_new = tegra210_amx_platform_remove, }; module_platform_driver(tegra210_amx_driver); -- cgit From 7ffba01bcd3e5e4e6ebb13348b6d9975015ab9e2 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:25 +0100 Subject: ASoC: tegra: tegra210_dmic: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-154-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_dmic.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c index db95794530f4..763b206cd52b 100644 --- a/sound/soc/tegra/tegra210_dmic.c +++ b/sound/soc/tegra/tegra210_dmic.c @@ -534,11 +534,9 @@ static int tegra210_dmic_probe(struct platform_device *pdev) return 0; } -static int tegra210_dmic_remove(struct platform_device *pdev) +static void tegra210_dmic_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra210_dmic_pm_ops = { @@ -561,7 +559,7 @@ static struct platform_driver tegra210_dmic_driver = { .pm = &tegra210_dmic_pm_ops, }, .probe = tegra210_dmic_probe, - .remove = tegra210_dmic_remove, + .remove_new = tegra210_dmic_remove, }; module_platform_driver(tegra210_dmic_driver) -- cgit From e29df600149b08dc4b045da5c05df49c48b99436 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:26 +0100 Subject: ASoC: tegra: tegra210_i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-155-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c index 39ffa4d76b59..21724cd3525e 100644 --- a/sound/soc/tegra/tegra210_i2s.c +++ b/sound/soc/tegra/tegra210_i2s.c @@ -931,11 +931,9 @@ static int tegra210_i2s_probe(struct platform_device *pdev) return 0; } -static int tegra210_i2s_remove(struct platform_device *pdev) +static void tegra210_i2s_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra210_i2s_pm_ops = { @@ -958,7 +956,7 @@ static struct platform_driver tegra210_i2s_driver = { .pm = &tegra210_i2s_pm_ops, }, .probe = tegra210_i2s_probe, - .remove = tegra210_i2s_remove, + .remove_new = tegra210_i2s_remove, }; module_platform_driver(tegra210_i2s_driver) -- cgit From e0d782fad1f23dfa9d5b2e7144a433d502fd5845 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:27 +0100 Subject: ASoC: tegra: tegra210_mixer: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-156-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_mixer.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra210_mixer.c b/sound/soc/tegra/tegra210_mixer.c index 16e679a95658..035e9035b533 100644 --- a/sound/soc/tegra/tegra210_mixer.c +++ b/sound/soc/tegra/tegra210_mixer.c @@ -656,11 +656,9 @@ static int tegra210_mixer_platform_probe(struct platform_device *pdev) return 0; } -static int tegra210_mixer_platform_remove(struct platform_device *pdev) +static void tegra210_mixer_platform_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra210_mixer_pm_ops = { @@ -677,7 +675,7 @@ static struct platform_driver tegra210_mixer_driver = { .pm = &tegra210_mixer_pm_ops, }, .probe = tegra210_mixer_platform_probe, - .remove = tegra210_mixer_platform_remove, + .remove_new = tegra210_mixer_platform_remove, }; module_platform_driver(tegra210_mixer_driver); -- cgit From f94195ff022e5f39b6a1d4e2bcfa6f49dc32b4b7 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:28 +0100 Subject: ASoC: tegra: tegra210_mvc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-157-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_mvc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra210_mvc.c b/sound/soc/tegra/tegra210_mvc.c index 725385e17d84..44f465e11bee 100644 --- a/sound/soc/tegra/tegra210_mvc.c +++ b/sound/soc/tegra/tegra210_mvc.c @@ -748,11 +748,9 @@ static int tegra210_mvc_platform_probe(struct platform_device *pdev) return 0; } -static int tegra210_mvc_platform_remove(struct platform_device *pdev) +static void tegra210_mvc_platform_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra210_mvc_pm_ops = { @@ -769,7 +767,7 @@ static struct platform_driver tegra210_mvc_driver = { .pm = &tegra210_mvc_pm_ops, }, .probe = tegra210_mvc_platform_probe, - .remove = tegra210_mvc_platform_remove, + .remove_new = tegra210_mvc_platform_remove, }; module_platform_driver(tegra210_mvc_driver) -- cgit From 37831f8c144136ddb5a9f8794a5581bc8030f3f5 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:29 +0100 Subject: ASoC: tegra: tegra210_ope: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-158-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_ope.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra210_ope.c b/sound/soc/tegra/tegra210_ope.c index 3dd2bdec657b..98e726432615 100644 --- a/sound/soc/tegra/tegra210_ope.c +++ b/sound/soc/tegra/tegra210_ope.c @@ -347,11 +347,9 @@ static int tegra210_ope_probe(struct platform_device *pdev) return 0; } -static int tegra210_ope_remove(struct platform_device *pdev) +static void tegra210_ope_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static int __maybe_unused tegra210_ope_runtime_suspend(struct device *dev) @@ -410,7 +408,7 @@ static struct platform_driver tegra210_ope_driver = { .pm = &tegra210_ope_pm_ops, }, .probe = tegra210_ope_probe, - .remove = tegra210_ope_remove, + .remove_new = tegra210_ope_remove, }; module_platform_driver(tegra210_ope_driver) -- cgit From 0e25bed50aafe5d7fe46671f9bd4f3480ef19e10 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:30 +0100 Subject: ASoC: tegra: tegra210_sfc: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-159-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_sfc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra210_sfc.c b/sound/soc/tegra/tegra210_sfc.c index 368f077e7bee..e9df1ffc8a58 100644 --- a/sound/soc/tegra/tegra210_sfc.c +++ b/sound/soc/tegra/tegra210_sfc.c @@ -3584,11 +3584,9 @@ static int tegra210_sfc_platform_probe(struct platform_device *pdev) return 0; } -static int tegra210_sfc_platform_remove(struct platform_device *pdev) +static void tegra210_sfc_platform_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra210_sfc_pm_ops = { @@ -3605,7 +3603,7 @@ static struct platform_driver tegra210_sfc_driver = { .pm = &tegra210_sfc_pm_ops, }, .probe = tegra210_sfc_platform_probe, - .remove = tegra210_sfc_platform_remove, + .remove_new = tegra210_sfc_platform_remove, }; module_platform_driver(tegra210_sfc_driver) -- cgit From b17cf43d704bd556f866057af9e8c227e0c382ee Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:31 +0100 Subject: ASoC: tegra: tegra30_ahub: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-160-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_ahub.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index ef011a488ceb..d2e8078e444a 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -592,13 +592,11 @@ err_unset_ahub: return ret; } -static int tegra30_ahub_remove(struct platform_device *pdev) +static void tegra30_ahub_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); ahub = NULL; - - return 0; } static const struct dev_pm_ops tegra30_ahub_pm_ops = { @@ -610,7 +608,7 @@ static const struct dev_pm_ops tegra30_ahub_pm_ops = { static struct platform_driver tegra30_ahub_driver = { .probe = tegra30_ahub_probe, - .remove = tegra30_ahub_remove, + .remove_new = tegra30_ahub_remove, .driver = { .name = DRV_NAME, .of_match_table = tegra30_ahub_of_match, -- cgit From d148a8d46583590166711ff7c3f3644242b7563a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:32 +0100 Subject: ASoC: tegra: tegra30_i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-161-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index c26f960c6afd..644280603095 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -531,7 +531,7 @@ err: return ret; } -static int tegra30_i2s_platform_remove(struct platform_device *pdev) +static void tegra30_i2s_platform_remove(struct platform_device *pdev) { struct tegra30_i2s *i2s = dev_get_drvdata(&pdev->dev); @@ -545,8 +545,6 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev) tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif); pm_runtime_disable(&pdev->dev); - - return 0; } static const struct dev_pm_ops tegra30_i2s_pm_ops = { @@ -563,7 +561,7 @@ static struct platform_driver tegra30_i2s_driver = { .pm = &tegra30_i2s_pm_ops, }, .probe = tegra30_i2s_platform_probe, - .remove = tegra30_i2s_platform_remove, + .remove_new = tegra30_i2s_platform_remove, }; module_platform_driver(tegra30_i2s_driver); -- cgit From 2ade2cf2b00c8746f26ed64cb9bb32daa5efbed0 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:33 +0100 Subject: ASoC: ti: ams-delta: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-162-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/ti/ams-delta.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c index 438e2fa843a0..1028b5efcfff 100644 --- a/sound/soc/ti/ams-delta.c +++ b/sound/soc/ti/ams-delta.c @@ -578,7 +578,7 @@ static int ams_delta_probe(struct platform_device *pdev) return 0; } -static int ams_delta_remove(struct platform_device *pdev) +static void ams_delta_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); @@ -586,7 +586,6 @@ static int ams_delta_remove(struct platform_device *pdev) snd_soc_unregister_card(card); card->dev = NULL; - return 0; } #define DRV_NAME "ams-delta-audio" @@ -596,7 +595,7 @@ static struct platform_driver ams_delta_driver = { .name = DRV_NAME, }, .probe = ams_delta_probe, - .remove = ams_delta_remove, + .remove_new = ams_delta_remove, }; module_platform_driver(ams_delta_driver); -- cgit From a4d121f6f7e9d46a54abd7efed46112cee28188f Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:34 +0100 Subject: ASoC: ti: davinci-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-163-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index 3ccd0cfca008..97dd1634b6be 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -739,7 +739,7 @@ err_put_clk: return ret; } -static int davinci_i2s_remove(struct platform_device *pdev) +static void davinci_i2s_remove(struct platform_device *pdev) { struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); @@ -748,8 +748,6 @@ static int davinci_i2s_remove(struct platform_device *pdev) clk_disable(dev->clk); clk_put(dev->clk); dev->clk = NULL; - - return 0; } static const struct of_device_id davinci_i2s_match[] __maybe_unused = { @@ -760,7 +758,7 @@ MODULE_DEVICE_TABLE(of, davinci_i2s_match); static struct platform_driver davinci_mcbsp_driver = { .probe = davinci_i2s_probe, - .remove = davinci_i2s_remove, + .remove_new = davinci_i2s_remove, .driver = { .name = "davinci-mcbsp", .of_match_table = of_match_ptr(davinci_i2s_match), -- cgit From 09382b0150f0ced1d70330a11fe23c42137c0bd4 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:35 +0100 Subject: ASoC: ti: davinci-mcasp: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-164-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/ti/davinci-mcasp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 578254549d2d..c0892be2992b 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -2461,11 +2461,9 @@ err: return ret; } -static int davinci_mcasp_remove(struct platform_device *pdev) +static void davinci_mcasp_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } #ifdef CONFIG_PM @@ -2531,7 +2529,7 @@ static const struct dev_pm_ops davinci_mcasp_pm_ops = { static struct platform_driver davinci_mcasp_driver = { .probe = davinci_mcasp_probe, - .remove = davinci_mcasp_remove, + .remove_new = davinci_mcasp_remove, .driver = { .name = "davinci-mcasp", .pm = &davinci_mcasp_pm_ops, -- cgit From f12b0d036382dec00815780a3c2d998c1c92a422 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:36 +0100 Subject: ASoC: ti: omap-hdmi: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-165-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/ti/omap-hdmi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c index 0dc0475670ff..ad37785e05d8 100644 --- a/sound/soc/ti/omap-hdmi.c +++ b/sound/soc/ti/omap-hdmi.c @@ -398,12 +398,11 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) return 0; } -static int omap_hdmi_audio_remove(struct platform_device *pdev) +static void omap_hdmi_audio_remove(struct platform_device *pdev) { struct hdmi_audio_data *ad = platform_get_drvdata(pdev); snd_soc_unregister_card(ad->card); - return 0; } static struct platform_driver hdmi_audio_driver = { @@ -411,7 +410,7 @@ static struct platform_driver hdmi_audio_driver = { .name = DRV_NAME, }, .probe = omap_hdmi_audio_probe, - .remove = omap_hdmi_audio_remove, + .remove_new = omap_hdmi_audio_remove, }; module_platform_driver(hdmi_audio_driver); -- cgit From 9b6818bb3c58de41f987554bf27db3058c5e6838 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:37 +0100 Subject: ASoC: ti: omap-mcbsp: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-166-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/ti/omap-mcbsp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c index 7c539a41a6a3..21fa7b978799 100644 --- a/sound/soc/ti/omap-mcbsp.c +++ b/sound/soc/ti/omap-mcbsp.c @@ -1412,7 +1412,7 @@ static int asoc_mcbsp_probe(struct platform_device *pdev) return sdma_pcm_platform_register(&pdev->dev, "tx", "rx"); } -static int asoc_mcbsp_remove(struct platform_device *pdev) +static void asoc_mcbsp_remove(struct platform_device *pdev) { struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); @@ -1421,8 +1421,6 @@ static int asoc_mcbsp_remove(struct platform_device *pdev) if (cpu_latency_qos_request_active(&mcbsp->pm_qos_req)) cpu_latency_qos_remove_request(&mcbsp->pm_qos_req); - - return 0; } static struct platform_driver asoc_mcbsp_driver = { @@ -1432,7 +1430,7 @@ static struct platform_driver asoc_mcbsp_driver = { }, .probe = asoc_mcbsp_probe, - .remove = asoc_mcbsp_remove, + .remove_new = asoc_mcbsp_remove, }; module_platform_driver(asoc_mcbsp_driver); -- cgit From 048d658978107f1a6b517297acb2eb08dd70b4c7 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:38 +0100 Subject: ASoC: uniphier: evea: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-167-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/uniphier/evea.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/uniphier/evea.c b/sound/soc/uniphier/evea.c index 42403ae8e31b..d90b3e4b0104 100644 --- a/sound/soc/uniphier/evea.c +++ b/sound/soc/uniphier/evea.c @@ -536,7 +536,7 @@ err_out_clock: return ret; } -static int evea_remove(struct platform_device *pdev) +static void evea_remove(struct platform_device *pdev) { struct evea_priv *evea = platform_get_drvdata(pdev); @@ -546,8 +546,6 @@ static int evea_remove(struct platform_device *pdev) clk_disable_unprepare(evea->clk_exiv); clk_disable_unprepare(evea->clk); - - return 0; } static const struct of_device_id evea_of_match[] __maybe_unused = { @@ -562,7 +560,7 @@ static struct platform_driver evea_codec_driver = { .of_match_table = of_match_ptr(evea_of_match), }, .probe = evea_probe, - .remove = evea_remove, + .remove_new = evea_remove, }; module_platform_driver(evea_codec_driver); -- cgit From d2b6d5b85a651f4678e7c8343df4d93cc736489b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:39 +0100 Subject: ASoC: ux500: mop500: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Linus Walleij Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-168-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/ux500/mop500.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 325e75e96136..e0ab4534fe3e 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c @@ -134,7 +134,7 @@ static int mop500_probe(struct platform_device *pdev) return ret; } -static int mop500_remove(struct platform_device *pdev) +static void mop500_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); @@ -143,8 +143,6 @@ static int mop500_remove(struct platform_device *pdev) snd_soc_unregister_card(card); mop500_ab8500_remove(card); mop500_of_node_put(); - - return 0; } static const struct of_device_id snd_soc_mop500_match[] = { @@ -159,7 +157,7 @@ static struct platform_driver snd_soc_mop500_driver = { .of_match_table = snd_soc_mop500_match, }, .probe = mop500_probe, - .remove = mop500_remove, + .remove_new = mop500_remove, }; module_platform_driver(snd_soc_mop500_driver); -- cgit From 316a6bbfb878b710cd0c28c4fcce47a299bbd64c Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:40 +0100 Subject: ASoC: ux500: ux500_msp_dai: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Linus Walleij Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-169-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/ux500/ux500_msp_dai.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 6fb1a5c207bc..44e88dad8584 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -791,7 +791,7 @@ err_reg_plat: return ret; } -static int ux500_msp_drv_remove(struct platform_device *pdev) +static void ux500_msp_drv_remove(struct platform_device *pdev) { struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(&pdev->dev); @@ -802,8 +802,6 @@ static int ux500_msp_drv_remove(struct platform_device *pdev) prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s"); ux500_msp_i2s_cleanup_msp(pdev, drvdata->msp); - - return 0; } static const struct of_device_id ux500_msp_i2s_match[] = { @@ -818,7 +816,7 @@ static struct platform_driver msp_i2s_driver = { .of_match_table = ux500_msp_i2s_match, }, .probe = ux500_msp_drv_probe, - .remove = ux500_msp_drv_remove, + .remove_new = ux500_msp_drv_remove, }; module_platform_driver(msp_i2s_driver); -- cgit From bf6b5ced96cdaec0af1621ecd4f245a907ed3b06 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:41 +0100 Subject: ASoC: xilinx: xlnx_formatter_pcm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-170-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/xilinx/xlnx_formatter_pcm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/xilinx/xlnx_formatter_pcm.c b/sound/soc/xilinx/xlnx_formatter_pcm.c index ff1fe62fea70..299cfb5e2022 100644 --- a/sound/soc/xilinx/xlnx_formatter_pcm.c +++ b/sound/soc/xilinx/xlnx_formatter_pcm.c @@ -687,7 +687,7 @@ clk_err: return ret; } -static int xlnx_formatter_pcm_remove(struct platform_device *pdev) +static void xlnx_formatter_pcm_remove(struct platform_device *pdev) { int ret = 0; struct xlnx_pcm_drv_data *adata = dev_get_drvdata(&pdev->dev); @@ -703,7 +703,6 @@ static int xlnx_formatter_pcm_remove(struct platform_device *pdev) dev_err(&pdev->dev, "audio formatter reset failed\n"); clk_disable_unprepare(adata->axi_clk); - return 0; } static const struct of_device_id xlnx_formatter_pcm_of_match[] = { @@ -714,7 +713,7 @@ MODULE_DEVICE_TABLE(of, xlnx_formatter_pcm_of_match); static struct platform_driver xlnx_formatter_pcm_driver = { .probe = xlnx_formatter_pcm_probe, - .remove = xlnx_formatter_pcm_remove, + .remove_new = xlnx_formatter_pcm_remove, .driver = { .name = DRV_NAME, .of_match_table = xlnx_formatter_pcm_of_match, -- cgit From 407a27b72e168aac1c192c4b977cc3ad6b41caa2 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:42 +0100 Subject: ASoC: xilinx: xlnx_spdif: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-171-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/xilinx/xlnx_spdif.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/xilinx/xlnx_spdif.c b/sound/soc/xilinx/xlnx_spdif.c index 7342048e9875..d52d5fc7b5b8 100644 --- a/sound/soc/xilinx/xlnx_spdif.c +++ b/sound/soc/xilinx/xlnx_spdif.c @@ -312,12 +312,11 @@ clk_err: return ret; } -static int xlnx_spdif_remove(struct platform_device *pdev) +static void xlnx_spdif_remove(struct platform_device *pdev) { struct spdif_dev_data *ctx = dev_get_drvdata(&pdev->dev); clk_disable_unprepare(ctx->axi_clk); - return 0; } static struct platform_driver xlnx_spdif_driver = { @@ -326,7 +325,7 @@ static struct platform_driver xlnx_spdif_driver = { .of_match_table = xlnx_spdif_of_match, }, .probe = xlnx_spdif_probe, - .remove = xlnx_spdif_remove, + .remove_new = xlnx_spdif_remove, }; module_platform_driver(xlnx_spdif_driver); -- cgit From cbde81bc5573ddade3d2560fe7b5e4fa80db8f7b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:43 +0100 Subject: ASoC: xtensa: xtfpga-i2s: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-172-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/xtensa/xtfpga-i2s.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c index a8f156540b50..287407714af4 100644 --- a/sound/soc/xtensa/xtfpga-i2s.c +++ b/sound/soc/xtensa/xtfpga-i2s.c @@ -605,7 +605,7 @@ err: return err; } -static int xtfpga_i2s_remove(struct platform_device *pdev) +static void xtfpga_i2s_remove(struct platform_device *pdev) { struct xtfpga_i2s *i2s = dev_get_drvdata(&pdev->dev); @@ -618,7 +618,6 @@ static int xtfpga_i2s_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) xtfpga_i2s_runtime_suspend(&pdev->dev); - return 0; } #ifdef CONFIG_OF @@ -636,7 +635,7 @@ static const struct dev_pm_ops xtfpga_i2s_pm_ops = { static struct platform_driver xtfpga_i2s_driver = { .probe = xtfpga_i2s_probe, - .remove = xtfpga_i2s_remove, + .remove_new = xtfpga_i2s_remove, .driver = { .name = "xtfpga-i2s", .of_match_table = of_match_ptr(xtfpga_i2s_of_match), -- cgit From 44e4b6ee0486e301bfd8f4b2948905893bcf1314 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:44 +0100 Subject: ALSA: sparc/cs4231: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-173-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/sparc/cs4231.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 2942c8c7a236..31bac355ec4d 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -2069,13 +2069,11 @@ static int cs4231_probe(struct platform_device *op) return -ENODEV; } -static int cs4231_remove(struct platform_device *op) +static void cs4231_remove(struct platform_device *op) { struct snd_cs4231 *chip = dev_get_drvdata(&op->dev); snd_card_free(chip->card); - - return 0; } static const struct of_device_id cs4231_match[] = { @@ -2097,7 +2095,7 @@ static struct platform_driver cs4231_driver = { .of_match_table = cs4231_match, }, .probe = cs4231_probe, - .remove = cs4231_remove, + .remove_new = cs4231_remove, }; module_platform_driver(cs4231_driver); -- cgit From 9fa6137d0c7843209472bb07277f9fcffa80847a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 15 Mar 2023 16:07:45 +0100 Subject: ALSA: sparc/dbri: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Takashi Iwai Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/20230315150745.67084-174-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/sparc/dbri.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 3881e1c1b08a..376aed136a45 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -2656,14 +2656,12 @@ _err: return err; } -static int dbri_remove(struct platform_device *op) +static void dbri_remove(struct platform_device *op) { struct snd_card *card = dev_get_drvdata(&op->dev); snd_dbri_free(card->private_data); snd_card_free(card); - - return 0; } static const struct of_device_id dbri_match[] = { @@ -2684,7 +2682,7 @@ static struct platform_driver dbri_sbus_driver = { .of_match_table = dbri_match, }, .probe = dbri_probe, - .remove = dbri_remove, + .remove_new = dbri_remove, }; module_platform_driver(dbri_sbus_driver); -- cgit From 0e6c37610934e9b91f6f5f2599de5e2f1ab59e72 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Wed, 15 Mar 2023 13:48:03 +0200 Subject: ASoC: rockchip: i2s: Add compatible for RK3588 The Rockchip I2S driver supports the RK3588/RK3588S SoCs, hence add the corresponding compatible string. Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20230315114806.3819515-9-cristian.ciocaltea@collabora.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_i2s.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index a8758ad68442..2e24cc0570eb 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -659,6 +659,7 @@ static const struct of_device_id rockchip_i2s_match[] __maybe_unused = { { .compatible = "rockchip,rk3366-i2s", }, { .compatible = "rockchip,rk3368-i2s", }, { .compatible = "rockchip,rk3399-i2s", .data = &rk3399_i2s_pins }, + { .compatible = "rockchip,rk3588-i2s", }, { .compatible = "rockchip,rv1126-i2s", }, {}, }; -- cgit From 1d52cba3b99278f178bfadf88e666648a217a813 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Thu, 16 Mar 2023 13:36:10 +0100 Subject: ASoC: fsl: define a common DRIVER_NAME Instead of copying the driver name manually, use a common define. No functional change. Signed-off-by: Alexander Stein Acked-by: Shengjiu Wang Link: https://lore.kernel.org/r/20230316123611.3495597-1-alexander.stein@ew.tq-group.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl-asoc-card.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index cdfca9fd1eb0..e956abfd50f8 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -28,6 +28,8 @@ #include "../codecs/wm8994.h" #include "../codecs/tlv320aic31xx.h" +#define DRIVER_NAME "fsl-asoc-card" + #define CS427x_SYSCLK_MCLK 0 #define RX 0 @@ -915,7 +917,7 @@ MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids); static struct platform_driver fsl_asoc_card_driver = { .probe = fsl_asoc_card_probe, .driver = { - .name = "fsl-asoc-card", + .name = DRIVER_NAME, .pm = &snd_soc_pm_ops, .of_match_table = fsl_asoc_card_dt_ids, }, @@ -924,5 +926,5 @@ module_platform_driver(fsl_asoc_card_driver); MODULE_DESCRIPTION("Freescale Generic ASoC Sound Card driver with ASRC"); MODULE_AUTHOR("Nicolin Chen "); -MODULE_ALIAS("platform:fsl-asoc-card"); +MODULE_ALIAS("platform:" DRIVER_NAME); MODULE_LICENSE("GPL"); -- cgit From 9934844f6b49fb9964f878f12912abe689eaed5d Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Thu, 16 Mar 2023 13:36:11 +0100 Subject: ASoC: fsl: Specify driver name in ASoC card Set the snd_soc_card driver name which fixes the warning: fsl-asoc-card sound: ASoC: driver name too long 'imx-audio-tlv320aic32x4' -> 'imx-audio-tlv32' Signed-off-by: Alexander Stein Acked-by: Shengjiu Wang Link: https://lore.kernel.org/r/20230316123611.3495597-2-alexander.stein@ew.tq-group.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl-asoc-card.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index e956abfd50f8..bffa1048d31e 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -609,6 +609,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->card.dapm_routes = audio_map; priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); + priv->card.driver_name = DRIVER_NAME; /* Diversify the card configurations */ if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) { codec_dai_name = "cs42888"; -- cgit From 00a7ef3242f42c38c9ffdf14ab2d729fd9754391 Mon Sep 17 00:00:00 2001 From: Jianhua Lu Date: Sat, 18 Mar 2023 22:14:39 +0800 Subject: ASoC: cs35l41: Add 12288000 clk freq to cs35l41_fs_mon clk config There are 8 cs35l41 speaker amplifier connected to TDM in my Xiaomi Mi Pad 5 Pro tablet. In this case, it's necessary to set 12288000 (48000 * 32 * 8) clk freq for it. rate=48000, slot_width=32, slots=8. Signed-off-by: Jianhua Lu Reviewed-by: David Rhodes Link: https://lore.kernel.org/r/20230318141440.29023-1-lujianhua000@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l41.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index 9ec01a5f09ca..6ac501f008ec 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -150,6 +150,7 @@ static const struct cs35l41_fs_mon_config cs35l41_fs_mon[] = { { 5644800, 16, 24 }, { 6000000, 16, 24 }, { 6144000, 16, 24 }, + { 12288000, 0, 0 }, }; static int cs35l41_get_fs_mon_config_index(int freq) -- cgit From 0cd1fd571719e19bd6824a98855382a70e47d932 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 20 Mar 2023 11:22:39 +0000 Subject: ASoC: wm_adsp: Use no_core_startstop to prevent creating preload control The no_core_startstop flag indicates a self-booting DSP - they are considered to be always running and therefore cannot be pre-loaded. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230320112245.115720-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index ea0dbc634ecf..854d9366a745 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1102,8 +1102,10 @@ int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *comp { char preload[32]; - snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->cs_dsp.name); - snd_soc_component_disable_pin(component, preload); + if (!dsp->cs_dsp.no_core_startstop) { + snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->cs_dsp.name); + snd_soc_component_disable_pin(component, preload); + } cs_dsp_init_debugfs(&dsp->cs_dsp, component->debugfs_root); -- cgit From 65a314b7ddc09f6b1bad8decc6670e68d45ef07d Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 20 Mar 2023 11:22:41 +0000 Subject: ASoC: wm_adsp: Support DSPs that don't require firmware download When a DSP can self-boot from ROM it is not necessary to download firmware - when the DSP has the wmfw_optional flag set not finding a wmfw firmware file is a successful outcome and not an error condition. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/167931140130.26.15590061696793062038@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 3 +++ sound/soc/codecs/wm_adsp.h | 1 + 2 files changed, 4 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 854d9366a745..8176b6173de9 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -850,6 +850,9 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, return 0; } + if (dsp->wmfw_optional) + return 0; + adsp_err(dsp, "Failed to request firmware <%s>%s-%s-%s<-%s<%s>>.wmfw\n", cirrus_dir, dsp->part, dsp->fwf_name, wm_adsp_fw[dsp->fw].file, system_name, asoc_component_prefix); diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index dc2f7a096e26..173dcae2c260 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -34,6 +34,7 @@ struct wm_adsp { unsigned int sys_config_size; int fw; + bool wmfw_optional; struct work_struct boot_work; int (*pre_run)(struct wm_adsp *dsp); -- cgit From 11520b87e2232c6e3defed69ec94f0e28fb80f84 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 20 Mar 2023 11:22:42 +0000 Subject: ASoC: wm_adsp: Expose the DSP boot work actions as wm_adsp_power_up() To support self-booting DSPs that are considered always running, the work that is usually invoked as part of a DAPM sequence needs to be triggered by a client of wm_adsp as part of it's startup sequence. These actions load firmware files that might create ALSA controls and apply configuration to the device. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230320112245.115720-6-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 27 ++++++++++++++++++--------- sound/soc/codecs/wm_adsp.h | 2 ++ 2 files changed, 20 insertions(+), 9 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 8176b6173de9..d4bffa2f7005 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -998,11 +998,8 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put); -static void wm_adsp_boot_work(struct work_struct *work) +int wm_adsp_power_up(struct wm_adsp *dsp) { - struct wm_adsp *dsp = container_of(work, - struct wm_adsp, - boot_work); int ret = 0; char *wmfw_filename = NULL; const struct firmware *wmfw_firmware = NULL; @@ -1013,16 +1010,28 @@ static void wm_adsp_boot_work(struct work_struct *work) &wmfw_firmware, &wmfw_filename, &coeff_firmware, &coeff_filename); if (ret) - return; + return ret; - cs_dsp_power_up(&dsp->cs_dsp, - wmfw_firmware, wmfw_filename, - coeff_firmware, coeff_filename, - wm_adsp_fw_text[dsp->fw]); + ret = cs_dsp_power_up(&dsp->cs_dsp, + wmfw_firmware, wmfw_filename, + coeff_firmware, coeff_filename, + wm_adsp_fw_text[dsp->fw]); wm_adsp_release_firmware_files(dsp, wmfw_firmware, wmfw_filename, coeff_firmware, coeff_filename); + + return ret; +} +EXPORT_SYMBOL_GPL(wm_adsp_power_up); + +static void wm_adsp_boot_work(struct work_struct *work) +{ + struct wm_adsp *dsp = container_of(work, + struct wm_adsp, + boot_work); + + wm_adsp_power_up(dsp); } int wm_adsp_early_event(struct snd_soc_dapm_widget *w, diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 173dcae2c260..769904d34a87 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -91,6 +91,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, int wm_adsp_early_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); +int wm_adsp_power_up(struct wm_adsp *dsp); + irqreturn_t wm_adsp2_bus_error(int irq, void *data); irqreturn_t wm_halo_bus_error(int irq, void *data); irqreturn_t wm_halo_wdt_expire(int irq, void *data); -- cgit From 0e7d82cbea8bc0db8ced613aea04da17ac0f0249 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 20 Mar 2023 11:22:43 +0000 Subject: ASoC: wm_adsp: Add support for loading bin files without wmfw A self-booted DSP may have a file of coefficients to apply to the device even when there is no firmware to download. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230320112245.115720-7-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index d4bffa2f7005..c23c306dc38d 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -850,8 +850,29 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, return 0; } - if (dsp->wmfw_optional) + if (dsp->wmfw_optional) { + if (system_name) { + if (asoc_component_prefix) + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, + cirrus_dir, system_name, + asoc_component_prefix, "bin"); + + if (!*coeff_firmware) + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, + cirrus_dir, system_name, + NULL, "bin"); + } + + if (!*coeff_firmware) + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, + "", NULL, NULL, "bin"); + + if (!*coeff_firmware) + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, + cirrus_dir, NULL, NULL, "bin"); + return 0; + } adsp_err(dsp, "Failed to request firmware <%s>%s-%s-%s<-%s<%s>>.wmfw\n", cirrus_dir, dsp->part, dsp->fwf_name, wm_adsp_fw[dsp->fw].file, -- cgit From 991b1de830f61076b7dc29bec081a4d2e50724cf Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 20 Mar 2023 11:22:44 +0000 Subject: ASoC: wm_adsp: Simplify the logging of requested firmware files This change makes the logging of firmware files more consistent and simplifies the code - a debug message is logged whether the requested file was found or not and this applies to both wmfw and bin files. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230320112245.115720-8-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index c23c306dc38d..216120b68b64 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -787,6 +787,8 @@ static int wm_adsp_request_firmware_file(struct wm_adsp *dsp, adsp_dbg(dsp, "Failed to request '%s'\n", *filename); kfree(*filename); *filename = NULL; + } else { + adsp_dbg(dsp, "Found '%s'\n", *filename); } return ret; @@ -807,7 +809,6 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, cirrus_dir, system_name, asoc_component_prefix, "wmfw")) { - adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename); wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, cirrus_dir, system_name, asoc_component_prefix, "bin"); @@ -819,7 +820,6 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, cirrus_dir, system_name, NULL, "wmfw")) { - adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename); if (asoc_component_prefix) wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, cirrus_dir, system_name, @@ -835,7 +835,6 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, "", NULL, NULL, "wmfw")) { - adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename); wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, "", NULL, NULL, "bin"); return 0; @@ -844,7 +843,6 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, ret = wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, cirrus_dir, NULL, NULL, "wmfw"); if (!ret) { - adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename); wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, cirrus_dir, NULL, NULL, "bin"); return 0; -- cgit From e496112529006ce0c2cfe67d1136186e2786d2e8 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Mon, 20 Mar 2023 11:22:45 +0000 Subject: ASoC: cs35l56: Add driver for Cirrus Logic CS35L56 The CS35L56 combines a high-performance mono audio amplifier, Class-H tracking inductive boost converter, Halo Core(TM) DSP and a DC-DC boost converter supporting Class-H tracking. Supported control interfaces are I2C, SPI or SoundWire. Supported audio interfaces are I2S/TDM or SoundWire. Most chip functionality is controlled by on-board ROM firmware that is always running. The driver must apply patch/tune to the firmware before using the CS35L56. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230320112245.115720-9-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 40 + sound/soc/codecs/Makefile | 10 + sound/soc/codecs/cs35l56-i2c.c | 83 +++ sound/soc/codecs/cs35l56-sdw.c | 528 ++++++++++++++ sound/soc/codecs/cs35l56-shared.c | 390 ++++++++++ sound/soc/codecs/cs35l56-spi.c | 81 ++ sound/soc/codecs/cs35l56.c | 1461 +++++++++++++++++++++++++++++++++++++ sound/soc/codecs/cs35l56.h | 77 ++ 8 files changed, 2670 insertions(+) create mode 100644 sound/soc/codecs/cs35l56-i2c.c create mode 100644 sound/soc/codecs/cs35l56-sdw.c create mode 100644 sound/soc/codecs/cs35l56-shared.c create mode 100644 sound/soc/codecs/cs35l56-spi.c create mode 100644 sound/soc/codecs/cs35l56.c create mode 100644 sound/soc/codecs/cs35l56.h (limited to 'sound') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 07747565c3b5..c9fb09cf8e6b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -68,6 +68,9 @@ config SND_SOC_ALL_CODECS imply SND_SOC_CS35L41_I2C imply SND_SOC_CS35L45_I2C imply SND_SOC_CS35L45_SPI + imply SND_SOC_CS35L56_I2C + imply SND_SOC_CS35L56_SPI + imply SND_SOC_CS35L56_SDW imply SND_SOC_CS42L42 imply SND_SOC_CS42L42_SDW imply SND_SOC_CS42L51_I2C @@ -364,6 +367,7 @@ config SND_SOC_WM_ADSP default y if SND_SOC_WM2200=y default y if SND_SOC_CS35L41_SPI=y default y if SND_SOC_CS35L41_I2C=y + default y if SND_SOC_CS35L56=y default m if SND_SOC_MADERA=m default m if SND_SOC_CS47L24=m default m if SND_SOC_WM5102=m @@ -371,6 +375,7 @@ config SND_SOC_WM_ADSP default m if SND_SOC_WM2200=m default m if SND_SOC_CS35L41_SPI=m default m if SND_SOC_CS35L41_I2C=m + default m if SND_SOC_CS35L56=m config SND_SOC_AB8500_CODEC tristate @@ -711,6 +716,41 @@ config SND_SOC_CS35L45_I2C Enable support for Cirrus Logic CS35L45 smart speaker amplifier with I2C control. +config SND_SOC_CS35L56 + tristate + +config SND_SOC_CS35L56_SHARED + tristate + +config SND_SOC_CS35L56_I2C + tristate "Cirrus Logic CS35L56 CODEC (I2C)" + depends on I2C + depends on SOUNDWIRE || !SOUNDWIRE + select REGMAP_I2C + select SND_SOC_CS35L56 + select SND_SOC_CS35L56_SHARED + help + Enable support for Cirrus Logic CS35L56 boosted amplifier with I2C control + +config SND_SOC_CS35L56_SPI + tristate "Cirrus Logic CS35L56 CODEC (SPI)" + depends on SPI_MASTER + depends on SOUNDWIRE || !SOUNDWIRE + select REGMAP_SPI + select SND_SOC_CS35L56 + select SND_SOC_CS35L56_SHARED + help + Enable support for Cirrus Logic CS35L56 boosted amplifier with SPI control + +config SND_SOC_CS35L56_SDW + tristate "Cirrus Logic CS35L56 CODEC (SDW)" + depends on SOUNDWIRE + select REGMAP + select SND_SOC_CS35L56 + select SND_SOC_CS35L56_SHARED + help + Enable support for Cirrus Logic CS35L56 boosted amplifier with SoundWire control + config SND_SOC_CS42L42_CORE tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index f1ca18f7946c..25ebce58a0ba 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -66,6 +66,11 @@ snd-soc-cs35l41-i2c-objs := cs35l41-i2c.o snd-soc-cs35l45-objs := cs35l45.o cs35l45-tables.o snd-soc-cs35l45-spi-objs := cs35l45-spi.o snd-soc-cs35l45-i2c-objs := cs35l45-i2c.o +snd-soc-cs35l56-objs := cs35l56.o +snd-soc-cs35l56-shared-objs := cs35l56-shared.o +snd-soc-cs35l56-i2c-objs := cs35l56-i2c.o +snd-soc-cs35l56-spi-objs := cs35l56-spi.o +snd-soc-cs35l56-sdw-objs := cs35l56-sdw.o snd-soc-cs42l42-objs := cs42l42.o snd-soc-cs42l42-i2c-objs := cs42l42-i2c.o snd-soc-cs42l42-sdw-objs := cs42l42-sdw.o @@ -433,6 +438,11 @@ obj-$(CONFIG_SND_SOC_CS35L41_I2C) += snd-soc-cs35l41-i2c.o obj-$(CONFIG_SND_SOC_CS35L45) += snd-soc-cs35l45.o obj-$(CONFIG_SND_SOC_CS35L45_SPI) += snd-soc-cs35l45-spi.o obj-$(CONFIG_SND_SOC_CS35L45_I2C) += snd-soc-cs35l45-i2c.o +obj-$(CONFIG_SND_SOC_CS35L56) += snd-soc-cs35l56.o +obj-$(CONFIG_SND_SOC_CS35L56_SHARED) += snd-soc-cs35l56-shared.o +obj-$(CONFIG_SND_SOC_CS35L56_I2C) += snd-soc-cs35l56-i2c.o +obj-$(CONFIG_SND_SOC_CS35L56_SPI) += snd-soc-cs35l56-spi.o +obj-$(CONFIG_SND_SOC_CS35L56_SDW) += snd-soc-cs35l56-sdw.o obj-$(CONFIG_SND_SOC_CS42L42_CORE) += snd-soc-cs42l42.o obj-$(CONFIG_SND_SOC_CS42L42) += snd-soc-cs42l42-i2c.o obj-$(CONFIG_SND_SOC_CS42L42_SDW) += snd-soc-cs42l42-sdw.o diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c new file mode 100644 index 000000000000..4b7f034a7670 --- /dev/null +++ b/sound/soc/codecs/cs35l56-i2c.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// CS35L56 ALSA SoC audio driver I2C binding +// +// Copyright (C) 2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include +#include +#include +#include +#include + +#include "cs35l56.h" + +static int cs35l56_i2c_probe(struct i2c_client *client) +{ + struct cs35l56_private *cs35l56; + struct device *dev = &client->dev; + const struct regmap_config *regmap_config = &cs35l56_regmap_i2c; + int ret; + + cs35l56 = devm_kzalloc(dev, sizeof(struct cs35l56_private), GFP_KERNEL); + if (!cs35l56) + return -ENOMEM; + + cs35l56->dev = dev; + cs35l56->irq = client->irq; + cs35l56->can_hibernate = true; + + i2c_set_clientdata(client, cs35l56); + cs35l56->regmap = devm_regmap_init_i2c(client, regmap_config); + if (IS_ERR(cs35l56->regmap)) { + ret = PTR_ERR(cs35l56->regmap); + return dev_err_probe(cs35l56->dev, ret, "Failed to allocate register map\n"); + } + + ret = cs35l56_common_probe(cs35l56); + if (ret != 0) + return ret; + + ret = cs35l56_init(cs35l56); + if (ret == 0) + ret = cs35l56_irq_request(cs35l56); + if (ret < 0) + cs35l56_remove(cs35l56); + + return ret; +} + +static void cs35l56_i2c_remove(struct i2c_client *client) +{ + struct cs35l56_private *cs35l56 = i2c_get_clientdata(client); + + cs35l56_remove(cs35l56); +} + +static const struct i2c_device_id cs35l56_id_i2c[] = { + { "cs35l56", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs35l56_id_i2c); + +static struct i2c_driver cs35l56_i2c_driver = { + .driver = { + .name = "cs35l56", + .pm = &cs35l56_pm_ops_i2c_spi, + }, + .id_table = cs35l56_id_i2c, + .probe_new = cs35l56_i2c_probe, + .remove = cs35l56_i2c_remove, +}; + +module_i2c_driver(cs35l56_i2c_driver); + +MODULE_DESCRIPTION("ASoC CS35L56 I2C driver"); +MODULE_IMPORT_NS(SND_SOC_CS35L56_CORE); +MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Simon Trimmer "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c new file mode 100644 index 000000000000..448ef3609f4c --- /dev/null +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -0,0 +1,528 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// CS35L56 ALSA SoC audio driver SoundWire binding +// +// Copyright (C) 2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cs35l56.h" + +/* Register addresses are offset when sent over SoundWire */ +#define CS35L56_SDW_ADDR_OFFSET 0x8000 + +static int cs35l56_sdw_read_one(struct sdw_slave *peripheral, unsigned int reg, void *buf) +{ + int ret; + + ret = sdw_nread_no_pm(peripheral, reg, 4, (u8 *)buf); + if (ret != 0) { + dev_err(&peripheral->dev, "Read failed @%#x:%d\n", reg, ret); + return ret; + } + + swab32s((u32 *)buf); + + return 0; +} + +static int cs35l56_sdw_read(void *context, const void *reg_buf, + const size_t reg_size, void *val_buf, + size_t val_size) +{ + struct sdw_slave *peripheral = context; + u8 *buf8 = val_buf; + unsigned int reg, bytes; + int ret; + + reg = le32_to_cpu(*(const __le32 *)reg_buf); + reg += CS35L56_SDW_ADDR_OFFSET; + + if (val_size == 4) + return cs35l56_sdw_read_one(peripheral, reg, val_buf); + + while (val_size) { + bytes = SDW_REG_NO_PAGE - (reg & SDW_REGADDR); /* to end of page */ + if (bytes > val_size) + bytes = val_size; + + ret = sdw_nread_no_pm(peripheral, reg, bytes, buf8); + if (ret != 0) { + dev_err(&peripheral->dev, "Read failed @%#x..%#x:%d\n", + reg, reg + bytes - 1, ret); + return ret; + } + + swab32_array((u32 *)buf8, bytes / 4); + val_size -= bytes; + reg += bytes; + buf8 += bytes; + } + + return 0; +} + +static inline void cs35l56_swab_copy(void *dest, const void *src, size_t nbytes) +{ + u32 *dest32 = dest; + const u32 *src32 = src; + + for (; nbytes > 0; nbytes -= 4) + *dest32++ = swab32(*src32++); +} + +static int cs35l56_sdw_write_one(struct sdw_slave *peripheral, unsigned int reg, const void *buf) +{ + u32 val_le = swab32(*(u32 *)buf); + int ret; + + ret = sdw_nwrite_no_pm(peripheral, reg, 4, (u8 *)&val_le); + if (ret != 0) { + dev_err(&peripheral->dev, "Write failed @%#x:%d\n", reg, ret); + return ret; + } + + return 0; +} + +static int cs35l56_sdw_gather_write(void *context, + const void *reg_buf, size_t reg_size, + const void *val_buf, size_t val_size) +{ + struct sdw_slave *peripheral = context; + const u8 *src_be = val_buf; + u32 val_le_buf[64]; /* Define u32 so it is 32-bit aligned */ + unsigned int reg, bytes; + int ret; + + reg = le32_to_cpu(*(const __le32 *)reg_buf); + reg += CS35L56_SDW_ADDR_OFFSET; + + if (val_size == 4) + return cs35l56_sdw_write_one(peripheral, reg, src_be); + + while (val_size) { + bytes = SDW_REG_NO_PAGE - (reg & SDW_REGADDR); /* to end of page */ + if (bytes > val_size) + bytes = val_size; + if (bytes > sizeof(val_le_buf)) + bytes = sizeof(val_le_buf); + + cs35l56_swab_copy(val_le_buf, src_be, bytes); + + ret = sdw_nwrite_no_pm(peripheral, reg, bytes, (u8 *)val_le_buf); + if (ret != 0) { + dev_err(&peripheral->dev, "Write failed @%#x..%#x:%d\n", + reg, reg + bytes - 1, ret); + return ret; + } + + val_size -= bytes; + reg += bytes; + src_be += bytes; + } + + return 0; +} + +static int cs35l56_sdw_write(void *context, const void *val_buf, size_t val_size) +{ + const u8 *src_buf = val_buf; + + /* First word of val_buf contains the destination address */ + return cs35l56_sdw_gather_write(context, &src_buf[0], 4, &src_buf[4], val_size - 4); +} + +/* + * Registers are big-endian on I2C and SPI but little-endian on SoundWire. + * Exported firmware controls are big-endian on I2C/SPI but little-endian on + * SoundWire. Firmware files are always big-endian and are opaque blobs. + * Present a big-endian regmap and hide the endianness swap, so that the ALSA + * byte controls always have the same byte order, and firmware file blobs + * can be written verbatim. + */ +static const struct regmap_bus cs35l56_regmap_bus_sdw = { + .read = cs35l56_sdw_read, + .write = cs35l56_sdw_write, + .gather_write = cs35l56_sdw_gather_write, + .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, + .val_format_endian_default = REGMAP_ENDIAN_BIG, +}; + +static void cs35l56_sdw_init(struct sdw_slave *peripheral) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + int ret; + + pm_runtime_get_noresume(cs35l56->dev); + + regcache_cache_only(cs35l56->regmap, false); + + ret = cs35l56_init(cs35l56); + if (ret < 0) { + regcache_cache_only(cs35l56->regmap, true); + goto out; + } + + /* + * cs35l56_init can return with !init_done if it triggered + * a soft reset. + */ + if (cs35l56->init_done) { + /* Enable SoundWire interrupts */ + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, + CS35L56_SDW_INT_MASK_CODEC_IRQ); + } + +out: + pm_runtime_mark_last_busy(cs35l56->dev); + pm_runtime_put_autosuspend(cs35l56->dev); +} + +static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral, + struct sdw_slave_intr_status *status) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + + /* SoundWire core holds our pm_runtime when calling this function. */ + + dev_dbg(cs35l56->dev, "int control_port=%#x\n", status->control_port); + + if ((status->control_port & SDW_SCP_INT1_IMPL_DEF) == 0) + return 0; + + /* + * Prevent bus manager suspending and possibly issuing a + * bus-reset before the queued work has run. + */ + pm_runtime_get_noresume(cs35l56->dev); + + /* + * Mask and clear until it has been handled. The read of GEN_INT_STAT_1 + * is required as per the SoundWire spec for interrupt status bits + * to clear. GEN_INT_MASK_1 masks the _inputs_ to GEN_INT_STAT1. + * None of the interrupts are time-critical so use the + * power-efficient queue. + */ + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); + sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); + queue_work(system_power_efficient_wq, &cs35l56->sdw_irq_work); + + return 0; +} + +static void cs35l56_sdw_irq_work(struct work_struct *work) +{ + struct cs35l56_private *cs35l56 = container_of(work, + struct cs35l56_private, + sdw_irq_work); + + cs35l56_irq(-1, cs35l56); + + /* unmask interrupts */ + if (!cs35l56->sdw_irq_no_unmask) + sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, + CS35L56_SDW_INT_MASK_CODEC_IRQ); + + pm_runtime_put_autosuspend(cs35l56->dev); +} + +static int cs35l56_sdw_read_prop(struct sdw_slave *peripheral) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + struct sdw_slave_prop *prop = &peripheral->prop; + struct sdw_dpn_prop *ports; + + ports = devm_kcalloc(cs35l56->dev, 2, sizeof(*ports), GFP_KERNEL); + if (!ports) + return -ENOMEM; + + prop->source_ports = BIT(CS35L56_SDW1_CAPTURE_PORT); + prop->sink_ports = BIT(CS35L56_SDW1_PLAYBACK_PORT); + prop->paging_support = true; + prop->clk_stop_mode1 = false; + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; + prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY | SDW_SCP_INT1_IMPL_DEF; + + /* DP1 - playback */ + ports[0].num = CS35L56_SDW1_PLAYBACK_PORT; + ports[0].type = SDW_DPN_FULL; + ports[0].ch_prep_timeout = 10; + prop->sink_dpn_prop = &ports[0]; + + /* DP3 - capture */ + ports[1].num = CS35L56_SDW1_CAPTURE_PORT; + ports[1].type = SDW_DPN_FULL; + ports[1].ch_prep_timeout = 10; + prop->src_dpn_prop = &ports[1]; + + return 0; +} + +static int cs35l56_sdw_update_status(struct sdw_slave *peripheral, + enum sdw_slave_status status) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + + switch (status) { + case SDW_SLAVE_ATTACHED: + dev_dbg(cs35l56->dev, "%s: ATTACHED\n", __func__); + if (cs35l56->sdw_attached) + break; + + if (!cs35l56->init_done || cs35l56->soft_resetting) + cs35l56_sdw_init(peripheral); + + cs35l56->sdw_attached = true; + break; + case SDW_SLAVE_UNATTACHED: + dev_dbg(cs35l56->dev, "%s: UNATTACHED\n", __func__); + cs35l56->sdw_attached = false; + break; + default: + break; + } + + return 0; +} + +static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56, + struct sdw_slave *peripheral) +{ + unsigned int curr_scale_reg, next_scale_reg; + int curr_scale, next_scale, ret; + + if (!cs35l56->init_done) + return 0; + + if (peripheral->bus->params.curr_bank) { + curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1; + next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0; + } else { + curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0; + next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1; + } + + /* + * Current clock scale value must be different to new value. + * Modify current to guarantee this. If next still has the dummy + * value we wrote when it was current, the core code has not set + * a new scale so restore its original good value + */ + curr_scale = sdw_read_no_pm(peripheral, curr_scale_reg); + if (curr_scale < 0) { + dev_err(cs35l56->dev, "Failed to read current clock scale: %d\n", curr_scale); + return curr_scale; + } + + next_scale = sdw_read_no_pm(peripheral, next_scale_reg); + if (next_scale < 0) { + dev_err(cs35l56->dev, "Failed to read next clock scale: %d\n", next_scale); + return next_scale; + } + + if (next_scale == CS35L56_SDW_INVALID_BUS_SCALE) { + next_scale = cs35l56->old_sdw_clock_scale; + ret = sdw_write_no_pm(peripheral, next_scale_reg, next_scale); + if (ret < 0) { + dev_err(cs35l56->dev, "Failed to modify current clock scale: %d\n", ret); + return ret; + } + } + + cs35l56->old_sdw_clock_scale = curr_scale; + ret = sdw_write_no_pm(peripheral, curr_scale_reg, CS35L56_SDW_INVALID_BUS_SCALE); + if (ret < 0) { + dev_err(cs35l56->dev, "Failed to modify current clock scale: %d\n", ret); + return ret; + } + + dev_dbg(cs35l56->dev, "Next bus scale: %#x\n", next_scale); + + return 0; +} + +static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral, + struct sdw_bus_params *params) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + int sclk; + + sclk = params->curr_dr_freq / 2; + dev_dbg(cs35l56->dev, "%s: sclk=%u c=%u r=%u\n", __func__, sclk, params->col, params->row); + + if (cs35l56->rev < 0xb0) + return cs35l56_a1_kick_divider(cs35l56, peripheral); + + return 0; +} + +static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral, + enum sdw_clk_stop_mode mode, + enum sdw_clk_stop_type type) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + + dev_dbg(cs35l56->dev, "%s: mode:%d type:%d\n", __func__, mode, type); + + return 0; +} + +static const struct sdw_slave_ops cs35l56_sdw_ops = { + .read_prop = cs35l56_sdw_read_prop, + .interrupt_callback = cs35l56_sdw_interrupt, + .update_status = cs35l56_sdw_update_status, + .bus_config = cs35l56_sdw_bus_config, +#ifdef DEBUG + .clk_stop = cs35l56_sdw_clk_stop, +#endif +}; + +static int __maybe_unused cs35l56_sdw_handle_unattach(struct cs35l56_private *cs35l56) +{ + struct sdw_slave *peripheral = cs35l56->sdw_peripheral; + + if (peripheral->unattach_request) { + /* Cannot access registers until bus is re-initialized. */ + dev_dbg(cs35l56->dev, "Wait for initialization_complete\n"); + if (!wait_for_completion_timeout(&peripheral->initialization_complete, + msecs_to_jiffies(5000))) { + dev_err(cs35l56->dev, "initialization_complete timed out\n"); + return -ETIMEDOUT; + } + + peripheral->unattach_request = 0; + + /* + * Don't call regcache_mark_dirty(), we can't be sure that the + * Manager really did issue a Bus Reset. + */ + } + + return 0; +} + +static int __maybe_unused cs35l56_sdw_runtime_suspend(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + if (!cs35l56->init_done) + return 0; + + return cs35l56_runtime_suspend(dev); +} + +static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + int ret; + + dev_dbg(dev, "Runtime resume\n"); + + if (!cs35l56->init_done) + return 0; + + ret = cs35l56_sdw_handle_unattach(cs35l56); + if (ret < 0) + return ret; + + ret = cs35l56_runtime_resume_common(cs35l56); + if (ret) + return ret; + + /* Re-enable SoundWire interrupts */ + sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, + CS35L56_SDW_INT_MASK_CODEC_IRQ); + + return 0; +} + +static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_device_id *id) +{ + struct device *dev = &peripheral->dev; + struct cs35l56_private *cs35l56; + int ret; + + cs35l56 = devm_kzalloc(dev, sizeof(*cs35l56), GFP_KERNEL); + if (!cs35l56) + return -ENOMEM; + + cs35l56->dev = dev; + cs35l56->sdw_peripheral = peripheral; + INIT_WORK(&cs35l56->sdw_irq_work, cs35l56_sdw_irq_work); + + dev_set_drvdata(dev, cs35l56); + + cs35l56->regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw, + peripheral, &cs35l56_regmap_sdw); + if (IS_ERR(cs35l56->regmap)) { + ret = PTR_ERR(cs35l56->regmap); + return dev_err_probe(dev, ret, "Failed to allocate register map\n"); + } + + /* Start in cache-only until device is enumerated */ + regcache_cache_only(cs35l56->regmap, true); + + ret = cs35l56_common_probe(cs35l56); + if (ret != 0) + return ret; + + return 0; +} + +static int cs35l56_sdw_remove(struct sdw_slave *peripheral) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + + /* Disable SoundWire interrupts */ + cs35l56->sdw_irq_no_unmask = true; + cancel_work_sync(&cs35l56->sdw_irq_work); + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); + sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); + + return cs35l56_remove(cs35l56); +} + +static const struct dev_pm_ops cs35l56_sdw_pm = { + SET_RUNTIME_PM_OPS(cs35l56_sdw_runtime_suspend, cs35l56_sdw_runtime_resume, NULL) +}; + +static const struct sdw_device_id cs35l56_sdw_id[] = { + SDW_SLAVE_ENTRY(0x01FA, 0x3556, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, cs35l56_sdw_id); + +static struct sdw_driver cs35l56_sdw_driver = { + .driver = { + .name = "cs35l56", + .pm = &cs35l56_sdw_pm, + }, + .probe = cs35l56_sdw_probe, + .remove = cs35l56_sdw_remove, + .ops = &cs35l56_sdw_ops, + .id_table = cs35l56_sdw_id, +}; + +module_sdw_driver(cs35l56_sdw_driver); + +MODULE_DESCRIPTION("ASoC CS35L56 SoundWire driver"); +MODULE_IMPORT_NS(SND_SOC_CS35L56_CORE); +MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Simon Trimmer "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c new file mode 100644 index 000000000000..d8bc06ad4888 --- /dev/null +++ b/sound/soc/codecs/cs35l56-shared.c @@ -0,0 +1,390 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Components shared between ASoC and HDA CS35L56 drivers +// +// Copyright (C) 2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include + +#include "cs35l56.h" + +static const struct reg_default cs35l56_reg_defaults[] = { + { CS35L56_ASP1_ENABLES1, 0x00000000 }, + { CS35L56_ASP1_CONTROL1, 0x00000028 }, + { CS35L56_ASP1_CONTROL2, 0x18180200 }, + { CS35L56_ASP1_CONTROL3, 0x00000002 }, + { CS35L56_ASP1_FRAME_CONTROL1, 0x03020100 }, + { CS35L56_ASP1_FRAME_CONTROL5, 0x00020100 }, + { CS35L56_ASP1_DATA_CONTROL1, 0x00000018 }, + { CS35L56_ASP1_DATA_CONTROL5, 0x00000018 }, + { CS35L56_ASP1TX1_INPUT, 0x00000018 }, + { CS35L56_ASP1TX2_INPUT, 0x00000019 }, + { CS35L56_ASP1TX3_INPUT, 0x00000020 }, + { CS35L56_ASP1TX4_INPUT, 0x00000028 }, + { CS35L56_SWIRE_DP3_CH1_INPUT, 0x00000018 }, + { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 }, + { CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 }, + { CS35L56_SWIRE_DP3_CH4_INPUT, 0x00000028 }, + { CS35L56_SWIRE_DP3_CH5_INPUT, 0x00000018 }, + { CS35L56_SWIRE_DP3_CH6_INPUT, 0x00000018 }, + { CS35L56_IRQ1_CFG, 0x00000000 }, + { CS35L56_IRQ1_MASK_1, 0x83ffffff }, + { CS35L56_IRQ1_MASK_2, 0xffff7fff }, + { CS35L56_IRQ1_MASK_4, 0xe0ffffff }, + { CS35L56_IRQ1_MASK_8, 0xfc000fff }, + { CS35L56_IRQ1_MASK_18, 0x1f7df0ff }, + { CS35L56_IRQ1_MASK_20, 0x15c00000 }, + /* CS35L56_MAIN_RENDER_USER_MUTE - soft register, no default */ + /* CS35L56_MAIN_RENDER_USER_VOLUME - soft register, no default */ + /* CS35L56_MAIN_POSTURE_NUMBER - soft register, no default */ +}; + +/* + * The Ax devices have different default register values to that of B0, + * establish a common set of register defaults. + */ +static const struct reg_sequence cs35l56_reva_patch[] = { + { CS35L56_SWIRE_DP3_CH5_INPUT, 0x00000018 }, + { CS35L56_SWIRE_DP3_CH6_INPUT, 0x00000018 }, +}; + +void cs35l56_patch(struct device *dev, struct regmap *regmap, u8 revid) +{ + int ret; + + if (revid >= CS35L56_REVID_B0) + return; + + ret = regmap_register_patch(regmap, cs35l56_reva_patch, + ARRAY_SIZE(cs35l56_reva_patch)); + if (ret) + dev_err(dev, "Failed to apply patch: %d\n", ret); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_patch, SND_SOC_CS35L56_SHARED); + +static bool cs35l56_is_dsp_memory(unsigned int reg) +{ + switch (reg) { + case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143: + case CS35L56_DSP1_XMEM_UNPACKED32_0 ... CS35L56_DSP1_XMEM_UNPACKED32_4095: + case CS35L56_DSP1_XMEM_UNPACKED24_0 ... CS35L56_DSP1_XMEM_UNPACKED24_8191: + case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604: + case CS35L56_DSP1_YMEM_UNPACKED32_0 ... CS35L56_DSP1_YMEM_UNPACKED32_3070: + case CS35L56_DSP1_YMEM_UNPACKED24_0 ... CS35L56_DSP1_YMEM_UNPACKED24_6141: + case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114: + return true; + default: + return false; + } +} + +static bool cs35l56_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS35L56_DEVID: + case CS35L56_REVID: + case CS35L56_RELID: + case CS35L56_OTPID: + case CS35L56_SFT_RESET: + case CS35L56_GLOBAL_ENABLES: + case CS35L56_BLOCK_ENABLES: + case CS35L56_BLOCK_ENABLES2: + case CS35L56_REFCLK_INPUT: + case CS35L56_GLOBAL_SAMPLE_RATE: + case CS35L56_ASP1_ENABLES1: + case CS35L56_ASP1_CONTROL1: + case CS35L56_ASP1_CONTROL2: + case CS35L56_ASP1_CONTROL3: + case CS35L56_ASP1_FRAME_CONTROL1: + case CS35L56_ASP1_FRAME_CONTROL5: + case CS35L56_ASP1_DATA_CONTROL1: + case CS35L56_ASP1_DATA_CONTROL5: + case CS35L56_DACPCM1_INPUT: + case CS35L56_DACPCM2_INPUT: + case CS35L56_ASP1TX1_INPUT: + case CS35L56_ASP1TX2_INPUT: + case CS35L56_ASP1TX3_INPUT: + case CS35L56_ASP1TX4_INPUT: + case CS35L56_DSP1RX1_INPUT: + case CS35L56_DSP1RX2_INPUT: + case CS35L56_SWIRE_DP3_CH1_INPUT: + case CS35L56_SWIRE_DP3_CH2_INPUT: + case CS35L56_SWIRE_DP3_CH3_INPUT: + case CS35L56_SWIRE_DP3_CH4_INPUT: + case CS35L56_SWIRE_DP3_CH5_INPUT: + case CS35L56_SWIRE_DP3_CH6_INPUT: + case CS35L56_IRQ1_CFG: + case CS35L56_IRQ1_STATUS: + case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8: + case CS35L56_IRQ1_EINT_18: + case CS35L56_IRQ1_EINT_20: + case CS35L56_IRQ1_MASK_1: + case CS35L56_IRQ1_MASK_2: + case CS35L56_IRQ1_MASK_4: + case CS35L56_IRQ1_MASK_8: + case CS35L56_IRQ1_MASK_18: + case CS35L56_IRQ1_MASK_20: + case CS35L56_DSP_VIRTUAL1_MBOX_1: + case CS35L56_DSP_VIRTUAL1_MBOX_2: + case CS35L56_DSP_VIRTUAL1_MBOX_3: + case CS35L56_DSP_VIRTUAL1_MBOX_4: + case CS35L56_DSP_VIRTUAL1_MBOX_5: + case CS35L56_DSP_VIRTUAL1_MBOX_6: + case CS35L56_DSP_VIRTUAL1_MBOX_7: + case CS35L56_DSP_VIRTUAL1_MBOX_8: + case CS35L56_DSP_RESTRICT_STS1: + case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END: + case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0: + case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1: + case CS35L56_DSP1_SCRATCH1: + case CS35L56_DSP1_SCRATCH2: + case CS35L56_DSP1_SCRATCH3: + case CS35L56_DSP1_SCRATCH4: + return true; + default: + return cs35l56_is_dsp_memory(reg); + } +} + +static bool cs35l56_precious_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143: + case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604: + case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114: + return true; + default: + return false; + } +} + +static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS35L56_DEVID: + case CS35L56_REVID: + case CS35L56_RELID: + case CS35L56_OTPID: + case CS35L56_SFT_RESET: + case CS35L56_GLOBAL_ENABLES: /* owned by firmware */ + case CS35L56_BLOCK_ENABLES: /* owned by firmware */ + case CS35L56_BLOCK_ENABLES2: /* owned by firmware */ + case CS35L56_REFCLK_INPUT: /* owned by firmware */ + case CS35L56_GLOBAL_SAMPLE_RATE: /* owned by firmware */ + case CS35L56_DACPCM1_INPUT: /* owned by firmware */ + case CS35L56_DACPCM2_INPUT: /* owned by firmware */ + case CS35L56_DSP1RX1_INPUT: /* owned by firmware */ + case CS35L56_DSP1RX2_INPUT: /* owned by firmware */ + case CS35L56_IRQ1_STATUS: + case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8: + case CS35L56_IRQ1_EINT_18: + case CS35L56_IRQ1_EINT_20: + case CS35L56_DSP_VIRTUAL1_MBOX_1: + case CS35L56_DSP_VIRTUAL1_MBOX_2: + case CS35L56_DSP_VIRTUAL1_MBOX_3: + case CS35L56_DSP_VIRTUAL1_MBOX_4: + case CS35L56_DSP_VIRTUAL1_MBOX_5: + case CS35L56_DSP_VIRTUAL1_MBOX_6: + case CS35L56_DSP_VIRTUAL1_MBOX_7: + case CS35L56_DSP_VIRTUAL1_MBOX_8: + case CS35L56_DSP_RESTRICT_STS1: + case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END: + case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0: + case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1: + case CS35L56_DSP1_SCRATCH1: + case CS35L56_DSP1_SCRATCH2: + case CS35L56_DSP1_SCRATCH3: + case CS35L56_DSP1_SCRATCH4: + return true; + case CS35L56_MAIN_RENDER_USER_MUTE: + case CS35L56_MAIN_RENDER_USER_VOLUME: + case CS35L56_MAIN_POSTURE_NUMBER: + return false; + default: + return cs35l56_is_dsp_memory(reg); + } +} + +static const u32 cs35l56_firmware_registers[] = { + CS35L56_MAIN_RENDER_USER_MUTE, + CS35L56_MAIN_RENDER_USER_VOLUME, + CS35L56_MAIN_POSTURE_NUMBER, +}; + +void cs35l56_reread_firmware_registers(struct device *dev, struct regmap *regmap) +{ + int i; + unsigned int val; + + for (i = 0; i < ARRAY_SIZE(cs35l56_firmware_registers); i++) { + regmap_read(regmap, cs35l56_firmware_registers[i], &val); + dev_dbg(dev, "%s: %d: %#x: %#x\n", __func__, + i, cs35l56_firmware_registers[i], val); + } +} +EXPORT_SYMBOL_NS_GPL(cs35l56_reread_firmware_registers, SND_SOC_CS35L56_SHARED); + +const struct cs_dsp_region cs35l56_dsp1_regions[] = { + { .type = WMFW_HALO_PM_PACKED, .base = CS35L56_DSP1_PMEM_0 }, + { .type = WMFW_HALO_XM_PACKED, .base = CS35L56_DSP1_XMEM_PACKED_0 }, + { .type = WMFW_HALO_YM_PACKED, .base = CS35L56_DSP1_YMEM_PACKED_0 }, + { .type = WMFW_ADSP2_XM, .base = CS35L56_DSP1_XMEM_UNPACKED24_0 }, + { .type = WMFW_ADSP2_YM, .base = CS35L56_DSP1_YMEM_UNPACKED24_0 }, +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_dsp1_regions, SND_SOC_CS35L56_SHARED); + +static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = { + [0x0C] = 128000, + [0x0F] = 256000, + [0x11] = 384000, + [0x12] = 512000, + [0x15] = 768000, + [0x17] = 1024000, + [0x1A] = 1500000, + [0x1B] = 1536000, + [0x1C] = 2000000, + [0x1D] = 2048000, + [0x1E] = 2400000, + [0x20] = 3000000, + [0x21] = 3072000, + [0x23] = 4000000, + [0x24] = 4096000, + [0x25] = 4800000, + [0x27] = 6000000, + [0x28] = 6144000, + [0x29] = 6250000, + [0x2A] = 6400000, + [0x2E] = 8000000, + [0x2F] = 8192000, + [0x30] = 9600000, + [0x32] = 12000000, + [0x33] = 12288000, + [0x37] = 13500000, + [0x38] = 19200000, + [0x39] = 22579200, + [0x3B] = 24576000, +}; + +int cs35l56_get_bclk_freq_id(unsigned int freq) +{ + int i; + + if (freq == 0) + return -EINVAL; + + /* The BCLK frequency must be a valid PLL REFCLK */ + for (i = 0; i < ARRAY_SIZE(cs35l56_bclk_valid_for_pll_freq_table); ++i) { + if (cs35l56_bclk_valid_for_pll_freq_table[i] == freq) + return i; + } + + return -EINVAL; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_get_bclk_freq_id, SND_SOC_CS35L56_SHARED); + +static const char * const cs35l56_supplies[/* auto-sized */] = { + "VDD_P", + "VDD_IO", + "VDD_A", +}; + +void cs35l56_fill_supply_names(struct regulator_bulk_data *data) +{ + int i; + + BUILD_BUG_ON(ARRAY_SIZE(cs35l56_supplies) != CS35L56_NUM_BULK_SUPPLIES); + for (i = 0; i < ARRAY_SIZE(cs35l56_supplies); i++) + data[i].supply = cs35l56_supplies[i]; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_fill_supply_names, SND_SOC_CS35L56_SHARED); + +const char * const cs35l56_tx_input_texts[] = { + "None", "ASP1RX1", "ASP1RX2", "VMON", "IMON", "ERRVOL", "CLASSH", + "VDDBMON", "VBSTMON", "DSP1TX1", "DSP1TX2", "DSP1TX3", "DSP1TX4", + "DSP1TX5", "DSP1TX6", "DSP1TX7", "DSP1TX8", "TEMPMON", + "INTERPOLATOR", "SDW1RX1", "SDW1RX2", "SDW2RX1", +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_texts, SND_SOC_CS35L56_SHARED); + +const unsigned int cs35l56_tx_input_values[] = { + CS35L56_INPUT_SRC_NONE, + CS35L56_INPUT_SRC_ASP1RX1, + CS35L56_INPUT_SRC_ASP1RX2, + CS35L56_INPUT_SRC_VMON, + CS35L56_INPUT_SRC_IMON, + CS35L56_INPUT_SRC_ERR_VOL, + CS35L56_INPUT_SRC_CLASSH, + CS35L56_INPUT_SRC_VDDBMON, + CS35L56_INPUT_SRC_VBSTMON, + CS35L56_INPUT_SRC_DSP1TX1, + CS35L56_INPUT_SRC_DSP1TX2, + CS35L56_INPUT_SRC_DSP1TX3, + CS35L56_INPUT_SRC_DSP1TX4, + CS35L56_INPUT_SRC_DSP1TX5, + CS35L56_INPUT_SRC_DSP1TX6, + CS35L56_INPUT_SRC_DSP1TX7, + CS35L56_INPUT_SRC_DSP1TX8, + CS35L56_INPUT_SRC_TEMPMON, + CS35L56_INPUT_SRC_INTERPOLATOR, + CS35L56_INPUT_SRC_SWIRE_RX1, + CS35L56_INPUT_SRC_SWIRE_RX2, + CS35L56_INPUT_SRC_SWIRE_RX3, +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED); + +struct regmap_config cs35l56_regmap_i2c = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .reg_format_endian = REGMAP_ENDIAN_BIG, + .val_format_endian = REGMAP_ENDIAN_BIG, + .max_register = CS35L56_DSP1_PMEM_5114, + .reg_defaults = cs35l56_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults), + .volatile_reg = cs35l56_volatile_reg, + .readable_reg = cs35l56_readable_reg, + .precious_reg = cs35l56_precious_reg, + .cache_type = REGCACHE_RBTREE, +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_i2c, SND_SOC_CS35L56_SHARED); + +struct regmap_config cs35l56_regmap_spi = { + .reg_bits = 32, + .val_bits = 32, + .pad_bits = 16, + .reg_stride = 4, + .reg_format_endian = REGMAP_ENDIAN_BIG, + .val_format_endian = REGMAP_ENDIAN_BIG, + .max_register = CS35L56_DSP1_PMEM_5114, + .reg_defaults = cs35l56_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults), + .volatile_reg = cs35l56_volatile_reg, + .readable_reg = cs35l56_readable_reg, + .precious_reg = cs35l56_precious_reg, + .cache_type = REGCACHE_RBTREE, +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, SND_SOC_CS35L56_SHARED); + +struct regmap_config cs35l56_regmap_sdw = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .reg_format_endian = REGMAP_ENDIAN_LITTLE, + .val_format_endian = REGMAP_ENDIAN_BIG, + .max_register = CS35L56_DSP1_PMEM_5114, + .reg_defaults = cs35l56_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults), + .volatile_reg = cs35l56_volatile_reg, + .readable_reg = cs35l56_readable_reg, + .precious_reg = cs35l56_precious_reg, + .cache_type = REGCACHE_RBTREE, +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_sdw, SND_SOC_CS35L56_SHARED); + +MODULE_DESCRIPTION("ASoC CS35L56 Shared"); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Simon Trimmer "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c new file mode 100644 index 000000000000..80dcf37daae2 --- /dev/null +++ b/sound/soc/codecs/cs35l56-spi.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// CS35L56 ALSA SoC audio driver SPI binding +// +// Copyright (C) 2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include +#include +#include +#include + +#include "cs35l56.h" + +static int cs35l56_spi_probe(struct spi_device *spi) +{ + const struct regmap_config *regmap_config = &cs35l56_regmap_spi; + struct cs35l56_private *cs35l56; + int ret; + + cs35l56 = devm_kzalloc(&spi->dev, sizeof(struct cs35l56_private), GFP_KERNEL); + if (!cs35l56) + return -ENOMEM; + + spi_set_drvdata(spi, cs35l56); + cs35l56->regmap = devm_regmap_init_spi(spi, regmap_config); + if (IS_ERR(cs35l56->regmap)) { + ret = PTR_ERR(cs35l56->regmap); + return dev_err_probe(&spi->dev, ret, "Failed to allocate register map\n"); + return ret; + } + + cs35l56->dev = &spi->dev; + cs35l56->irq = spi->irq; + + ret = cs35l56_common_probe(cs35l56); + if (ret != 0) + return ret; + + ret = cs35l56_init(cs35l56); + if (ret == 0) + ret = cs35l56_irq_request(cs35l56); + if (ret < 0) + cs35l56_remove(cs35l56); + + return ret; +} + +static void cs35l56_spi_remove(struct spi_device *spi) +{ + struct cs35l56_private *cs35l56 = spi_get_drvdata(spi); + + cs35l56_remove(cs35l56); +} + +static const struct spi_device_id cs35l56_id_spi[] = { + { "cs35l56", 0 }, + {} +}; +MODULE_DEVICE_TABLE(spi, cs35l56_id_spi); + +static struct spi_driver cs35l56_spi_driver = { + .driver = { + .name = "cs35l56", + .pm = &cs35l56_pm_ops_i2c_spi, + }, + .id_table = cs35l56_id_spi, + .probe = cs35l56_spi_probe, + .remove = cs35l56_spi_remove, +}; + +module_spi_driver(cs35l56_spi_driver); + +MODULE_DESCRIPTION("ASoC CS35L56 SPI driver"); +MODULE_IMPORT_NS(SND_SOC_CS35L56_CORE); +MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Simon Trimmer "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c new file mode 100644 index 000000000000..90fc79b5666d --- /dev/null +++ b/sound/soc/codecs/cs35l56.c @@ -0,0 +1,1461 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Driver for Cirrus Logic CS35L56 smart amp +// +// Copyright (C) 2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wm_adsp.h" +#include "cs35l56.h" + +static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); + +static int cs35l56_wait_dsp_ready(struct cs35l56_private *cs35l56) +{ + int ret; + + if (!cs35l56->fw_patched) { + /* block until firmware download completes */ + ret = wait_for_completion_timeout(&cs35l56->dsp_ready_completion, + msecs_to_jiffies(25000)); + if (!ret) { + dev_err(cs35l56->dev, "dsp_ready_completion timeout\n"); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int cs35l56_dspwait_get_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); + int ret = cs35l56_wait_dsp_ready(cs35l56); + + if (ret) + return ret; + + return snd_soc_get_volsw(kcontrol, ucontrol); +} + +static int cs35l56_dspwait_put_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); + int ret = cs35l56_wait_dsp_ready(cs35l56); + + if (ret) + return ret; + + return snd_soc_put_volsw(kcontrol, ucontrol); +} + +static DECLARE_TLV_DB_SCALE(vol_tlv, -10000, 25, 0); + +static const struct snd_kcontrol_new cs35l56_controls[] = { + SOC_SINGLE_EXT("Speaker Switch", + CS35L56_MAIN_RENDER_USER_MUTE, 0, 1, 1, + cs35l56_dspwait_get_volsw, cs35l56_dspwait_put_volsw), + SOC_SINGLE_S_EXT_TLV("Speaker Volume", + CS35L56_MAIN_RENDER_USER_VOLUME, + 6, -400, 400, 9, 0, + cs35l56_dspwait_get_volsw, + cs35l56_dspwait_put_volsw, + vol_tlv), + SOC_SINGLE_EXT("Posture Number", CS35L56_MAIN_POSTURE_NUMBER, + 0, 255, 0, + cs35l56_dspwait_get_volsw, cs35l56_dspwait_put_volsw), +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx1_enum, + CS35L56_ASP1TX1_INPUT, + 0, CS35L56_ASP_TXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new asp1_tx1_mux = + SOC_DAPM_ENUM("ASP1TX1 SRC", cs35l56_asp1tx1_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx2_enum, + CS35L56_ASP1TX2_INPUT, + 0, CS35L56_ASP_TXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new asp1_tx2_mux = + SOC_DAPM_ENUM("ASP1TX2 SRC", cs35l56_asp1tx2_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx3_enum, + CS35L56_ASP1TX3_INPUT, + 0, CS35L56_ASP_TXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new asp1_tx3_mux = + SOC_DAPM_ENUM("ASP1TX3 SRC", cs35l56_asp1tx3_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx4_enum, + CS35L56_ASP1TX4_INPUT, + 0, CS35L56_ASP_TXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new asp1_tx4_mux = + SOC_DAPM_ENUM("ASP1TX4 SRC", cs35l56_asp1tx4_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx1_enum, + CS35L56_SWIRE_DP3_CH1_INPUT, + 0, CS35L56_SWIRETXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new sdw1_tx1_mux = + SOC_DAPM_ENUM("SDW1TX1 SRC", cs35l56_sdw1tx1_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx2_enum, + CS35L56_SWIRE_DP3_CH2_INPUT, + 0, CS35L56_SWIRETXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new sdw1_tx2_mux = + SOC_DAPM_ENUM("SDW1TX2 SRC", cs35l56_sdw1tx2_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx3_enum, + CS35L56_SWIRE_DP3_CH3_INPUT, + 0, CS35L56_SWIRETXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new sdw1_tx3_mux = + SOC_DAPM_ENUM("SDW1TX3 SRC", cs35l56_sdw1tx3_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx4_enum, + CS35L56_SWIRE_DP3_CH4_INPUT, + 0, CS35L56_SWIRETXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new sdw1_tx4_mux = + SOC_DAPM_ENUM("SDW1TX4 SRC", cs35l56_sdw1tx4_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx5_enum, + CS35L56_SWIRE_DP3_CH5_INPUT, + 0, CS35L56_SWIRETXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new sdw1_tx5_mux = + SOC_DAPM_ENUM("SDW1TX5 SRC", cs35l56_sdw1tx5_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx6_enum, + CS35L56_SWIRE_DP3_CH6_INPUT, + 0, CS35L56_SWIRETXn_SRC_MASK, + cs35l56_tx_input_texts, + cs35l56_tx_input_values); + +static const struct snd_kcontrol_new sdw1_tx6_mux = + SOC_DAPM_ENUM("SDW1TX6 SRC", cs35l56_sdw1tx6_enum); + +static const struct snd_soc_dapm_widget cs35l56_dapm_widgets[] = { + SND_SOC_DAPM_REGULATOR_SUPPLY("VDD_B", 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("VDD_AMP", 0, 0), + + SND_SOC_DAPM_OUT_DRV("AMP", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("SPK"), + + SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, cs35l56_dsp_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_AIF_IN("ASP1RX1", NULL, 0, CS35L56_ASP1_ENABLES1, + CS35L56_ASP_RX1_EN_SHIFT, 0), + SND_SOC_DAPM_AIF_IN("ASP1RX2", NULL, 1, CS35L56_ASP1_ENABLES1, + CS35L56_ASP_RX2_EN_SHIFT, 0), + SND_SOC_DAPM_AIF_OUT("ASP1TX1", NULL, 0, CS35L56_ASP1_ENABLES1, + CS35L56_ASP_TX1_EN_SHIFT, 0), + SND_SOC_DAPM_AIF_OUT("ASP1TX2", NULL, 1, CS35L56_ASP1_ENABLES1, + CS35L56_ASP_TX2_EN_SHIFT, 0), + SND_SOC_DAPM_AIF_OUT("ASP1TX3", NULL, 2, CS35L56_ASP1_ENABLES1, + CS35L56_ASP_TX3_EN_SHIFT, 0), + SND_SOC_DAPM_AIF_OUT("ASP1TX4", NULL, 3, CS35L56_ASP1_ENABLES1, + CS35L56_ASP_TX4_EN_SHIFT, 0), + + SND_SOC_DAPM_MUX("ASP1 TX1 Source", SND_SOC_NOPM, 0, 0, &asp1_tx1_mux), + SND_SOC_DAPM_MUX("ASP1 TX2 Source", SND_SOC_NOPM, 0, 0, &asp1_tx2_mux), + SND_SOC_DAPM_MUX("ASP1 TX3 Source", SND_SOC_NOPM, 0, 0, &asp1_tx3_mux), + SND_SOC_DAPM_MUX("ASP1 TX4 Source", SND_SOC_NOPM, 0, 0, &asp1_tx4_mux), + + SND_SOC_DAPM_MUX("SDW1 TX1 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx1_mux), + SND_SOC_DAPM_MUX("SDW1 TX2 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx2_mux), + SND_SOC_DAPM_MUX("SDW1 TX3 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx3_mux), + SND_SOC_DAPM_MUX("SDW1 TX4 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx4_mux), + SND_SOC_DAPM_MUX("SDW1 TX5 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx5_mux), + SND_SOC_DAPM_MUX("SDW1 TX6 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx6_mux), + + SND_SOC_DAPM_SIGGEN("VMON ADC"), + SND_SOC_DAPM_SIGGEN("IMON ADC"), + SND_SOC_DAPM_SIGGEN("ERRVOL ADC"), + SND_SOC_DAPM_SIGGEN("CLASSH ADC"), + SND_SOC_DAPM_SIGGEN("VDDBMON ADC"), + SND_SOC_DAPM_SIGGEN("VBSTMON ADC"), + SND_SOC_DAPM_SIGGEN("TEMPMON ADC"), +}; + +#define CS35L56_SRC_ROUTE(name) \ + { name" Source", "ASP1RX1", "ASP1RX1" }, \ + { name" Source", "ASP1RX2", "ASP1RX2" }, \ + { name" Source", "VMON", "VMON ADC" }, \ + { name" Source", "IMON", "IMON ADC" }, \ + { name" Source", "ERRVOL", "ERRVOL ADC" }, \ + { name" Source", "CLASSH", "CLASSH ADC" }, \ + { name" Source", "VDDBMON", "VDDBMON ADC" }, \ + { name" Source", "VBSTMON", "VBSTMON ADC" }, \ + { name" Source", "DSP1TX1", "DSP1" }, \ + { name" Source", "DSP1TX2", "DSP1" }, \ + { name" Source", "DSP1TX3", "DSP1" }, \ + { name" Source", "DSP1TX4", "DSP1" }, \ + { name" Source", "DSP1TX5", "DSP1" }, \ + { name" Source", "DSP1TX6", "DSP1" }, \ + { name" Source", "DSP1TX7", "DSP1" }, \ + { name" Source", "DSP1TX8", "DSP1" }, \ + { name" Source", "TEMPMON", "TEMPMON ADC" }, \ + { name" Source", "INTERPOLATOR", "AMP" }, \ + { name" Source", "SDW1RX1", "SDW1 Playback" }, \ + { name" Source", "SDW1RX2", "SDW1 Playback" }, + +static const struct snd_soc_dapm_route cs35l56_audio_map[] = { + { "AMP", NULL, "VDD_B" }, + { "AMP", NULL, "VDD_AMP" }, + + { "ASP1RX1", NULL, "ASP1 Playback" }, + { "ASP1RX2", NULL, "ASP1 Playback" }, + { "DSP1", NULL, "ASP1RX1" }, + { "DSP1", NULL, "ASP1RX2" }, + { "DSP1", NULL, "SDW1 Playback" }, + { "AMP", NULL, "DSP1" }, + { "SPK", NULL, "AMP" }, + + CS35L56_SRC_ROUTE("ASP1 TX1") + CS35L56_SRC_ROUTE("ASP1 TX2") + CS35L56_SRC_ROUTE("ASP1 TX3") + CS35L56_SRC_ROUTE("ASP1 TX4") + + { "ASP1TX1", NULL, "ASP1 TX1 Source" }, + { "ASP1TX2", NULL, "ASP1 TX2 Source" }, + { "ASP1TX3", NULL, "ASP1 TX3 Source" }, + { "ASP1TX4", NULL, "ASP1 TX4 Source" }, + { "ASP1 Capture", NULL, "ASP1TX1" }, + { "ASP1 Capture", NULL, "ASP1TX2" }, + { "ASP1 Capture", NULL, "ASP1TX3" }, + { "ASP1 Capture", NULL, "ASP1TX4" }, + + CS35L56_SRC_ROUTE("SDW1 TX1") + CS35L56_SRC_ROUTE("SDW1 TX2") + CS35L56_SRC_ROUTE("SDW1 TX3") + CS35L56_SRC_ROUTE("SDW1 TX4") + CS35L56_SRC_ROUTE("SDW1 TX5") + CS35L56_SRC_ROUTE("SDW1 TX6") + { "SDW1 Capture", NULL, "SDW1 TX1 Source" }, + { "SDW1 Capture", NULL, "SDW1 TX2 Source" }, + { "SDW1 Capture", NULL, "SDW1 TX3 Source" }, + { "SDW1 Capture", NULL, "SDW1 TX4 Source" }, + { "SDW1 Capture", NULL, "SDW1 TX5 Source" }, + { "SDW1 Capture", NULL, "SDW1 TX6 Source" }, +}; + +static int cs35l56_mbox_send(struct cs35l56_private *cs35l56, unsigned int command) +{ + unsigned int val; + int ret; + + regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command); + ret = regmap_read_poll_timeout(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, + val, (val == 0), + CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US); + if (ret) { + dev_warn(cs35l56->dev, "MBOX command %#x failed: %d\n", command, ret); + return ret; + } + + return 0; +} + +static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); + + dev_dbg(cs35l56->dev, "%s: %d\n", __func__, event); + + return wm_adsp_event(w, kcontrol, event); +} + +irqreturn_t cs35l56_irq(int irq, void *data) +{ + struct cs35l56_private *cs35l56 = data; + unsigned int status1 = 0, status8 = 0, status20 = 0; + unsigned int mask1, mask8, mask20; + unsigned int rv, val; + irqreturn_t ret = IRQ_NONE; + + if (!cs35l56->init_done) + return IRQ_NONE; + + mutex_lock(&cs35l56->irq_lock); + + rv = pm_runtime_resume_and_get(cs35l56->dev); + if (rv < 0) { + dev_err(cs35l56->dev, "irq: failed to get pm_runtime: %d\n", rv); + goto err_unlock; + } + + regmap_read(cs35l56->regmap, CS35L56_IRQ1_STATUS, &val); + if ((val & CS35L56_IRQ1_STS_MASK) == 0) { + dev_dbg(cs35l56->dev, "Spurious IRQ: no pending interrupt\n"); + goto err; + } + + /* Ack interrupts */ + regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_1, &status1); + regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_1, &mask1); + status1 &= ~mask1; + regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_1, status1); + + regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_8, &status8); + regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_8, &mask8); + status8 &= ~mask8; + regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_8, status8); + + regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_20, &status20); + regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_20, &mask20); + status20 &= ~mask20; + /* We don't want EINT20 but they default to unmasked: force mask */ + regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); + + dev_dbg(cs35l56->dev, "%s: %#x %#x\n", __func__, status1, status8); + + /* Check to see if unmasked bits are active */ + if (!status1 && !status8 && !status20) + goto err; + + if (status1 & CS35L56_AMP_SHORT_ERR_EINT1_MASK) + dev_crit(cs35l56->dev, "Amp short error\n"); + + if (status8 & CS35L56_TEMP_ERR_EINT1_MASK) + dev_crit(cs35l56->dev, "Overtemp error\n"); + + ret = IRQ_HANDLED; + +err: + pm_runtime_put(cs35l56->dev); +err_unlock: + mutex_unlock(&cs35l56->irq_lock); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_CORE); + +int cs35l56_irq_request(struct cs35l56_private *cs35l56) +{ + int ret; + + if (!cs35l56->irq) + return 0; + + ret = devm_request_threaded_irq(cs35l56->dev, cs35l56->irq, NULL, + cs35l56_irq, + IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW, + "cs35l56", cs35l56); + if (ret < 0) + dev_err(cs35l56->dev, "Failed to get IRQ: %d\n", ret); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_irq_request, SND_SOC_CS35L56_CORE); + +static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(codec_dai->component); + unsigned int val; + + dev_dbg(cs35l56->dev, "%s: %#x\n", __func__, fmt); + + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: + break; + default: + dev_err(cs35l56->dev, "Unsupported clock source mode\n"); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + val = CS35L56_ASP_FMT_DSP_A << CS35L56_ASP_FMT_SHIFT; + cs35l56->tdm_mode = true; + break; + case SND_SOC_DAIFMT_I2S: + val = CS35L56_ASP_FMT_I2S << CS35L56_ASP_FMT_SHIFT; + cs35l56->tdm_mode = false; + break; + default: + dev_err(cs35l56->dev, "Unsupported DAI format\n"); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_IF: + val |= CS35L56_ASP_FSYNC_INV_MASK; + break; + case SND_SOC_DAIFMT_IB_NF: + val |= CS35L56_ASP_BCLK_INV_MASK; + break; + case SND_SOC_DAIFMT_IB_IF: + val |= CS35L56_ASP_BCLK_INV_MASK | CS35L56_ASP_FSYNC_INV_MASK; + break; + case SND_SOC_DAIFMT_NB_NF: + break; + default: + dev_err(cs35l56->dev, "Invalid clock invert\n"); + return -EINVAL; + } + + regmap_update_bits(cs35l56->regmap, + CS35L56_ASP1_CONTROL2, + CS35L56_ASP_FMT_MASK | + CS35L56_ASP_BCLK_INV_MASK | CS35L56_ASP_FSYNC_INV_MASK, + val); + + /* Hi-Z DOUT in unused slots and when all TX are disabled */ + regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL3, + CS35L56_ASP1_DOUT_HIZ_CTRL_MASK, + CS35L56_ASP_UNUSED_HIZ_OFF_HIZ); + + return 0; +} + +static void cs35l56_set_asp_slot_positions(struct cs35l56_private *cs35l56, + unsigned int reg, unsigned long mask) +{ + unsigned int reg_val, channel_shift; + int bit_num; + + /* Init all slots to 63 */ + switch (reg) { + case CS35L56_ASP1_FRAME_CONTROL1: + reg_val = 0x3f3f3f3f; + break; + case CS35L56_ASP1_FRAME_CONTROL5: + reg_val = 0x3f3f3f; + break; + } + + /* Enable consecutive TX1..TXn for each of the slots set in mask */ + channel_shift = 0; + for_each_set_bit(bit_num, &mask, 32) { + reg_val &= ~(0x3f << channel_shift); + reg_val |= bit_num << channel_shift; + channel_shift += 8; + } + + regmap_write(cs35l56->regmap, reg, reg_val); +} + +static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int slot_width) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + + if ((slots == 0) || (slot_width == 0)) { + dev_dbg(cs35l56->dev, "tdm config cleared\n"); + cs35l56->asp_slot_width = 0; + cs35l56->asp_slot_count = 0; + return 0; + } + + if (slot_width > (CS35L56_ASP_RX_WIDTH_MASK >> CS35L56_ASP_RX_WIDTH_SHIFT)) { + dev_err(cs35l56->dev, "tdm invalid slot width %d\n", slot_width); + return -EINVAL; + } + + /* More than 32 slots would give an unsupportable BCLK frequency */ + if (slots > 32) { + dev_err(cs35l56->dev, "tdm invalid slot count %d\n", slots); + return -EINVAL; + } + + cs35l56->asp_slot_width = (u8)slot_width; + cs35l56->asp_slot_count = (u8)slots; + + // Note: rx/tx is from point of view of the CPU end + if (tx_mask == 0) + tx_mask = 0x3; // ASPRX1/RX2 in slots 0 and 1 + + if (rx_mask == 0) + rx_mask = 0xf; // ASPTX1..TX4 in slots 0..3 + + cs35l56_set_asp_slot_positions(cs35l56, CS35L56_ASP1_FRAME_CONTROL1, rx_mask); + cs35l56_set_asp_slot_positions(cs35l56, CS35L56_ASP1_FRAME_CONTROL5, tx_mask); + + dev_dbg(cs35l56->dev, "tdm slot width: %u count: %u tx_mask: %#x rx_mask: %#x\n", + cs35l56->asp_slot_width, cs35l56->asp_slot_count, tx_mask, rx_mask); + + return 0; +} + +static int cs35l56_asp_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + unsigned int rate = params_rate(params); + u8 asp_width, asp_wl; + + asp_wl = params_width(params); + if (cs35l56->asp_slot_width) + asp_width = cs35l56->asp_slot_width; + else + asp_width = asp_wl; + + dev_dbg(cs35l56->dev, "%s: wl=%d, width=%d, rate=%d", __func__, asp_wl, asp_width, rate); + + if (!cs35l56->sysclk_set) { + unsigned int slots = cs35l56->asp_slot_count; + unsigned int bclk_freq; + int freq_id; + + if (slots == 0) { + slots = params_channels(params); + + /* I2S always has an even number of slots */ + if (!cs35l56->tdm_mode) + slots = round_up(slots, 2); + } + + bclk_freq = asp_width * slots * rate; + freq_id = cs35l56_get_bclk_freq_id(bclk_freq); + if (freq_id < 0) { + dev_err(cs35l56->dev, "%s: Invalid BCLK %u\n", __func__, bclk_freq); + return -EINVAL; + } + + regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL1, + CS35L56_ASP_BCLK_FREQ_MASK, + freq_id << CS35L56_ASP_BCLK_FREQ_SHIFT); + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL2, + CS35L56_ASP_RX_WIDTH_MASK, asp_width << + CS35L56_ASP_RX_WIDTH_SHIFT); + regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_DATA_CONTROL5, + CS35L56_ASP_RX_WL_MASK, asp_wl); + } else { + regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL2, + CS35L56_ASP_TX_WIDTH_MASK, asp_width << + CS35L56_ASP_TX_WIDTH_SHIFT); + regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_DATA_CONTROL1, + CS35L56_ASP_TX_WL_MASK, asp_wl); + } + + return 0; +} + +static int cs35l56_asp_dai_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + int freq_id; + + if (freq == 0) { + cs35l56->sysclk_set = false; + return 0; + } + + freq_id = cs35l56_get_bclk_freq_id(freq); + if (freq_id < 0) + return freq_id; + + regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL1, + CS35L56_ASP_BCLK_FREQ_MASK, + freq_id << CS35L56_ASP_BCLK_FREQ_SHIFT); + cs35l56->sysclk_set = true; + + return 0; +} + +static int cs35l56_mute_stream(struct snd_soc_dai *dai, int mute, int stream) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + unsigned int val; + int ret; + + dev_dbg(cs35l56->dev, "%s: %d %s\n", __func__, stream, mute ? "mute" : "unmute"); + + if (stream != SNDRV_PCM_STREAM_PLAYBACK) + return 0; + + if (mute) { + ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_PAUSE); + } else { + ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_PLAY); + if (ret == 0) { + /* Wait for firmware to enter PS0 power state */ + ret = regmap_read_poll_timeout(cs35l56->regmap, + CS35L56_TRANSDUCER_ACTUAL_PS, + val, (val == CS35L56_PS0), + CS35L56_PS0_POLL_US, + CS35L56_PS0_TIMEOUT_US); + if (ret) + dev_err(cs35l56->dev, "PS0 wait failed: %d\n", ret); + ret = 0; + } + } + + return ret; +} + +static const struct snd_soc_dai_ops cs35l56_ops = { + .set_fmt = cs35l56_asp_dai_set_fmt, + .set_tdm_slot = cs35l56_asp_dai_set_tdm_slot, + .hw_params = cs35l56_asp_dai_hw_params, + .set_sysclk = cs35l56_asp_dai_set_sysclk, + .mute_stream = cs35l56_mute_stream, +}; + +static void cs35l56_sdw_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + snd_soc_dai_set_dma_data(dai, substream, NULL); +} + +static int cs35l56_sdw_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int slot_width) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + + /* rx/tx are from point of view of the CPU end so opposite to our rx/tx */ + cs35l56->rx_mask = tx_mask; + cs35l56->tx_mask = rx_mask; + + return 0; +} + +static int cs35l56_sdw_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); + struct sdw_stream_config sconfig; + struct sdw_port_config pconfig; + int ret; + + dev_dbg(cs35l56->dev, "%s: rate %d\n", __func__, params_rate(params)); + + if (!cs35l56->init_done) + return -ENODEV; + + if (!sdw_stream) + return -EINVAL; + + memset(&sconfig, 0, sizeof(sconfig)); + memset(&pconfig, 0, sizeof(pconfig)); + + sconfig.frame_rate = params_rate(params); + sconfig.bps = snd_pcm_format_width(params_format(params)); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + sconfig.direction = SDW_DATA_DIR_RX; + pconfig.num = CS35L56_SDW1_PLAYBACK_PORT; + pconfig.ch_mask = cs35l56->rx_mask; + } else { + sconfig.direction = SDW_DATA_DIR_TX; + pconfig.num = CS35L56_SDW1_CAPTURE_PORT; + pconfig.ch_mask = cs35l56->tx_mask; + } + + if (pconfig.ch_mask == 0) { + sconfig.ch_count = params_channels(params); + pconfig.ch_mask = GENMASK(sconfig.ch_count - 1, 0); + } else { + sconfig.ch_count = hweight32(pconfig.ch_mask); + } + + ret = sdw_stream_add_slave(cs35l56->sdw_peripheral, &sconfig, &pconfig, + 1, sdw_stream); + if (ret) { + dev_err(dai->dev, "Failed to add sdw stream: %d\n", ret); + return ret; + } + + return 0; +} + +static int cs35l56_sdw_dai_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); + + if (!cs35l56->sdw_peripheral) + return -EINVAL; + + sdw_stream_remove_slave(cs35l56->sdw_peripheral, sdw_stream); + + return 0; +} + +static int cs35l56_sdw_dai_set_stream(struct snd_soc_dai *dai, + void *sdw_stream, int direction) +{ + if (!sdw_stream) + return 0; + + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); + + return 0; +} + +static const struct snd_soc_dai_ops cs35l56_sdw_dai_ops = { + .set_tdm_slot = cs35l56_sdw_dai_set_tdm_slot, + .shutdown = cs35l56_sdw_dai_shutdown, + .hw_params = cs35l56_sdw_dai_hw_params, + .hw_free = cs35l56_sdw_dai_hw_free, + .mute_stream = cs35l56_mute_stream, + .set_stream = cs35l56_sdw_dai_set_stream, +}; + +static struct snd_soc_dai_driver cs35l56_dai[] = { + { + .name = "cs35l56-asp1", + .id = 0, + .playback = { + .stream_name = "ASP1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = CS35L56_RATES, + .formats = CS35L56_RX_FORMATS, + }, + .capture = { + .stream_name = "ASP1 Capture", + .channels_min = 1, + .channels_max = 4, + .rates = CS35L56_RATES, + .formats = CS35L56_TX_FORMATS, + }, + .ops = &cs35l56_ops, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, + }, + { + .name = "cs35l56-sdw1", + .id = 1, + .playback = { + .stream_name = "SDW1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = CS35L56_RATES, + .formats = CS35L56_RX_FORMATS, + }, + .capture = { + .stream_name = "SDW1 Capture", + .channels_min = 1, + .channels_max = 6, + .rates = CS35L56_RATES, + .formats = CS35L56_TX_FORMATS, + }, + .symmetric_rate = 1, + .ops = &cs35l56_sdw_dai_ops, + } +}; + +static int cs35l56_wait_for_firmware_boot(struct cs35l56_private *cs35l56) +{ + unsigned int reg; + unsigned int val; + int ret; + + if (cs35l56->rev < CS35L56_REVID_B0) + reg = CS35L56_DSP1_HALO_STATE_A1; + else + reg = CS35L56_DSP1_HALO_STATE; + + ret = regmap_read_poll_timeout(cs35l56->regmap, reg, + val, + (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE), + CS35L56_HALO_STATE_POLL_US, + CS35L56_HALO_STATE_TIMEOUT_US); + + if ((ret < 0) && (ret != -ETIMEDOUT)) { + dev_err(cs35l56->dev, "Failed to read HALO_STATE: %d\n", ret); + return ret; + } + + if ((ret == -ETIMEDOUT) || (val != CS35L56_HALO_STATE_BOOT_DONE)) { + dev_err(cs35l56->dev, "Firmware boot fail: HALO_STATE=%#x\n", val); + return -EIO; + } + + return 0; +} + +static const struct reg_sequence cs35l56_system_reset_seq[] = { + REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), +}; + +static void cs35l56_system_reset(struct cs35l56_private *cs35l56) +{ + cs35l56->soft_resetting = true; + + /* + * Must enter cache-only first so there can't be any more register + * accesses other than the controlled system reset sequence below. + */ + regcache_cache_only(cs35l56->regmap, true); + regmap_multi_reg_write_bypassed(cs35l56->regmap, + cs35l56_system_reset_seq, + ARRAY_SIZE(cs35l56_system_reset_seq)); + + /* On SoundWire the registers won't be accessible until it re-enumerates. */ + if (cs35l56->sdw_peripheral) + return; + + usleep_range(CS35L56_CONTROL_PORT_READY_US, CS35L56_CONTROL_PORT_READY_US + 400); + regcache_cache_only(cs35l56->regmap, false); +} + +static void cs35l56_dsp_work(struct work_struct *work) +{ + struct cs35l56_private *cs35l56 = container_of(work, + struct cs35l56_private, + dsp_work); + unsigned int reg; + unsigned int val; + int ret = 0; + + if (!wait_for_completion_timeout(&cs35l56->init_completion, + msecs_to_jiffies(5000))) { + dev_err(cs35l56->dev, "%s: init_completion timed out\n", __func__); + goto complete; + } + + if (!cs35l56->init_done || cs35l56->removing) + goto complete; + + cs35l56->dsp.part = devm_kasprintf(cs35l56->dev, GFP_KERNEL, "cs35l56%s-%02x", + cs35l56->secured ? "s" : "", cs35l56->rev); + + if (!cs35l56->dsp.part) + goto complete; + + pm_runtime_get_sync(cs35l56->dev); + + /* + * Disable SoundWire interrupts to prevent race with IRQ work. + * Setting sdw_irq_no_unmask prevents the handler re-enabling + * the SoundWire interrupt. + */ + if (cs35l56->sdw_peripheral) { + cs35l56->sdw_irq_no_unmask = true; + cancel_work_sync(&cs35l56->sdw_irq_work); + sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); + sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1); + sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); + } + + ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_SHUTDOWN); + if (ret) { + dev_dbg(cs35l56->dev, "%s: CS35L56_MBOX_CMD_SHUTDOWN ret %d\n", __func__, ret); + goto err; + } + + if (cs35l56->rev < CS35L56_REVID_B0) + reg = CS35L56_DSP1_PM_CUR_STATE_A1; + else + reg = CS35L56_DSP1_PM_CUR_STATE; + + ret = regmap_read_poll_timeout(cs35l56->regmap, reg, + val, (val == CS35L56_HALO_STATE_SHUTDOWN), + CS35L56_HALO_STATE_POLL_US, + CS35L56_HALO_STATE_TIMEOUT_US); + if (ret < 0) + dev_err(cs35l56->dev, "Failed to poll PM_CUR_STATE to 1 is %d (ret %d)\n", + val, ret); + + /* Use wm_adsp to load and apply the firmware patch and coefficient files */ + ret = wm_adsp_power_up(&cs35l56->dsp); + if (ret) { + dev_dbg(cs35l56->dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret); + goto err; + } + + if (cs35l56->removing) + goto err; + + mutex_lock(&cs35l56->irq_lock); + + init_completion(&cs35l56->init_completion); + + cs35l56_system_reset(cs35l56); + + if (cs35l56->sdw_peripheral) { + /* + * The system-reset causes the CS35L56 to detach from the bus. + * Wait for the manager to re-enumerate the CS35L56 and + * cs35l56_init() to run again. + */ + if (!wait_for_completion_timeout(&cs35l56->init_completion, + msecs_to_jiffies(5000))) { + dev_err(cs35l56->dev, "%s: init_completion timed out (SDW)\n", __func__); + goto err_unlock; + } + } else if (cs35l56_init(cs35l56)) { + goto err_unlock; + } + + cs35l56->fw_patched = true; + +err_unlock: + mutex_unlock(&cs35l56->irq_lock); +err: + pm_runtime_mark_last_busy(cs35l56->dev); + pm_runtime_put_autosuspend(cs35l56->dev); + + /* Re-enable SoundWire interrupts */ + if (cs35l56->sdw_peripheral) { + cs35l56->sdw_irq_no_unmask = false; + sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, + CS35L56_SDW_INT_MASK_CODEC_IRQ); + } + +complete: + complete_all(&cs35l56->dsp_ready_completion); +} + +static int cs35l56_component_probe(struct snd_soc_component *component) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); + struct dentry *debugfs_root = component->debugfs_root; + + BUILD_BUG_ON(ARRAY_SIZE(cs35l56_tx_input_texts) != ARRAY_SIZE(cs35l56_tx_input_values)); + + cs35l56->removing = false; + cs35l56->component = component; + wm_adsp2_component_probe(&cs35l56->dsp, component); + + debugfs_create_bool("init_done", 0444, debugfs_root, &cs35l56->init_done); + debugfs_create_bool("can_hibernate", 0444, debugfs_root, &cs35l56->can_hibernate); + debugfs_create_bool("fw_patched", 0444, debugfs_root, &cs35l56->fw_patched); + + queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work); + + return 0; +} + +static void cs35l56_component_remove(struct snd_soc_component *component) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); + + cs35l56->removing = true; + complete(&cs35l56->init_completion); + cancel_work_sync(&cs35l56->dsp_work); +} + +static int cs35l56_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); + int ret = 0; + + switch (level) { + case SND_SOC_BIAS_STANDBY: + /* + * Wait for patching to complete when transitioning from + * BIAS_OFF to BIAS_STANDBY + */ + if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) + ret = cs35l56_wait_dsp_ready(cs35l56); + + break; + default: + break; + } + + return ret; +} + +static const struct snd_soc_component_driver soc_component_dev_cs35l56 = { + .probe = cs35l56_component_probe, + .remove = cs35l56_component_remove, + + .dapm_widgets = cs35l56_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs35l56_dapm_widgets), + .dapm_routes = cs35l56_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs35l56_audio_map), + .controls = cs35l56_controls, + .num_controls = ARRAY_SIZE(cs35l56_controls), + + .set_bias_level = cs35l56_set_bias_level, +}; + +static const struct reg_sequence cs35l56_hibernate_seq[] = { + /* This must be the last register access */ + REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_HIBERNATE_NOW), +}; + +static const struct reg_sequence cs35l56_hibernate_wake_seq[] = { + REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_WAKEUP), +}; + +int cs35l56_runtime_suspend(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + unsigned int val; + int ret; + + if (!cs35l56->init_done) + return 0; + + /* Firmware must have entered a power-save state */ + ret = regmap_read_poll_timeout(cs35l56->regmap, + CS35L56_TRANSDUCER_ACTUAL_PS, + val, (val >= CS35L56_PS3), + CS35L56_PS3_POLL_US, + CS35L56_PS3_TIMEOUT_US); + if (ret) + dev_warn(cs35l56->dev, "PS3 wait failed: %d\n", ret); + + /* Clear BOOT_DONE so it can be used to detect a reboot */ + regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_4, CS35L56_OTP_BOOT_DONE_MASK); + + if (!cs35l56->can_hibernate) { + regcache_cache_only(cs35l56->regmap, true); + dev_dbg(dev, "Suspended: no hibernate"); + + return 0; + } + + /* + * Enable auto-hibernate. If it is woken by some other wake source + * it will automatically return to hibernate. + */ + ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE); + if (ret) + dev_warn(cs35l56->dev, "ALLOW_HIBERNATE failed: %d\n", ret); + + /* + * Must enter cache-only first so there can't be any more register + * accesses other than the controlled hibernate sequence below. + */ + regcache_cache_only(cs35l56->regmap, true); + + regmap_multi_reg_write_bypassed(cs35l56->regmap, + cs35l56_hibernate_seq, + ARRAY_SIZE(cs35l56_hibernate_seq)); + + dev_dbg(dev, "Suspended: hibernate"); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_suspend, SND_SOC_CS35L56_CORE); + +static int __maybe_unused cs35l56_runtime_resume_i2c_spi(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + if (!cs35l56->init_done) + return 0; + + return cs35l56_runtime_resume_common(cs35l56); +} + +int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56) +{ + unsigned int val; + int ret; + + if (!cs35l56->can_hibernate) { + regcache_cache_only(cs35l56->regmap, false); + goto out_sync; + } + + if (!cs35l56->sdw_peripheral) { + /* + * Dummy transaction to trigger I2C/SPI auto-wake. This will NAK on I2C. + * Must be done before releasing cache-only. + */ + regmap_multi_reg_write_bypassed(cs35l56->regmap, + cs35l56_hibernate_wake_seq, + ARRAY_SIZE(cs35l56_hibernate_wake_seq)); + + usleep_range(CS35L56_CONTROL_PORT_READY_US, + CS35L56_CONTROL_PORT_READY_US + 400); + } + + regcache_cache_only(cs35l56->regmap, false); + + ret = cs35l56_wait_for_firmware_boot(cs35l56); + if (ret) { + dev_err(cs35l56->dev, "Hibernate wake failed: %d\n", ret); + goto err; + } + + ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); + if (ret) + goto err; + +out_sync: + /* BOOT_DONE will be 1 if the amp reset */ + regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_4, &val); + if (val & CS35L56_OTP_BOOT_DONE_MASK) { + dev_dbg(cs35l56->dev, "Registers reset in suspend\n"); + regcache_mark_dirty(cs35l56->regmap); + } + + regcache_sync(cs35l56->regmap); + + dev_dbg(cs35l56->dev, "Resumed"); + + return 0; + +err: + regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, + CS35L56_MBOX_CMD_HIBERNATE_NOW); + + regcache_cache_only(cs35l56->regmap, true); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_CORE); + +static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) +{ + struct wm_adsp *dsp; + int ret; + + cs35l56->dsp_wq = create_singlethread_workqueue("cs35l56-dsp"); + if (!cs35l56->dsp_wq) + return -ENOMEM; + + INIT_WORK(&cs35l56->dsp_work, cs35l56_dsp_work); + init_completion(&cs35l56->dsp_ready_completion); + + dsp = &cs35l56->dsp; + dsp->part = "cs35l56"; + dsp->cs_dsp.num = 1; + dsp->cs_dsp.type = WMFW_HALO; + dsp->cs_dsp.rev = 0; + dsp->fw = 12; + dsp->cs_dsp.dev = cs35l56->dev; + dsp->cs_dsp.regmap = cs35l56->regmap; + dsp->cs_dsp.base = CS35L56_DSP1_CORE_BASE; + dsp->cs_dsp.base_sysinfo = CS35L56_DSP1_SYS_INFO_ID; + dsp->cs_dsp.mem = cs35l56_dsp1_regions; + dsp->cs_dsp.num_mems = ARRAY_SIZE(cs35l56_dsp1_regions); + dsp->cs_dsp.no_core_startstop = true; + dsp->wmfw_optional = true; + + dev_dbg(cs35l56->dev, "DSP system name: '%s'\n", dsp->system_name); + + ret = wm_halo_init(dsp); + if (ret != 0) { + dev_err(cs35l56->dev, "wm_halo_init failed\n"); + return ret; + } + + return 0; +} + +static int cs35l56_acpi_get_name(struct cs35l56_private *cs35l56) +{ + acpi_handle handle = ACPI_HANDLE(cs35l56->dev); + const char *sub; + + /* If there is no ACPI_HANDLE, there is no ACPI for this system, return 0 */ + if (!handle) + return 0; + + sub = acpi_get_subsystem_id(handle); + if (IS_ERR(sub)) { + /* If bad ACPI, return 0 and fallback to legacy firmware path, otherwise fail */ + if (PTR_ERR(sub) == -ENODATA) + return 0; + else + return PTR_ERR(sub); + } + + cs35l56->dsp.system_name = sub; + dev_dbg(cs35l56->dev, "Subsystem ID: %s\n", cs35l56->dsp.system_name); + + return 0; +} + +int cs35l56_common_probe(struct cs35l56_private *cs35l56) +{ + int ret; + + init_completion(&cs35l56->init_completion); + mutex_init(&cs35l56->irq_lock); + + dev_set_drvdata(cs35l56->dev, cs35l56); + + cs35l56_fill_supply_names(cs35l56->supplies); + ret = devm_regulator_bulk_get(cs35l56->dev, ARRAY_SIZE(cs35l56->supplies), + cs35l56->supplies); + if (ret != 0) + return dev_err_probe(cs35l56->dev, ret, "Failed to request supplies\n"); + + /* Reset could be controlled by the BIOS or shared by multiple amps */ + cs35l56->reset_gpio = devm_gpiod_get_optional(cs35l56->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(cs35l56->reset_gpio)) { + ret = PTR_ERR(cs35l56->reset_gpio); + /* + * If RESET is shared the first amp to probe will grab the reset + * line and reset all the amps + */ + if (ret != -EBUSY) + return dev_err_probe(cs35l56->dev, ret, "Failed to get reset GPIO\n"); + + dev_info(cs35l56->dev, "Reset GPIO busy, assume shared reset\n"); + cs35l56->reset_gpio = NULL; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); + if (ret != 0) + return dev_err_probe(cs35l56->dev, ret, "Failed to enable supplies\n"); + + if (cs35l56->reset_gpio) { + /* satisfy minimum reset pulse width spec */ + usleep_range(CS35L56_RESET_PULSE_MIN_US, + CS35L56_RESET_PULSE_MIN_US + 400); + gpiod_set_value_cansleep(cs35l56->reset_gpio, 1); + } + + ret = cs35l56_acpi_get_name(cs35l56); + if (ret != 0) + goto err; + + ret = cs35l56_dsp_init(cs35l56); + if (ret < 0) { + dev_err_probe(cs35l56->dev, ret, "DSP init failed\n"); + goto err; + } + + ret = devm_snd_soc_register_component(cs35l56->dev, + &soc_component_dev_cs35l56, + cs35l56_dai, ARRAY_SIZE(cs35l56_dai)); + if (ret < 0) { + dev_err_probe(cs35l56->dev, ret, "Register codec failed\n"); + goto err; + } + + return 0; + +err: + gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); + regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_common_probe, SND_SOC_CS35L56_CORE); + +int cs35l56_init(struct cs35l56_private *cs35l56) +{ + int ret; + unsigned int devid, revid, otpid, secured; + + /* + * Check whether the actions associated with soft reset or one time + * init need to be performed. + */ + if (cs35l56->soft_resetting) + goto post_soft_reset; + + if (cs35l56->init_done) + return 0; + + pm_runtime_set_autosuspend_delay(cs35l56->dev, 100); + pm_runtime_use_autosuspend(cs35l56->dev); + pm_runtime_set_active(cs35l56->dev); + pm_runtime_enable(cs35l56->dev); + + /* + * If the system is not using a reset_gpio then issue a + * dummy read to force a wakeup. + */ + if (!cs35l56->reset_gpio) + regmap_read(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, &devid); + + /* Wait for control port to be ready (datasheet tIRS). */ + usleep_range(CS35L56_CONTROL_PORT_READY_US, + CS35L56_CONTROL_PORT_READY_US + 400); + + /* + * The HALO_STATE register is in different locations on Ax and B0 + * devices so the REVID needs to be determined before waiting for the + * firmware to boot. + */ + ret = regmap_read(cs35l56->regmap, CS35L56_REVID, &revid); + if (ret < 0) { + dev_err(cs35l56->dev, "Get Revision ID failed\n"); + return ret; + } + cs35l56->rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK); + + ret = cs35l56_wait_for_firmware_boot(cs35l56); + if (ret) + return ret; + + ret = regmap_read(cs35l56->regmap, CS35L56_DEVID, &devid); + if (ret < 0) { + dev_err(cs35l56->dev, "Get Device ID failed\n"); + return ret; + } + devid &= CS35L56_DEVID_MASK; + + switch (devid) { + case 0x35A56: + break; + default: + dev_err(cs35l56->dev, "Unknown device %x\n", devid); + return ret; + } + + ret = regmap_read(cs35l56->regmap, CS35L56_DSP_RESTRICT_STS1, &secured); + if (ret) { + dev_err(cs35l56->dev, "Get Secure status failed\n"); + return ret; + } + + /* When any bus is restricted treat the device as secured */ + if (secured & CS35L56_RESTRICTED_MASK) + cs35l56->secured = true; + + ret = regmap_read(cs35l56->regmap, CS35L56_OTPID, &otpid); + if (ret < 0) { + dev_err(cs35l56->dev, "Get OTP ID failed\n"); + return ret; + } + + dev_info(cs35l56->dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d\n", + cs35l56->secured ? "s" : "", cs35l56->rev, otpid); + + cs35l56_patch(cs35l56->dev, cs35l56->regmap, cs35l56->rev); + + /* Wake source interrupts default to unmasked, so mask them */ + regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); + regmap_update_bits(cs35l56->regmap, CS35L56_IRQ1_MASK_1, + CS35L56_AMP_SHORT_ERR_EINT1_MASK, + 0); + regmap_update_bits(cs35l56->regmap, CS35L56_IRQ1_MASK_8, + CS35L56_TEMP_ERR_EINT1_MASK, + 0); + + if (!cs35l56->reset_gpio) { + dev_dbg(cs35l56->dev, "No reset gpio: using soft reset\n"); + cs35l56_system_reset(cs35l56); + if (cs35l56->sdw_peripheral) { + /* Keep alive while we wait for re-enumeration */ + pm_runtime_get_noresume(cs35l56->dev); + return 0; + } + } + +post_soft_reset: + if (cs35l56->soft_resetting) { + cs35l56->soft_resetting = false; + + /* Done re-enumerating after one-time init so release the keep-alive */ + if (cs35l56->sdw_peripheral && !cs35l56->init_done) + pm_runtime_put_noidle(cs35l56->dev); + + regcache_mark_dirty(cs35l56->regmap); + ret = cs35l56_wait_for_firmware_boot(cs35l56); + if (ret) + return ret; + + dev_dbg(cs35l56->dev, "Firmware rebooted after soft reset\n"); + } + + /* Disable auto-hibernate so that runtime_pm has control */ + ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); + if (ret) + return ret; + + /* Populate soft registers in the regmap cache */ + cs35l56_reread_firmware_registers(cs35l56->dev, cs35l56->regmap); + + /* Registers could be dirty after soft reset or SoundWire enumeration */ + regcache_sync(cs35l56->regmap); + + cs35l56->init_done = true; + complete(&cs35l56->init_completion); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_init, SND_SOC_CS35L56_CORE); + +int cs35l56_remove(struct cs35l56_private *cs35l56) +{ + cs35l56->init_done = false; + + /* + * WAKE IRQs unmask if CS35L56 hibernates so free the handler to + * prevent it racing with remove(). + */ + if (cs35l56->irq) + devm_free_irq(cs35l56->dev, cs35l56->irq, cs35l56); + + flush_workqueue(cs35l56->dsp_wq); + destroy_workqueue(cs35l56->dsp_wq); + + pm_runtime_suspend(cs35l56->dev); + pm_runtime_disable(cs35l56->dev); + + regcache_cache_only(cs35l56->regmap, true); + + kfree(cs35l56->dsp.system_name); + + gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); + regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cs35l56_remove, SND_SOC_CS35L56_CORE); + +const struct dev_pm_ops cs35l56_pm_ops_i2c_spi = { + SET_RUNTIME_PM_OPS(cs35l56_runtime_suspend, cs35l56_runtime_resume_i2c_spi, NULL) +}; +EXPORT_SYMBOL_NS_GPL(cs35l56_pm_ops_i2c_spi, SND_SOC_CS35L56_CORE); + +MODULE_DESCRIPTION("ASoC CS35L56 driver"); +MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Simon Trimmer "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h new file mode 100644 index 000000000000..efc4b99180f9 --- /dev/null +++ b/sound/soc/codecs/cs35l56.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Driver for Cirrus Logic CS35L56 smart amp + * + * Copyright (C) 2023 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef CS35L56_H +#define CS35L56_H + +#include +#include +#include +#include +#include +#include "wm_adsp.h" + +#define CS35L56_SDW_GEN_INT_STAT_1 0xc0 +#define CS35L56_SDW_GEN_INT_MASK_1 0xc1 +#define CS35L56_SDW_INT_MASK_CODEC_IRQ BIT(0) + +#define CS35L56_SDW_INVALID_BUS_SCALE 0xf + +#define CS35L56_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) +#define CS35L56_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE \ + | SNDRV_PCM_FMTBIT_S32_LE) + +#define CS35L56_RATES (SNDRV_PCM_RATE_48000) + +struct sdw_slave; + +struct cs35l56_private { + struct wm_adsp dsp; /* must be first member */ + struct work_struct dsp_work; + struct workqueue_struct *dsp_wq; + struct completion dsp_ready_completion; + struct mutex irq_lock; + struct snd_soc_component *component; + struct device *dev; + struct regmap *regmap; + struct regulator_bulk_data supplies[CS35L56_NUM_BULK_SUPPLIES]; + int irq; + struct sdw_slave *sdw_peripheral; + u8 rev; + struct work_struct sdw_irq_work; + bool secured; + bool sdw_irq_no_unmask; + bool soft_resetting; + bool init_done; + bool sdw_attached; + bool removing; + bool fw_patched; + bool can_hibernate; + struct completion init_completion; + struct gpio_desc *reset_gpio; + + u32 rx_mask; + u32 tx_mask; + u8 asp_slot_width; + u8 asp_slot_count; + bool tdm_mode; + bool sysclk_set; + u8 old_sdw_clock_scale; +}; + +extern const struct dev_pm_ops cs35l56_pm_ops_i2c_spi; + +int cs35l56_runtime_suspend(struct device *dev); +int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56); +irqreturn_t cs35l56_irq(int irq, void *data); +int cs35l56_irq_request(struct cs35l56_private *cs35l56); +int cs35l56_common_probe(struct cs35l56_private *cs35l56); +int cs35l56_init(struct cs35l56_private *cs35l56); +int cs35l56_remove(struct cs35l56_private *cs35l56); + +#endif /* ifndef CS35L56_H */ -- cgit From 3d3e223f09ed59f7a47d27cf4301b4d0d5c7fc3d Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 21 Mar 2023 11:26:52 +0200 Subject: ASoC: SOF: topology: Set pipeline widget before updating IPC structures Set up the IPC structure for scheduler widgets and set the pipeline widget before updating the IPC structures for all widgets. This will be needed to look up pipeline information during IPC structure set up. Signed-off-by: Ranjani Sridharan Signed-off-by: Jyri Sarha Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230321092654.7292-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index b642835e14df..bc8ca1e05b83 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2126,7 +2126,6 @@ static int sof_complete(struct snd_soc_component *scomp) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); - struct snd_sof_widget *swidget, *comp_swidget; const struct sof_ipc_tplg_widget_ops *widget_ops; struct snd_sof_control *scontrol; struct snd_sof_pipeline *spipe; @@ -2145,37 +2144,38 @@ static int sof_complete(struct snd_soc_component *scomp) } } - /* - * then update all widget IPC structures. If any of the ipc_setup callbacks fail, the - * topology will be removed and all widgets will be unloaded resulting in freeing all - * associated memories. - */ - list_for_each_entry(swidget, &sdev->widget_list, list) { - if (widget_ops && widget_ops[swidget->id].ipc_setup) { - ret = widget_ops[swidget->id].ipc_setup(swidget); + /* set up the IPC structures for the pipeline widgets */ + list_for_each_entry(spipe, &sdev->pipeline_list, list) { + struct snd_sof_widget *pipe_widget = spipe->pipe_widget; + struct snd_sof_widget *swidget; + + /* Update the scheduler widget's IPC structure */ + if (widget_ops && widget_ops[pipe_widget->id].ipc_setup) { + ret = widget_ops[pipe_widget->id].ipc_setup(pipe_widget); if (ret < 0) { dev_err(sdev->dev, "failed updating IPC struct for %s\n", - swidget->widget->name); + pipe_widget->widget->name); return ret; } } - } - /* set the pipe_widget and apply the dynamic_pipeline_widget_flag */ - list_for_each_entry(spipe, &sdev->pipeline_list, list) { - struct snd_sof_widget *pipe_widget = spipe->pipe_widget; - - /* - * Apply the dynamic_pipeline_widget flag and set the pipe_widget field - * for all widgets that have the same pipeline ID as the scheduler widget. - * Skip the scheduler widgets as they have their pipeline set during widget_ready - */ - list_for_each_entry(comp_swidget, &sdev->widget_list, list) - if (comp_swidget->widget->id != snd_soc_dapm_scheduler && - comp_swidget->pipeline_id == pipe_widget->pipeline_id) { - ret = sof_set_widget_pipeline(sdev, spipe, comp_swidget); + /* set the pipeline and update the IPC structure for the non scheduler widgets */ + list_for_each_entry(swidget, &sdev->widget_list, list) + if (swidget->widget->id != snd_soc_dapm_scheduler && + swidget->pipeline_id == pipe_widget->pipeline_id) { + ret = sof_set_widget_pipeline(sdev, spipe, swidget); if (ret < 0) return ret; + + if (widget_ops && widget_ops[swidget->id].ipc_setup) { + ret = widget_ops[swidget->id].ipc_setup(swidget); + if (ret < 0) { + dev_err(sdev->dev, + "failed updating IPC struct for %s\n", + swidget->widget->name); + return ret; + } + } } } -- cgit From ca5ce0caa67fa9eeecaa29d895c2e4c3151c159e Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 21 Mar 2023 11:26:54 +0200 Subject: ASoC: SOF: ipc4/intel: Add support for chained DMA Add logic for setting up and tearing down chained DMA connections. Since pipelines are not used, all the logic to set the pipeline states can be bypassed, with only the DMA programming sequences remaining. In addition the same format needs to be used for host- and link-DMA, without the usual fixup to use the S32_LE format on the link. Note however that for convenience and compatibility with existing definitions, the topology relies on the concept of pipelines with a 'USE_CHAIN_DMA' token indicating that all the logic shall be bypassed. Unlike 'normal' ALSA sequences, the chain DMA is not programmed in hw_params/hw_free. The IPC message to set-up and tear-down chained DMA are sent in sof_ipc4_trigger_pipelines(), but the contents prepared earlier. Chained DMA is only supported by the Intel HDA DAI for now, and only S16_LE and S32_LE formats are supported for now. Signed-off-by: Jyri Sarha Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230321092654.7292-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 18 +++++- sound/soc/sof/ipc4-pcm.c | 122 ++++++++++++++++++++++++++++++++++++-- sound/soc/sof/ipc4-topology.c | 120 ++++++++++++++++++++++++++++++++++++- sound/soc/sof/ipc4-topology.h | 2 + 4 files changed, 254 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index be109f33715f..de48f13259f1 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -277,6 +277,15 @@ static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = { .post_trigger = hda_ipc4_post_trigger }; +static const struct hda_dai_widget_dma_ops hda_ipc4_chain_dma_ops = { + .get_hext_stream = hda_get_hext_stream, + .assign_hext_stream = hda_assign_hext_stream, + .release_hext_stream = hda_release_hext_stream, + .setup_hext_stream = hda_setup_hext_stream, + .reset_hext_stream = hda_reset_hext_stream, + .trigger = hda_trigger, +}; + static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, struct snd_pcm_substream *substream, int cmd) { @@ -331,8 +340,15 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg { struct sof_ipc4_copier *ipc4_copier = sdai->private; - if (ipc4_copier->dai_type == SOF_DAI_INTEL_HDA) + if (ipc4_copier->dai_type == SOF_DAI_INTEL_HDA) { + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; + + if (pipeline->use_chain_dma) + return &hda_ipc4_chain_dma_ops; + return &hda_ipc4_dma_ops; + } break; } default: diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 4598057b7f28..db64200ba1e5 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -193,6 +193,88 @@ sof_ipc4_update_pipeline_state(struct snd_sof_dev *sdev, int state, int cmd, * prepare ioctl before the START trigger. */ +/* + * Chained DMA is a special case where there is no processing on + * DSP. The samples are just moved over by host side DMA to a single + * buffer on DSP and directly from there to link DMA. However, the + * model on SOF driver has two notional pipelines, one at host DAI, + * and another at link DAI. They both shall have the use_chain_dma + * attribute. + */ + +static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev, + struct snd_sof_pcm_stream_pipeline_list *pipeline_list, + int state, int cmd) +{ + bool allocate, enable, set_fifo_size; + struct sof_ipc4_msg msg = {{ 0 }}; + int i; + + switch (state) { + case SOF_IPC4_PIPE_RUNNING: /* Allocate and start chained dma */ + allocate = true; + enable = true; + /* + * SOF assumes creation of a new stream from the presence of fifo_size + * in the message, so we must leave it out in pause release case. + */ + if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) + set_fifo_size = false; + else + set_fifo_size = true; + break; + case SOF_IPC4_PIPE_PAUSED: /* Disable chained DMA. */ + allocate = true; + enable = false; + set_fifo_size = false; + break; + case SOF_IPC4_PIPE_RESET: /* Disable and free chained DMA. */ + allocate = false; + enable = false; + set_fifo_size = false; + break; + default: + dev_err(sdev->dev, "Unexpected state %d", state); + return -EINVAL; + } + + msg.primary = SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_CHAIN_DMA); + msg.primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); + msg.primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_FW_GEN_MSG); + + /* + * To set-up the DMA chain, the host DMA ID and SCS setting + * are retrieved from the host pipeline configuration. Likewise + * the link DMA ID and fifo_size are retrieved from the link + * pipeline configuration. + */ + for (i = 0; i < pipeline_list->count; i++) { + struct snd_sof_pipeline *spipe = pipeline_list->pipelines[i]; + struct snd_sof_widget *pipe_widget = spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; + + if (!pipeline->use_chain_dma) { + dev_err(sdev->dev, + "All pipelines in chained DMA stream should have use_chain_dma attribute set."); + return -EINVAL; + } + + msg.primary |= pipeline->msg.primary; + + /* Add fifo_size (actually DMA buffer size) field to the message */ + if (set_fifo_size) + msg.extension |= pipeline->msg.extension; + } + + if (allocate) + msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_ALLOCATE_MASK; + + if (enable) + msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_ENABLE_MASK; + + return sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); +} + static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, struct snd_pcm_substream *substream, int state, int cmd) { @@ -201,6 +283,8 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, struct snd_sof_pcm_stream_pipeline_list *pipeline_list; struct sof_ipc4_fw_data *ipc4_data = sdev->private; struct ipc4_pipeline_set_state_data *trigger_list; + struct snd_sof_widget *pipe_widget; + struct sof_ipc4_pipeline *pipeline; struct snd_sof_pipeline *spipe; struct snd_sof_pcm *spcm; int ret; @@ -218,6 +302,17 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, if (!pipeline_list->pipelines || !pipeline_list->count) return 0; + spipe = pipeline_list->pipelines[0]; + pipe_widget = spipe->pipe_widget; + pipeline = pipe_widget->private; + + /* + * If use_chain_dma attribute is set we proceed to chained DMA + * trigger function that handles the rest for the substream. + */ + if (pipeline->use_chain_dma) + return sof_ipc4_chain_dma_trigger(sdev, pipeline_list, state, cmd); + /* allocate memory for the pipeline data */ trigger_list = kzalloc(struct_size(trigger_list, pipeline_ids, pipeline_list->count), GFP_KERNEL); @@ -422,8 +517,10 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); struct snd_sof_dai *dai = snd_sof_find_dai(component, rtd->dai_link->name); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct sof_ipc4_copier *ipc4_copier; - int ret; + bool use_chain_dma = false; + int dir; if (!dai) { dev_err(component->dev, "%s: No DAI found with name %s\n", __func__, @@ -438,9 +535,26 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, return -EINVAL; } - ret = sof_ipc4_pcm_dai_link_fixup_rate(sdev, params, ipc4_copier); - if (ret) - return ret; + for_each_pcm_streams(dir) { + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, dir); + + if (w) { + struct snd_sof_widget *swidget = w->dobj.private; + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; + + if (pipeline->use_chain_dma) + use_chain_dma = true; + } + } + + /* Chain DMA does not use copiers, so no fixup needed */ + if (!use_chain_dma) { + int ret = sof_ipc4_pcm_dai_link_fixup_rate(sdev, params, ipc4_copier); + + if (ret) + return ret; + } switch (ipc4_copier->dai_type) { case SOF_DAI_INTEL_SSP: diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 3a4a3267017b..f1e1aed94da4 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -19,6 +19,7 @@ #define SOF_IPC4_GAIN_PARAM_ID 0 #define SOF_IPC4_TPLG_ABI_SIZE 6 +#define SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS 2 static DEFINE_IDA(alh_group_ida); static DEFINE_IDA(pipeline_ida); @@ -26,6 +27,8 @@ static DEFINE_IDA(pipeline_ida); static const struct sof_topology_token ipc4_sched_tokens[] = { {SOF_TKN_SCHED_LP_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, offsetof(struct sof_ipc4_pipeline, lp_mode)}, + {SOF_TKN_SCHED_USE_CHAIN_DMA, SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16, + offsetof(struct sof_ipc4_pipeline, use_chain_dma)}, {SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, offsetof(struct sof_ipc4_pipeline, core_id)}, }; @@ -475,6 +478,8 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dai *dai = swidget->private; struct sof_ipc4_copier *ipc4_copier; + struct snd_sof_widget *pipe_widget; + struct sof_ipc4_pipeline *pipeline; int node_type = 0; int ret; @@ -512,6 +517,16 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) ipc4_copier->data.gtw_cfg.node_id = SOF_IPC4_NODE_TYPE(node_type); + pipe_widget = swidget->spipe->pipe_widget; + pipeline = pipe_widget->private; + if (pipeline->use_chain_dma && ipc4_copier->dai_type != SOF_DAI_INTEL_HDA) { + dev_err(scomp->dev, + "Bad DAI type '%d', Chained DMA is only supported by HDA DAIs (%d).\n", + ipc4_copier->dai_type, SOF_DAI_INTEL_HDA); + ret = -ENODEV; + goto free_available_fmt; + } + switch (ipc4_copier->dai_type) { case SOF_DAI_INTEL_ALH: { @@ -643,6 +658,12 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) swidget->core = pipeline->core_id; + if (pipeline->use_chain_dma) { + dev_dbg(scomp->dev, "Set up chain DMA for %s\n", swidget->widget->name); + swidget->private = pipeline; + return 0; + } + /* parse one set of pipeline tokens */ ret = sof_update_ipc_object(scomp, swidget, SOF_PIPELINE_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(*swidget), 1); @@ -1103,11 +1124,21 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget) pipeline->mem_usage = 0; if (WIDGET_IS_AIF(swidget->id) || swidget->id == snd_soc_dapm_buffer) { + if (pipeline->use_chain_dma) { + pipeline->msg.primary = 0; + pipeline->msg.extension = 0; + } ipc4_copier = swidget->private; } else if (WIDGET_IS_DAI(swidget->id)) { struct snd_sof_dai *dai = swidget->private; ipc4_copier = dai->private; + + if (pipeline->use_chain_dma) { + pipeline->msg.primary = 0; + pipeline->msg.extension = 0; + } + if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) { struct sof_ipc4_copier_data *copier_data = &ipc4_copier->data; struct sof_ipc4_alh_configuration_blob *blob; @@ -1344,13 +1375,44 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, return ret; } - pipe_widget = swidget->spipe->pipe_widget; - pipeline = pipe_widget->private; ipc4_copier = (struct sof_ipc4_copier *)swidget->private; gtw_attr = ipc4_copier->gtw_attr; copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; + pipe_widget = swidget->spipe->pipe_widget; + pipeline = pipe_widget->private; + + if (pipeline->use_chain_dma) { + u32 host_dma_id; + u32 fifo_size; + + host_dma_id = platform_params->stream_tag - 1; + pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_HOST_ID(host_dma_id); + + /* Set SCS bit for S16_LE format only */ + if (params_format(fe_params) == SNDRV_PCM_FORMAT_S16_LE) + pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_SCS_MASK; + + /* + * Despite its name the bitfield 'fifo_size' is used to define DMA buffer + * size. The expression calculates 2ms buffer size. + */ + fifo_size = DIV_ROUND_UP((SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS * + params_rate(fe_params) * + params_channels(fe_params) * + params_physical_width(fe_params)), 8000); + pipeline->msg.extension |= SOF_IPC4_GLB_EXT_CHAIN_DMA_FIFO_SIZE(fifo_size); + + /* + * Chain DMA does not support stream timestamping, set node_id to invalid + * to skip the code in sof_ipc4_get_stream_start_offset(). + */ + copier_data->gtw_cfg.node_id = SOF_IPC4_INVALID_NODE_ID; + + return 0; + } + /* * Use the input_pin_fmts to match pcm params for playback and the output_pin_fmts * for capture. @@ -1375,6 +1437,12 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, case snd_soc_dapm_dai_in: case snd_soc_dapm_dai_out: { + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; + + if (pipeline->use_chain_dma) + return 0; + dai = swidget->private; ipc4_copier = (struct sof_ipc4_copier *)dai->private; @@ -1921,6 +1989,9 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget case snd_soc_dapm_scheduler: pipeline = swidget->private; + if (pipeline->use_chain_dma) + return 0; + dev_dbg(sdev->dev, "pipeline: %d memory pages: %d\n", swidget->pipeline_id, pipeline->mem_usage); @@ -1943,6 +2014,10 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget { struct sof_ipc4_copier *ipc4_copier = swidget->private; + pipeline = pipe_widget->private; + if (pipeline->use_chain_dma) + return 0; + ipc_size = ipc4_copier->ipc_config_size; ipc_data = ipc4_copier->ipc_config_data; @@ -1955,6 +2030,10 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget struct snd_sof_dai *dai = swidget->private; struct sof_ipc4_copier *ipc4_copier = dai->private; + pipeline = pipe_widget->private; + if (pipeline->use_chain_dma) + return 0; + ipc_size = ipc4_copier->ipc_config_size; ipc_data = ipc4_copier->ipc_config_data; @@ -2066,6 +2145,9 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget struct sof_ipc4_msg msg = {{ 0 }}; u32 header; + if (pipeline->use_chain_dma) + return 0; + header = SOF_IPC4_GLB_PIPE_INSTANCE_ID(swidget->instance_id); header |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_DELETE_PIPELINE); header |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); @@ -2082,7 +2164,11 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget pipeline->state = SOF_IPC4_PIPE_UNINITIALIZED; ida_free(&pipeline_ida, swidget->instance_id); } else { - ida_free(&fw_module->m_ida, swidget->instance_id); + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; + + if (!pipeline->use_chain_dma) + ida_free(&fw_module->m_ida, swidget->instance_id); } mutex_unlock(&ipc4_data->pipeline_state_mutex); @@ -2234,12 +2320,27 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * { struct snd_sof_widget *src_widget = sroute->src_widget; struct snd_sof_widget *sink_widget = sroute->sink_widget; + struct snd_sof_widget *src_pipe_widget = src_widget->spipe->pipe_widget; + struct snd_sof_widget *sink_pipe_widget = sink_widget->spipe->pipe_widget; struct sof_ipc4_fw_module *src_fw_module = src_widget->module_info; struct sof_ipc4_fw_module *sink_fw_module = sink_widget->module_info; + struct sof_ipc4_pipeline *src_pipeline = src_pipe_widget->private; + struct sof_ipc4_pipeline *sink_pipeline = sink_pipe_widget->private; struct sof_ipc4_msg msg = {{ 0 }}; u32 header, extension; int ret; + /* no route set up if chain DMA is used */ + if (src_pipeline->use_chain_dma || sink_pipeline->use_chain_dma) { + if (!src_pipeline->use_chain_dma || !sink_pipeline->use_chain_dma) { + dev_err(sdev->dev, + "use_chain_dma must be set for both src %s and sink %s pipelines\n", + src_widget->widget->name, sink_widget->widget->name); + return -EINVAL; + } + return 0; + } + sroute->src_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget, SOF_PIN_TYPE_OUTPUT); if (sroute->src_queue_id < 0) { @@ -2310,9 +2411,17 @@ static int sof_ipc4_route_free(struct snd_sof_dev *sdev, struct snd_sof_route *s struct sof_ipc4_fw_module *src_fw_module = src_widget->module_info; struct sof_ipc4_fw_module *sink_fw_module = sink_widget->module_info; struct sof_ipc4_msg msg = {{ 0 }}; + struct snd_sof_widget *src_pipe_widget = src_widget->spipe->pipe_widget; + struct snd_sof_widget *sink_pipe_widget = sink_widget->spipe->pipe_widget; + struct sof_ipc4_pipeline *src_pipeline = src_pipe_widget->private; + struct sof_ipc4_pipeline *sink_pipeline = sink_pipe_widget->private; u32 header, extension; int ret = 0; + /* no route is set up if chain DMA is used */ + if (src_pipeline->use_chain_dma || sink_pipeline->use_chain_dma) + return 0; + dev_dbg(sdev->dev, "unbind modules %s:%d -> %s:%d\n", src_widget->widget->name, sroute->src_queue_id, sink_widget->widget->name, sroute->dst_queue_id); @@ -2374,6 +2483,11 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * switch (ipc4_copier->dai_type) { case SOF_DAI_INTEL_HDA: + if (pipeline->use_chain_dma) { + pipeline->msg.primary &= ~SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_MASK; + pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_LINK_ID(data->dai_data); + break; + } gtw_attr = ipc4_copier->gtw_attr; gtw_attr->lp_buffer_alloc = pipeline->lp_mode; pipeline->skip_during_fe_trigger = true; diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 015027b23588..cf007282867b 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -126,6 +126,7 @@ struct sof_ipc4_copier_config_set_sink_format { * @mem_usage: Memory usage * @core_id: Target core for the pipeline * @state: Pipeline state + * @use_chain_dma: flag to indicate if the firmware shall use chained DMA * @msg: message structure for pipeline * @skip_during_fe_trigger: skip triggering this pipeline during the FE DAI trigger */ @@ -135,6 +136,7 @@ struct sof_ipc4_pipeline { uint32_t mem_usage; uint32_t core_id; int state; + bool use_chain_dma; struct sof_ipc4_msg msg; bool skip_during_fe_trigger; }; -- cgit From fa8c052b4c614aa1d2d60e5c9f40e9d885bf9511 Mon Sep 17 00:00:00 2001 From: "Vlad.Karpovich" Date: Wed, 15 Mar 2023 10:47:18 -0500 Subject: ASoC: cs35l45: Support for GPIO pins configuration. Adds device tree configuration for cs35l45 GPIOs Signed-off-by: Vlad Karpovich Link: https://lore.kernel.org/r/20230315154722.3911463-1-vkarpovi@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l45-tables.c | 14 ++++++++++ sound/soc/codecs/cs35l45.c | 56 +++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/cs35l45.h | 27 +++++++++++++++++-- 3 files changed, 95 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c index 4b1320a2e6e9..997ea418a6dc 100644 --- a/sound/soc/codecs/cs35l45-tables.c +++ b/sound/soc/codecs/cs35l45-tables.c @@ -43,6 +43,9 @@ EXPORT_SYMBOL_NS_GPL(cs35l45_apply_patch, SND_SOC_CS35L45); static const struct reg_default cs35l45_defaults[] = { { CS35L45_BLOCK_ENABLES, 0x00003323 }, { CS35L45_BLOCK_ENABLES2, 0x00000010 }, + { CS35L45_SYNC_GPIO1, 0x00000007 }, + { CS35L45_INTB_GPIO2_MCLK_REF, 0x00000005 }, + { CS35L45_GPIO3, 0x00000005 }, { CS35L45_REFCLK_INPUT, 0x00000510 }, { CS35L45_GLOBAL_SAMPLE_RATE, 0x00000003 }, { CS35L45_ASP_ENABLES1, 0x00000000 }, @@ -61,6 +64,9 @@ static const struct reg_default cs35l45_defaults[] = { { CS35L45_ASPTX4_INPUT, 0x00000028 }, { CS35L45_ASPTX5_INPUT, 0x00000048 }, { CS35L45_AMP_PCM_CONTROL, 0x00100000 }, + { CS35L45_GPIO1_CTRL1, 0x81000001 }, + { CS35L45_GPIO2_CTRL1, 0x81000001 }, + { CS35L45_GPIO3_CTRL1, 0x81000001 }, }; static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) @@ -72,6 +78,9 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_BLOCK_ENABLES: case CS35L45_BLOCK_ENABLES2: case CS35L45_ERROR_RELEASE: + case CS35L45_SYNC_GPIO1: + case CS35L45_INTB_GPIO2_MCLK_REF: + case CS35L45_GPIO3: case CS35L45_REFCLK_INPUT: case CS35L45_GLOBAL_SAMPLE_RATE: case CS35L45_ASP_ENABLES1: @@ -92,6 +101,10 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_AMP_PCM_CONTROL: case CS35L45_AMP_PCM_HPF_TST: case CS35L45_IRQ1_EINT_4: + case CS35L45_GPIO_STATUS1: + case CS35L45_GPIO1_CTRL1: + case CS35L45_GPIO2_CTRL1: + case CS35L45_GPIO3_CTRL1: return true; default: return false; @@ -107,6 +120,7 @@ static bool cs35l45_volatile_reg(struct device *dev, unsigned int reg) case CS35L45_ERROR_RELEASE: case CS35L45_AMP_PCM_HPF_TST: /* not cachable */ case CS35L45_IRQ1_EINT_4: + case CS35L45_GPIO_STATUS1: return true; default: return false; diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c index 855d9f13e6ff..c87dccb3382e 100644 --- a/sound/soc/codecs/cs35l45.c +++ b/sound/soc/codecs/cs35l45.c @@ -536,7 +536,63 @@ static int __maybe_unused cs35l45_runtime_resume(struct device *dev) static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45) { + struct device_node *node = cs35l45->dev->of_node; + unsigned int gpio_regs[] = {CS35L45_GPIO1_CTRL1, CS35L45_GPIO2_CTRL1, + CS35L45_GPIO3_CTRL1}; + unsigned int pad_regs[] = {CS35L45_SYNC_GPIO1, + CS35L45_INTB_GPIO2_MCLK_REF, CS35L45_GPIO3}; + struct device_node *child; unsigned int val; + char of_name[32]; + int ret, i; + + if (!node) + return 0; + + for (i = 0; i < CS35L45_NUM_GPIOS; i++) { + sprintf(of_name, "cirrus,gpio-ctrl%d", i + 1); + child = of_get_child_by_name(node, of_name); + if (!child) + continue; + + ret = of_property_read_u32(child, "gpio-dir", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, gpio_regs[i], + CS35L45_GPIO_DIR_MASK, + val << CS35L45_GPIO_DIR_SHIFT); + + ret = of_property_read_u32(child, "gpio-lvl", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, gpio_regs[i], + CS35L45_GPIO_LVL_MASK, + val << CS35L45_GPIO_LVL_SHIFT); + + ret = of_property_read_u32(child, "gpio-op-cfg", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, gpio_regs[i], + CS35L45_GPIO_OP_CFG_MASK, + val << CS35L45_GPIO_OP_CFG_SHIFT); + + ret = of_property_read_u32(child, "gpio-pol", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, gpio_regs[i], + CS35L45_GPIO_POL_MASK, + val << CS35L45_GPIO_POL_SHIFT); + + ret = of_property_read_u32(child, "gpio-ctrl", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, pad_regs[i], + CS35L45_GPIO_CTRL_MASK, + val << CS35L45_GPIO_CTRL_SHIFT); + + ret = of_property_read_u32(child, "gpio-invert", &val); + if (!ret) + regmap_update_bits(cs35l45->regmap, pad_regs[i], + CS35L45_GPIO_INVERT_MASK, + val << CS35L45_GPIO_INVERT_SHIFT); + + of_node_put(child); + } if (device_property_read_u32(cs35l45->dev, "cirrus,asp-sdout-hiz-ctrl", &val) == 0) { diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h index 53fe9d2b7b15..f3a54fc57d53 100644 --- a/sound/soc/codecs/cs35l45.h +++ b/sound/soc/codecs/cs35l45.h @@ -14,6 +14,7 @@ #include #include #include +#include #define CS35L45_DEVID 0x00000000 #define CS35L45_REVID 0x00000004 @@ -24,6 +25,9 @@ #define CS35L45_BLOCK_ENABLES 0x00002018 #define CS35L45_BLOCK_ENABLES2 0x0000201C #define CS35L45_ERROR_RELEASE 0x00002034 +#define CS35L45_SYNC_GPIO1 0x00002430 +#define CS35L45_INTB_GPIO2_MCLK_REF 0x00002434 +#define CS35L45_GPIO3 0x00002438 #define CS35L45_REFCLK_INPUT 0x00002C04 #define CS35L45_GLOBAL_SAMPLE_RATE 0x00002C0C #define CS35L45_BOOST_CCM_CFG 0x00003808 @@ -48,8 +52,11 @@ #define CS35L45_AMP_PCM_CONTROL 0x00007000 #define CS35L45_AMP_PCM_HPF_TST 0x00007004 #define CS35L45_IRQ1_EINT_4 0x0000E01C -#define CS35L45_LASTREG 0x0000E01C - +#define CS35L45_GPIO_STATUS1 0x0000F000 +#define CS35L45_GPIO1_CTRL1 0x0000F008 +#define CS35L45_GPIO2_CTRL1 0x0000F00C +#define CS35L45_GPIO3_CTRL1 0x0000F010 +#define CS35L45_LASTREG 0x0000F010 /* SFT_RESET */ #define CS35L45_SOFT_RESET_TRIGGER 0x5A000000 @@ -165,6 +172,22 @@ #define CS35L45_OTP_BOOT_DONE_STS_MASK BIT(1) #define CS35L45_OTP_BUSY_MASK BIT(0) +/* GPIOX_CTRL1 */ +#define CS35L45_GPIO_DIR_SHIFT 31 +#define CS35L45_GPIO_DIR_MASK BIT(31) +#define CS35L45_GPIO_LVL_SHIFT 15 +#define CS35L45_GPIO_LVL_MASK BIT(15) +#define CS35L45_GPIO_OP_CFG_SHIFT 14 +#define CS35L45_GPIO_OP_CFG_MASK BIT(14) +#define CS35L45_GPIO_POL_SHIFT 12 +#define CS35L45_GPIO_POL_MASK BIT(12) + +/* SYNC_GPIO1, INTB_GPIO2_MCLK_REF, GPIO3 */ +#define CS35L45_GPIO_CTRL_SHIFT 20 +#define CS35L45_GPIO_CTRL_MASK GENMASK(22, 20) +#define CS35L45_GPIO_INVERT_SHIFT 19 +#define CS35L45_GPIO_INVERT_MASK BIT(19) + /* Mixer sources */ #define CS35L45_PCM_SRC_MASK 0x7F #define CS35L45_PCM_SRC_ZERO 0x00 -- cgit From 6085f9e6dc1973cf98ee7f5dcf629939e50f1b84 Mon Sep 17 00:00:00 2001 From: "Vlad.Karpovich" Date: Wed, 15 Mar 2023 10:47:20 -0500 Subject: ASoC: cs35l45: IRQ support Adds IRQ handlers Signed-off-by: Vlad Karpovich Link: https://lore.kernel.org/r/167933510218.26.11092784685990338045@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l45-i2c.c | 1 + sound/soc/codecs/cs35l45-spi.c | 1 + sound/soc/codecs/cs35l45-tables.c | 29 +++++++++- sound/soc/codecs/cs35l45.c | 111 +++++++++++++++++++++++++++++++++++++- sound/soc/codecs/cs35l45.h | 107 ++++++++++++++++++++++++++++++++++++ 5 files changed, 245 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l45-i2c.c b/sound/soc/codecs/cs35l45-i2c.c index 1117df4b2f11..33fa6d59e9a4 100644 --- a/sound/soc/codecs/cs35l45-i2c.c +++ b/sound/soc/codecs/cs35l45-i2c.c @@ -32,6 +32,7 @@ static int cs35l45_i2c_probe(struct i2c_client *client) } cs35l45->dev = dev; + cs35l45->irq = client->irq; return cs35l45_probe(cs35l45); } diff --git a/sound/soc/codecs/cs35l45-spi.c b/sound/soc/codecs/cs35l45-spi.c index ffaca07fb267..6166cff417be 100644 --- a/sound/soc/codecs/cs35l45-spi.c +++ b/sound/soc/codecs/cs35l45-spi.c @@ -32,6 +32,7 @@ static int cs35l45_spi_probe(struct spi_device *spi) } cs35l45->dev = dev; + cs35l45->irq = spi->irq; return cs35l45_probe(cs35l45); } diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c index 997ea418a6dc..eb9fb075c134 100644 --- a/sound/soc/codecs/cs35l45-tables.c +++ b/sound/soc/codecs/cs35l45-tables.c @@ -64,6 +64,25 @@ static const struct reg_default cs35l45_defaults[] = { { CS35L45_ASPTX4_INPUT, 0x00000028 }, { CS35L45_ASPTX5_INPUT, 0x00000048 }, { CS35L45_AMP_PCM_CONTROL, 0x00100000 }, + { CS35L45_IRQ1_CFG, 0x00000000 }, + { CS35L45_IRQ1_MASK_1, 0xBFEFFFBF }, + { CS35L45_IRQ1_MASK_2, 0xFFFFFFFF }, + { CS35L45_IRQ1_MASK_3, 0xFFFF87FF }, + { CS35L45_IRQ1_MASK_4, 0xF8FFFFFF }, + { CS35L45_IRQ1_MASK_5, 0x0EF80000 }, + { CS35L45_IRQ1_MASK_6, 0x00000000 }, + { CS35L45_IRQ1_MASK_7, 0xFFFFFF78 }, + { CS35L45_IRQ1_MASK_8, 0x00003FFF }, + { CS35L45_IRQ1_MASK_9, 0x00000000 }, + { CS35L45_IRQ1_MASK_10, 0x00000000 }, + { CS35L45_IRQ1_MASK_11, 0x00000000 }, + { CS35L45_IRQ1_MASK_12, 0x00000000 }, + { CS35L45_IRQ1_MASK_13, 0x00000000 }, + { CS35L45_IRQ1_MASK_14, 0x00000001 }, + { CS35L45_IRQ1_MASK_15, 0x00000000 }, + { CS35L45_IRQ1_MASK_16, 0x00000000 }, + { CS35L45_IRQ1_MASK_17, 0x00000000 }, + { CS35L45_IRQ1_MASK_18, 0x3FE5D0FF }, { CS35L45_GPIO1_CTRL1, 0x81000001 }, { CS35L45_GPIO2_CTRL1, 0x81000001 }, { CS35L45_GPIO3_CTRL1, 0x81000001 }, @@ -100,7 +119,11 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_ASPTX5_INPUT: case CS35L45_AMP_PCM_CONTROL: case CS35L45_AMP_PCM_HPF_TST: - case CS35L45_IRQ1_EINT_4: + case CS35L45_IRQ1_CFG: + case CS35L45_IRQ1_STATUS: + case CS35L45_IRQ1_EINT_1 ... CS35L45_IRQ1_EINT_18: + case CS35L45_IRQ1_STS_1 ... CS35L45_IRQ1_STS_18: + case CS35L45_IRQ1_MASK_1 ... CS35L45_IRQ1_MASK_18: case CS35L45_GPIO_STATUS1: case CS35L45_GPIO1_CTRL1: case CS35L45_GPIO2_CTRL1: @@ -119,7 +142,9 @@ static bool cs35l45_volatile_reg(struct device *dev, unsigned int reg) case CS35L45_GLOBAL_ENABLES: case CS35L45_ERROR_RELEASE: case CS35L45_AMP_PCM_HPF_TST: /* not cachable */ - case CS35L45_IRQ1_EINT_4: + case CS35L45_IRQ1_STATUS: + case CS35L45_IRQ1_EINT_1 ... CS35L45_IRQ1_EINT_18: + case CS35L45_IRQ1_STS_1 ... CS35L45_IRQ1_STS_18: case CS35L45_GPIO_STATUS1: return true; default: diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c index c87dccb3382e..a7095da34f5a 100644 --- a/sound/soc/codecs/cs35l45.c +++ b/sound/soc/codecs/cs35l45.c @@ -586,10 +586,13 @@ static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45) val << CS35L45_GPIO_CTRL_SHIFT); ret = of_property_read_u32(child, "gpio-invert", &val); - if (!ret) + if (!ret) { regmap_update_bits(cs35l45->regmap, pad_regs[i], CS35L45_GPIO_INVERT_MASK, val << CS35L45_GPIO_INVERT_SHIFT); + if (i == 1) + cs35l45->irq_invert = val; + } of_node_put(child); } @@ -604,6 +607,78 @@ static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45) return 0; } +static irqreturn_t cs35l45_pll_unlock(int irq, void *data) +{ + struct cs35l45_private *cs35l45 = data; + + dev_dbg(cs35l45->dev, "PLL unlock detected!"); + + return IRQ_HANDLED; +} + +static irqreturn_t cs35l45_pll_lock(int irq, void *data) +{ + struct cs35l45_private *cs35l45 = data; + + dev_dbg(cs35l45->dev, "PLL lock detected!"); + + return IRQ_HANDLED; +} + +static irqreturn_t cs35l45_spk_safe_err(int irq, void *data); + +static const struct cs35l45_irq cs35l45_irqs[] = { + CS35L45_IRQ(AMP_SHORT_ERR, "Amplifier short error", cs35l45_spk_safe_err), + CS35L45_IRQ(UVLO_VDDBATT_ERR, "VDDBATT undervoltage error", cs35l45_spk_safe_err), + CS35L45_IRQ(BST_SHORT_ERR, "Boost inductor error", cs35l45_spk_safe_err), + CS35L45_IRQ(BST_UVP_ERR, "Boost undervoltage error", cs35l45_spk_safe_err), + CS35L45_IRQ(TEMP_ERR, "Overtemperature error", cs35l45_spk_safe_err), + CS35L45_IRQ(AMP_CAL_ERR, "Amplifier calibration error", cs35l45_spk_safe_err), + CS35L45_IRQ(UVLO_VDDLV_ERR, "LV threshold detector error", cs35l45_spk_safe_err), + CS35L45_IRQ(GLOBAL_ERROR, "Global error", cs35l45_spk_safe_err), + CS35L45_IRQ(DSP_WDT_EXPIRE, "DSP Watchdog Timer", cs35l45_spk_safe_err), + CS35L45_IRQ(PLL_UNLOCK_FLAG_RISE, "PLL unlock", cs35l45_pll_unlock), + CS35L45_IRQ(PLL_LOCK_FLAG, "PLL lock", cs35l45_pll_lock), +}; + +static irqreturn_t cs35l45_spk_safe_err(int irq, void *data) +{ + struct cs35l45_private *cs35l45 = data; + int i; + + i = irq - regmap_irq_get_virq(cs35l45->irq_data, 0); + + dev_err(cs35l45->dev, "%s condition detected!\n", cs35l45_irqs[i].name); + + return IRQ_HANDLED; +} + +static const struct regmap_irq cs35l45_reg_irqs[] = { + CS35L45_REG_IRQ(IRQ1_EINT_1, AMP_SHORT_ERR), + CS35L45_REG_IRQ(IRQ1_EINT_1, UVLO_VDDBATT_ERR), + CS35L45_REG_IRQ(IRQ1_EINT_1, BST_SHORT_ERR), + CS35L45_REG_IRQ(IRQ1_EINT_1, BST_UVP_ERR), + CS35L45_REG_IRQ(IRQ1_EINT_1, TEMP_ERR), + CS35L45_REG_IRQ(IRQ1_EINT_3, AMP_CAL_ERR), + CS35L45_REG_IRQ(IRQ1_EINT_18, UVLO_VDDLV_ERR), + CS35L45_REG_IRQ(IRQ1_EINT_18, GLOBAL_ERROR), + CS35L45_REG_IRQ(IRQ1_EINT_2, DSP_WDT_EXPIRE), + CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_UNLOCK_FLAG_RISE), + CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_LOCK_FLAG), +}; + +static const struct regmap_irq_chip cs35l45_regmap_irq_chip = { + .name = "cs35l45 IRQ1 Controller", + .main_status = CS35L45_IRQ1_STATUS, + .status_base = CS35L45_IRQ1_EINT_1, + .mask_base = CS35L45_IRQ1_MASK_1, + .ack_base = CS35L45_IRQ1_EINT_1, + .num_regs = 18, + .irqs = cs35l45_reg_irqs, + .num_irqs = ARRAY_SIZE(cs35l45_reg_irqs), + .runtime_pm = true, +}; + static int cs35l45_initialize(struct cs35l45_private *cs35l45) { struct device *dev = cs35l45->dev; @@ -660,7 +735,8 @@ static int cs35l45_initialize(struct cs35l45_private *cs35l45) int cs35l45_probe(struct cs35l45_private *cs35l45) { struct device *dev = cs35l45->dev; - int ret; + unsigned long irq_pol = IRQF_ONESHOT | IRQF_SHARED; + int ret, i, irq; cs35l45->vdd_batt = devm_regulator_get(dev, "vdd-batt"); if (IS_ERR(cs35l45->vdd_batt)) @@ -705,6 +781,37 @@ int cs35l45_probe(struct cs35l45_private *cs35l45) if (ret < 0) goto err_reset; + if (cs35l45->irq) { + if (cs35l45->irq_invert) + irq_pol |= IRQF_TRIGGER_HIGH; + else + irq_pol |= IRQF_TRIGGER_LOW; + + ret = devm_regmap_add_irq_chip(dev, cs35l45->regmap, cs35l45->irq, irq_pol, 0, + &cs35l45_regmap_irq_chip, &cs35l45->irq_data); + if (ret) { + dev_err(dev, "Failed to register IRQ chip: %d\n", ret); + goto err_reset; + } + + for (i = 0; i < ARRAY_SIZE(cs35l45_irqs); i++) { + irq = regmap_irq_get_virq(cs35l45->irq_data, cs35l45_irqs[i].irq); + if (irq < 0) { + dev_err(dev, "Failed to get %s\n", cs35l45_irqs[i].name); + ret = irq; + goto err_reset; + } + + ret = devm_request_threaded_irq(dev, irq, NULL, cs35l45_irqs[i].handler, + irq_pol, cs35l45_irqs[i].name, cs35l45); + if (ret) { + dev_err(dev, "Failed to request IRQ %s: %d\n", + cs35l45_irqs[i].name, ret); + goto err_reset; + } + } + } + ret = devm_snd_soc_register_component(dev, &cs35l45_component, cs35l45_dai, ARRAY_SIZE(cs35l45_dai)); diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h index f3a54fc57d53..ce92f5068ac5 100644 --- a/sound/soc/codecs/cs35l45.h +++ b/sound/soc/codecs/cs35l45.h @@ -51,7 +51,42 @@ #define CS35L45_LDPM_CONFIG 0x00006404 #define CS35L45_AMP_PCM_CONTROL 0x00007000 #define CS35L45_AMP_PCM_HPF_TST 0x00007004 +#define CS35L45_IRQ1_CFG 0x0000E000 +#define CS35L45_IRQ1_STATUS 0x0000E004 +#define CS35L45_IRQ1_EINT_1 0x0000E010 +#define CS35L45_IRQ1_EINT_2 0x0000E014 +#define CS35L45_IRQ1_EINT_3 0x0000E018 #define CS35L45_IRQ1_EINT_4 0x0000E01C +#define CS35L45_IRQ1_EINT_5 0x0000E020 +#define CS35L45_IRQ1_EINT_7 0x0000E028 +#define CS35L45_IRQ1_EINT_8 0x0000E02C +#define CS35L45_IRQ1_EINT_18 0x0000E054 +#define CS35L45_IRQ1_STS_1 0x0000E090 +#define CS35L45_IRQ1_STS_2 0x0000E094 +#define CS35L45_IRQ1_STS_3 0x0000E098 +#define CS35L45_IRQ1_STS_4 0x0000E09C +#define CS35L45_IRQ1_STS_5 0x0000E0A0 +#define CS35L45_IRQ1_STS_7 0x0000E0A8 +#define CS35L45_IRQ1_STS_8 0x0000E0AC +#define CS35L45_IRQ1_STS_18 0x0000E0D4 +#define CS35L45_IRQ1_MASK_1 0x0000E110 +#define CS35L45_IRQ1_MASK_2 0x0000E114 +#define CS35L45_IRQ1_MASK_3 0x0000E118 +#define CS35L45_IRQ1_MASK_4 0x0000E11C +#define CS35L45_IRQ1_MASK_5 0x0000E120 +#define CS35L45_IRQ1_MASK_6 0x0000E124 +#define CS35L45_IRQ1_MASK_7 0x0000E128 +#define CS35L45_IRQ1_MASK_8 0x0000E12C +#define CS35L45_IRQ1_MASK_9 0x0000E130 +#define CS35L45_IRQ1_MASK_10 0x0000E134 +#define CS35L45_IRQ1_MASK_11 0x0000E138 +#define CS35L45_IRQ1_MASK_12 0x0000E13C +#define CS35L45_IRQ1_MASK_13 0x0000E140 +#define CS35L45_IRQ1_MASK_14 0x0000E144 +#define CS35L45_IRQ1_MASK_15 0x0000E148 +#define CS35L45_IRQ1_MASK_16 0x0000E14C +#define CS35L45_IRQ1_MASK_17 0x0000E150 +#define CS35L45_IRQ1_MASK_18 0x0000E154 #define CS35L45_GPIO_STATUS1 0x0000F000 #define CS35L45_GPIO1_CTRL1 0x0000F008 #define CS35L45_GPIO2_CTRL1 0x0000F00C @@ -188,6 +223,38 @@ #define CS35L45_GPIO_INVERT_SHIFT 19 #define CS35L45_GPIO_INVERT_MASK BIT(19) +/* CS35L45_IRQ1_EINT_1 */ +#define CS35L45_BST_UVP_ERR_SHIFT 7 +#define CS35L45_BST_UVP_ERR_MASK BIT(7) +#define CS35L45_BST_SHORT_ERR_SHIFT 8 +#define CS35L45_BST_SHORT_ERR_MASK BIT(8) +#define CS35L45_TEMP_ERR_SHIFT 17 +#define CS35L45_TEMP_ERR_MASK BIT(17) +#define CS35L45_MSM_GLOBAL_EN_ASSERT_SHIFT 22 +#define CS35L45_MSM_GLOBAL_EN_ASSERT_MASK BIT(22) +#define CS35L45_UVLO_VDDBATT_ERR_SHIFT 29 +#define CS35L45_UVLO_VDDBATT_ERR_MASK BIT(29) +#define CS35L45_AMP_SHORT_ERR_SHIFT 31 +#define CS35L45_AMP_SHORT_ERR_MASK BIT(31) + +/* CS35L45_IRQ1_EINT_2 */ +#define CS35L45_DSP_WDT_EXPIRE_SHIFT 4 +#define CS35L45_DSP_WDT_EXPIRE_MASK BIT(4) + +/* CS35L45_IRQ1_EINT_3 */ +#define CS35L45_PLL_LOCK_FLAG_SHIFT 1 +#define CS35L45_PLL_LOCK_FLAG_MASK BIT(1) +#define CS35L45_PLL_UNLOCK_FLAG_RISE_SHIFT 4 +#define CS35L45_PLL_UNLOCK_FLAG_RISE_MASK BIT(4) +#define CS35L45_AMP_CAL_ERR_SHIFT 25 +#define CS35L45_AMP_CAL_ERR_MASK BIT(25) + +/* CS35L45_IRQ1_EINT_18 */ +#define CS35L45_GLOBAL_ERROR_SHIFT 15 +#define CS35L45_GLOBAL_ERROR_MASK BIT(15) +#define CS35L45_UVLO_VDDLV_ERR_SHIFT 16 +#define CS35L45_UVLO_VDDLV_ERR_MASK BIT(16) + /* Mixer sources */ #define CS35L45_PCM_SRC_MASK 0x7F #define CS35L45_PCM_SRC_ZERO 0x00 @@ -217,6 +284,43 @@ SNDRV_PCM_RATE_88200 | \ SNDRV_PCM_RATE_96000) +/* + * IRQs + */ +#define CS35L45_IRQ(_irq, _name, _hand) \ + { \ + .irq = CS35L45_ ## _irq ## _IRQ,\ + .name = _name, \ + .handler = _hand, \ + } + +struct cs35l45_irq { + int irq; + const char *name; + irqreturn_t (*handler)(int irq, void *data); +}; + +#define CS35L45_REG_IRQ(_reg, _irq) \ + [CS35L45_ ## _irq ## _IRQ] = { \ + .reg_offset = (CS35L45_ ## _reg) - CS35L45_IRQ1_EINT_1, \ + .mask = CS35L45_ ## _irq ## _MASK \ + } + +enum cs35l45_irq_list { + CS35L45_AMP_SHORT_ERR_IRQ, + CS35L45_UVLO_VDDBATT_ERR_IRQ, + CS35L45_BST_SHORT_ERR_IRQ, + CS35L45_BST_UVP_ERR_IRQ, + CS35L45_TEMP_ERR_IRQ, + CS35L45_AMP_CAL_ERR_IRQ, + CS35L45_UVLO_VDDLV_ERR_IRQ, + CS35L45_GLOBAL_ERROR_IRQ, + CS35L45_DSP_WDT_EXPIRE_IRQ, + CS35L45_PLL_UNLOCK_FLAG_RISE_IRQ, + CS35L45_PLL_LOCK_FLAG_IRQ, + CS35L45_NUM_IRQ +}; + struct cs35l45_private { struct device *dev; struct regmap *regmap; @@ -227,6 +331,9 @@ struct cs35l45_private { bool sysclk_set; u8 slot_width; u8 slot_count; + int irq_invert; + int irq; + struct regmap_irq_chip_data *irq_data; }; extern const struct dev_pm_ops cs35l45_pm_ops; -- cgit From 74b14e2850a34740c121cf2758d4181063d4c77c Mon Sep 17 00:00:00 2001 From: "Vlad.Karpovich" Date: Wed, 15 Mar 2023 10:47:21 -0500 Subject: ASoC: cs35l45: DSP Support The CS35L45 digital core incorporates one programmable DSP block, capable of running a wide range of audio enhancement and speaker and battery protection functions. Signed-off-by: Vlad Karpovich Link: https://lore.kernel.org/r/167933510679.26.5992985447093367768@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/cs35l45-spi.c | 3 + sound/soc/codecs/cs35l45-tables.c | 86 +++++++++ sound/soc/codecs/cs35l45.c | 391 ++++++++++++++++++++++++++++++++++++-- sound/soc/codecs/cs35l45.h | 108 ++++++++++- 5 files changed, 579 insertions(+), 13 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 07747565c3b5..090f296e6857 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -364,6 +364,8 @@ config SND_SOC_WM_ADSP default y if SND_SOC_WM2200=y default y if SND_SOC_CS35L41_SPI=y default y if SND_SOC_CS35L41_I2C=y + default y if SND_SOC_CS35L45_SPI=y + default y if SND_SOC_CS35L45_I2C=y default m if SND_SOC_MADERA=m default m if SND_SOC_CS47L24=m default m if SND_SOC_WM5102=m @@ -371,6 +373,8 @@ config SND_SOC_WM_ADSP default m if SND_SOC_WM2200=m default m if SND_SOC_CS35L41_SPI=m default m if SND_SOC_CS35L41_I2C=m + default m if SND_SOC_CS35L45_SPI=m + default m if SND_SOC_CS35L45_I2C=m config SND_SOC_AB8500_CODEC tristate diff --git a/sound/soc/codecs/cs35l45-spi.c b/sound/soc/codecs/cs35l45-spi.c index 6166cff417be..99657325a281 100644 --- a/sound/soc/codecs/cs35l45-spi.c +++ b/sound/soc/codecs/cs35l45-spi.c @@ -23,6 +23,9 @@ static int cs35l45_spi_probe(struct spi_device *spi) if (cs35l45 == NULL) return -ENOMEM; + spi->max_speed_hz = CS35L45_SPI_MAX_FREQ; + spi_setup(spi); + spi_set_drvdata(spi, cs35l45); cs35l45->regmap = devm_regmap_init_spi(spi, &cs35l45_spi_regmap); if (IS_ERR(cs35l45->regmap)) { diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c index eb9fb075c134..434a6473070e 100644 --- a/sound/soc/codecs/cs35l45-tables.c +++ b/sound/soc/codecs/cs35l45-tables.c @@ -46,6 +46,7 @@ static const struct reg_default cs35l45_defaults[] = { { CS35L45_SYNC_GPIO1, 0x00000007 }, { CS35L45_INTB_GPIO2_MCLK_REF, 0x00000005 }, { CS35L45_GPIO3, 0x00000005 }, + { CS35L45_PWRMGT_CTL, 0x00000000 }, { CS35L45_REFCLK_INPUT, 0x00000510 }, { CS35L45_GLOBAL_SAMPLE_RATE, 0x00000003 }, { CS35L45_ASP_ENABLES1, 0x00000000 }, @@ -63,6 +64,30 @@ static const struct reg_default cs35l45_defaults[] = { { CS35L45_ASPTX3_INPUT, 0x00000020 }, { CS35L45_ASPTX4_INPUT, 0x00000028 }, { CS35L45_ASPTX5_INPUT, 0x00000048 }, + { CS35L45_DSP1_RX1_RATE, 0x00000001 }, + { CS35L45_DSP1_RX2_RATE, 0x00000001 }, + { CS35L45_DSP1_RX3_RATE, 0x00000001 }, + { CS35L45_DSP1_RX4_RATE, 0x00000001 }, + { CS35L45_DSP1_RX5_RATE, 0x00000001 }, + { CS35L45_DSP1_RX6_RATE, 0x00000001 }, + { CS35L45_DSP1_RX7_RATE, 0x00000001 }, + { CS35L45_DSP1_RX8_RATE, 0x00000001 }, + { CS35L45_DSP1_TX1_RATE, 0x00000001 }, + { CS35L45_DSP1_TX2_RATE, 0x00000001 }, + { CS35L45_DSP1_TX3_RATE, 0x00000001 }, + { CS35L45_DSP1_TX4_RATE, 0x00000001 }, + { CS35L45_DSP1_TX5_RATE, 0x00000001 }, + { CS35L45_DSP1_TX6_RATE, 0x00000001 }, + { CS35L45_DSP1_TX7_RATE, 0x00000001 }, + { CS35L45_DSP1_TX8_RATE, 0x00000001 }, + { CS35L45_DSP1RX1_INPUT, 0x00000008 }, + { CS35L45_DSP1RX2_INPUT, 0x00000009 }, + { CS35L45_DSP1RX3_INPUT, 0x00000018 }, + { CS35L45_DSP1RX4_INPUT, 0x00000019 }, + { CS35L45_DSP1RX5_INPUT, 0x00000020 }, + { CS35L45_DSP1RX6_INPUT, 0x00000028 }, + { CS35L45_DSP1RX7_INPUT, 0x0000003A }, + { CS35L45_DSP1RX8_INPUT, 0x00000028 }, { CS35L45_AMP_PCM_CONTROL, 0x00100000 }, { CS35L45_IRQ1_CFG, 0x00000000 }, { CS35L45_IRQ1_MASK_1, 0xBFEFFFBF }, @@ -100,6 +125,7 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_SYNC_GPIO1: case CS35L45_INTB_GPIO2_MCLK_REF: case CS35L45_GPIO3: + case CS35L45_PWRMGT_CTL: case CS35L45_REFCLK_INPUT: case CS35L45_GLOBAL_SAMPLE_RATE: case CS35L45_ASP_ENABLES1: @@ -117,6 +143,14 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_ASPTX3_INPUT: case CS35L45_ASPTX4_INPUT: case CS35L45_ASPTX5_INPUT: + case CS35L45_DSP1RX1_INPUT: + case CS35L45_DSP1RX2_INPUT: + case CS35L45_DSP1RX3_INPUT: + case CS35L45_DSP1RX4_INPUT: + case CS35L45_DSP1RX5_INPUT: + case CS35L45_DSP1RX6_INPUT: + case CS35L45_DSP1RX7_INPUT: + case CS35L45_DSP1RX8_INPUT: case CS35L45_AMP_PCM_CONTROL: case CS35L45_AMP_PCM_HPF_TST: case CS35L45_IRQ1_CFG: @@ -128,6 +162,40 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_GPIO1_CTRL1: case CS35L45_GPIO2_CTRL1: case CS35L45_GPIO3_CTRL1: + case CS35L45_DSP_MBOX_1: + case CS35L45_DSP_MBOX_2: + case CS35L45_DSP_VIRT1_MBOX_1 ... CS35L45_DSP_VIRT1_MBOX_4: + case CS35L45_DSP_VIRT2_MBOX_1 ... CS35L45_DSP_VIRT2_MBOX_4: + case CS35L45_DSP1_SYS_ID: + case CS35L45_DSP1_CLOCK_FREQ: + case CS35L45_DSP1_RX1_RATE: + case CS35L45_DSP1_RX2_RATE: + case CS35L45_DSP1_RX3_RATE: + case CS35L45_DSP1_RX4_RATE: + case CS35L45_DSP1_RX5_RATE: + case CS35L45_DSP1_RX6_RATE: + case CS35L45_DSP1_RX7_RATE: + case CS35L45_DSP1_RX8_RATE: + case CS35L45_DSP1_TX1_RATE: + case CS35L45_DSP1_TX2_RATE: + case CS35L45_DSP1_TX3_RATE: + case CS35L45_DSP1_TX4_RATE: + case CS35L45_DSP1_TX5_RATE: + case CS35L45_DSP1_TX6_RATE: + case CS35L45_DSP1_TX7_RATE: + case CS35L45_DSP1_TX8_RATE: + case CS35L45_DSP1_SCRATCH1: + case CS35L45_DSP1_SCRATCH2: + case CS35L45_DSP1_SCRATCH3: + case CS35L45_DSP1_SCRATCH4: + case CS35L45_DSP1_CCM_CORE_CONTROL: + case CS35L45_DSP1_XMEM_PACK_0 ... CS35L45_DSP1_XMEM_PACK_4607: + case CS35L45_DSP1_XMEM_UNPACK32_0 ... CS35L45_DSP1_XMEM_UNPACK32_3071: + case CS35L45_DSP1_XMEM_UNPACK24_0 ... CS35L45_DSP1_XMEM_UNPACK24_6143: + case CS35L45_DSP1_YMEM_PACK_0 ... CS35L45_DSP1_YMEM_PACK_1532: + case CS35L45_DSP1_YMEM_UNPACK32_0 ... CS35L45_DSP1_YMEM_UNPACK32_1022: + case CS35L45_DSP1_YMEM_UNPACK24_0 ... CS35L45_DSP1_YMEM_UNPACK24_2043: + case CS35L45_DSP1_PMEM_0 ... CS35L45_DSP1_PMEM_3834: return true; default: return false; @@ -146,6 +214,24 @@ static bool cs35l45_volatile_reg(struct device *dev, unsigned int reg) case CS35L45_IRQ1_EINT_1 ... CS35L45_IRQ1_EINT_18: case CS35L45_IRQ1_STS_1 ... CS35L45_IRQ1_STS_18: case CS35L45_GPIO_STATUS1: + case CS35L45_DSP_MBOX_1: + case CS35L45_DSP_MBOX_2: + case CS35L45_DSP_VIRT1_MBOX_1 ... CS35L45_DSP_VIRT1_MBOX_4: + case CS35L45_DSP_VIRT2_MBOX_1 ... CS35L45_DSP_VIRT2_MBOX_4: + case CS35L45_DSP1_SYS_ID: + case CS35L45_DSP1_CLOCK_FREQ: + case CS35L45_DSP1_SCRATCH1: + case CS35L45_DSP1_SCRATCH2: + case CS35L45_DSP1_SCRATCH3: + case CS35L45_DSP1_SCRATCH4: + case CS35L45_DSP1_CCM_CORE_CONTROL: + case CS35L45_DSP1_XMEM_PACK_0 ... CS35L45_DSP1_XMEM_PACK_4607: + case CS35L45_DSP1_XMEM_UNPACK32_0 ... CS35L45_DSP1_XMEM_UNPACK32_3071: + case CS35L45_DSP1_XMEM_UNPACK24_0 ... CS35L45_DSP1_XMEM_UNPACK24_6143: + case CS35L45_DSP1_YMEM_PACK_0 ... CS35L45_DSP1_YMEM_PACK_1532: + case CS35L45_DSP1_YMEM_UNPACK32_0 ... CS35L45_DSP1_YMEM_UNPACK32_1022: + case CS35L45_DSP1_YMEM_UNPACK24_0 ... CS35L45_DSP1_YMEM_UNPACK24_2043: + case CS35L45_DSP1_PMEM_0 ... CS35L45_DSP1_PMEM_3834: return true; default: return false; diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c index a7095da34f5a..97f6819fa2ad 100644 --- a/sound/soc/codecs/cs35l45.c +++ b/sound/soc/codecs/cs35l45.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,69 @@ #include "cs35l45.h" +static bool cs35l45_check_cspl_mbox_sts(const enum cs35l45_cspl_mboxcmd cmd, + enum cs35l45_cspl_mboxstate sts) +{ + switch (cmd) { + case CSPL_MBOX_CMD_NONE: + case CSPL_MBOX_CMD_UNKNOWN_CMD: + return true; + case CSPL_MBOX_CMD_PAUSE: + case CSPL_MBOX_CMD_OUT_OF_HIBERNATE: + return (sts == CSPL_MBOX_STS_PAUSED); + case CSPL_MBOX_CMD_RESUME: + return (sts == CSPL_MBOX_STS_RUNNING); + case CSPL_MBOX_CMD_REINIT: + return (sts == CSPL_MBOX_STS_RUNNING); + case CSPL_MBOX_CMD_STOP_PRE_REINIT: + return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT); + default: + return false; + } +} + +static int cs35l45_set_cspl_mbox_cmd(struct cs35l45_private *cs35l45, + struct regmap *regmap, + const enum cs35l45_cspl_mboxcmd cmd) +{ + unsigned int sts = 0, i; + int ret; + + if (!cs35l45->dsp.cs_dsp.running) { + dev_err(cs35l45->dev, "DSP not running\n"); + return -EPERM; + } + + // Set mailbox cmd + ret = regmap_write(regmap, CS35L45_DSP_VIRT1_MBOX_1, cmd); + if (ret < 0) { + if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE) + dev_err(cs35l45->dev, "Failed to write MBOX: %d\n", ret); + return ret; + } + + // Read mailbox status and verify it is appropriate for the given cmd + for (i = 0; i < 5; i++) { + usleep_range(1000, 1100); + + ret = regmap_read(regmap, CS35L45_DSP_MBOX_2, &sts); + if (ret < 0) { + dev_err(cs35l45->dev, "Failed to read MBOX STS: %d\n", ret); + continue; + } + + if (!cs35l45_check_cspl_mbox_sts(cmd, sts)) + dev_dbg(cs35l45->dev, "[%u] cmd %u returned invalid sts %u", i, cmd, sts); + else + return 0; + } + + if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE) + dev_err(cs35l45->dev, "Failed to set mailbox cmd %u (status %u)\n", cmd, sts); + + return -ENOMSG; +} + static int cs35l45_global_en_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -46,10 +110,68 @@ static int cs35l45_global_en_ev(struct snd_soc_dapm_widget *w, return 0; } +static int cs35l45_dsp_preload_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); + int ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (cs35l45->dsp.cs_dsp.booted) + return 0; + + return wm_adsp_early_event(w, kcontrol, event); + case SND_SOC_DAPM_POST_PMU: + if (cs35l45->dsp.cs_dsp.running) + return 0; + + regmap_set_bits(cs35l45->regmap, CS35L45_PWRMGT_CTL, + CS35L45_MEM_RDY_MASK); + + return wm_adsp_event(w, kcontrol, event); + case SND_SOC_DAPM_PRE_PMD: + if (cs35l45->dsp.preloaded) + return 0; + + if (cs35l45->dsp.cs_dsp.running) { + ret = wm_adsp_event(w, kcontrol, event); + if (ret) + return ret; + } + + return wm_adsp_early_event(w, kcontrol, event); + default: + return 0; + } +} + +static int cs35l45_dsp_audio_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + return cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap, + CSPL_MBOX_CMD_RESUME); + case SND_SOC_DAPM_PRE_PMD: + return cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap, + CSPL_MBOX_CMD_PAUSE); + default: + return 0; + } + + return 0; +} + static const char * const cs35l45_asp_tx_txt[] = { "Zero", "ASP_RX1", "ASP_RX2", "VMON", "IMON", "ERR_VOL", "VDD_BATTMON", "VDD_BSTMON", + "DSP_TX1", "DSP_TX2", "Interpolator", "IL_TARGET", }; @@ -57,6 +179,7 @@ static const unsigned int cs35l45_asp_tx_val[] = { CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2, CS35L45_PCM_SRC_VMON, CS35L45_PCM_SRC_IMON, CS35L45_PCM_SRC_ERR_VOL, CS35L45_PCM_SRC_VDD_BATTMON, CS35L45_PCM_SRC_VDD_BSTMON, + CS35L45_PCM_SRC_DSP_TX1, CS35L45_PCM_SRC_DSP_TX2, CS35L45_PCM_SRC_INTERPOLATOR, CS35L45_PCM_SRC_IL_TARGET, }; @@ -78,12 +201,54 @@ static const struct soc_enum cs35l45_asp_tx_enums[] = { cs35l45_asp_tx_val), }; +static const char * const cs35l45_dsp_rx_txt[] = { + "Zero", "ASP_RX1", "ASP_RX2", + "VMON", "IMON", "ERR_VOL", + "CLASSH_TGT", "VDD_BATTMON", + "VDD_BSTMON", "TEMPMON", +}; + +static const unsigned int cs35l45_dsp_rx_val[] = { + CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2, + CS35L45_PCM_SRC_VMON, CS35L45_PCM_SRC_IMON, CS35L45_PCM_SRC_ERR_VOL, + CS35L45_PCM_SRC_CLASSH_TGT, CS35L45_PCM_SRC_VDD_BATTMON, + CS35L45_PCM_SRC_VDD_BSTMON, CS35L45_PCM_SRC_TEMPMON, +}; + +static const struct soc_enum cs35l45_dsp_rx_enums[] = { + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX1_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX2_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX3_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX4_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX5_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX6_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX7_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), + SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX8_INPUT, 0, CS35L45_PCM_SRC_MASK, + ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, + cs35l45_dsp_rx_val), +}; + static const char * const cs35l45_dac_txt[] = { - "Zero", "ASP_RX1", "ASP_RX2" + "Zero", "ASP_RX1", "ASP_RX2", "DSP_TX1", "DSP_TX2" }; static const unsigned int cs35l45_dac_val[] = { - CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2 + CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2, + CS35L45_PCM_SRC_DSP_TX1, CS35L45_PCM_SRC_DSP_TX2 }; static const struct soc_enum cs35l45_dacpcm_enums[] = { @@ -100,11 +265,29 @@ static const struct snd_kcontrol_new cs35l45_asp_muxes[] = { SOC_DAPM_ENUM("ASP_TX5 Source", cs35l45_asp_tx_enums[4]), }; +static const struct snd_kcontrol_new cs35l45_dsp_muxes[] = { + SOC_DAPM_ENUM("DSP_RX1 Source", cs35l45_dsp_rx_enums[0]), + SOC_DAPM_ENUM("DSP_RX2 Source", cs35l45_dsp_rx_enums[1]), + SOC_DAPM_ENUM("DSP_RX3 Source", cs35l45_dsp_rx_enums[2]), + SOC_DAPM_ENUM("DSP_RX4 Source", cs35l45_dsp_rx_enums[3]), + SOC_DAPM_ENUM("DSP_RX5 Source", cs35l45_dsp_rx_enums[4]), + SOC_DAPM_ENUM("DSP_RX6 Source", cs35l45_dsp_rx_enums[5]), + SOC_DAPM_ENUM("DSP_RX7 Source", cs35l45_dsp_rx_enums[6]), + SOC_DAPM_ENUM("DSP_RX8 Source", cs35l45_dsp_rx_enums[7]), +}; + static const struct snd_kcontrol_new cs35l45_dac_muxes[] = { SOC_DAPM_ENUM("DACPCM1 Source", cs35l45_dacpcm_enums[0]), }; static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { + SND_SOC_DAPM_SPK("DSP1 Preload", NULL), + SND_SOC_DAPM_SUPPLY_S("DSP1 Preloader", 100, SND_SOC_NOPM, 0, 0, + cs35l45_dsp_preload_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_OUT_DRV_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, + cs35l45_dsp_audio_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_SUPPLY("GLOBAL_EN", SND_SOC_NOPM, 0, 0, cs35l45_global_en_ev, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), @@ -139,6 +322,15 @@ static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { SND_SOC_DAPM_MUX("ASP_TX4 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[3]), SND_SOC_DAPM_MUX("ASP_TX5 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[4]), + SND_SOC_DAPM_MUX("DSP_RX1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[0]), + SND_SOC_DAPM_MUX("DSP_RX2 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[1]), + SND_SOC_DAPM_MUX("DSP_RX3 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[2]), + SND_SOC_DAPM_MUX("DSP_RX4 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[3]), + SND_SOC_DAPM_MUX("DSP_RX5 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[4]), + SND_SOC_DAPM_MUX("DSP_RX6 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[5]), + SND_SOC_DAPM_MUX("DSP_RX7 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[6]), + SND_SOC_DAPM_MUX("DSP_RX8 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[7]), + SND_SOC_DAPM_MUX("DACPCM1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dac_muxes[0]), SND_SOC_DAPM_OUT_DRV("AMP", SND_SOC_NOPM, 0, 0, NULL, 0), @@ -149,6 +341,8 @@ static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { #define CS35L45_ASP_MUX_ROUTE(name) \ { name" Source", "ASP_RX1", "ASP_RX1" }, \ { name" Source", "ASP_RX2", "ASP_RX2" }, \ + { name" Source", "DSP_TX1", "DSP1" }, \ + { name" Source", "DSP_TX2", "DSP1" }, \ { name" Source", "VMON", "VMON" }, \ { name" Source", "IMON", "IMON" }, \ { name" Source", "ERR_VOL", "ERR_VOL" }, \ @@ -157,10 +351,16 @@ static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { { name" Source", "Interpolator", "AMP_INTP" }, \ { name" Source", "IL_TARGET", "IL_TARGET" } -#define CS35L45_DAC_MUX_ROUTE(name) \ +#define CS35L45_DSP_MUX_ROUTE(name) \ { name" Source", "ASP_RX1", "ASP_RX1" }, \ { name" Source", "ASP_RX2", "ASP_RX2" } +#define CS35L45_DAC_MUX_ROUTE(name) \ + { name" Source", "ASP_RX1", "ASP_RX1" }, \ + { name" Source", "ASP_RX2", "ASP_RX2" }, \ + { name" Source", "DSP_TX1", "DSP1" }, \ + { name" Source", "DSP_TX2", "DSP1" } + static const struct snd_soc_dapm_route cs35l45_dapm_routes[] = { /* Feedback */ { "VMON", NULL, "VMON_SRC" }, @@ -204,6 +404,27 @@ static const struct snd_soc_dapm_route cs35l45_dapm_routes[] = { { "AMP", NULL, "DACPCM1 Source"}, { "AMP", NULL, "GLOBAL_EN"}, + CS35L45_DSP_MUX_ROUTE("DSP_RX1"), + CS35L45_DSP_MUX_ROUTE("DSP_RX2"), + CS35L45_DSP_MUX_ROUTE("DSP_RX3"), + CS35L45_DSP_MUX_ROUTE("DSP_RX4"), + CS35L45_DSP_MUX_ROUTE("DSP_RX5"), + CS35L45_DSP_MUX_ROUTE("DSP_RX6"), + CS35L45_DSP_MUX_ROUTE("DSP_RX7"), + CS35L45_DSP_MUX_ROUTE("DSP_RX8"), + + {"DSP1", NULL, "DSP_RX1 Source"}, + {"DSP1", NULL, "DSP_RX2 Source"}, + {"DSP1", NULL, "DSP_RX3 Source"}, + {"DSP1", NULL, "DSP_RX4 Source"}, + {"DSP1", NULL, "DSP_RX5 Source"}, + {"DSP1", NULL, "DSP_RX6 Source"}, + {"DSP1", NULL, "DSP_RX7 Source"}, + {"DSP1", NULL, "DSP_RX8 Source"}, + + {"DSP1 Preload", NULL, "DSP1 Preloader"}, + {"DSP1", NULL, "DSP1 Preloader"}, + CS35L45_DAC_MUX_ROUTE("DACPCM1"), { "SPK", NULL, "AMP"}, @@ -219,6 +440,8 @@ static const struct snd_kcontrol_new cs35l45_controls[] = { -409, 48, (CS35L45_AMP_VOL_PCM_WIDTH - 1) - 1, 0, cs35l45_dig_pcm_vol_tlv), + WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), + WM_ADSP_FW_CONTROL("DSP1", 0), }; static int cs35l45_set_pll(struct cs35l45_private *cs35l45, unsigned int freq) @@ -489,7 +712,24 @@ static struct snd_soc_dai_driver cs35l45_dai[] = { }, }; +static int cs35l45_component_probe(struct snd_soc_component *component) +{ + struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); + + return wm_adsp2_component_probe(&cs35l45->dsp, component); +} + +static void cs35l45_component_remove(struct snd_soc_component *component) +{ + struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); + + wm_adsp2_component_remove(&cs35l45->dsp, component); +} + static const struct snd_soc_component_driver cs35l45_component = { + .probe = cs35l45_component_probe, + .remove = cs35l45_component_remove, + .dapm_widgets = cs35l45_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(cs35l45_dapm_widgets), @@ -607,6 +847,60 @@ static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45) return 0; } +static int cs35l45_dsp_virt2_mbox3_irq_handle(struct cs35l45_private *cs35l45, + const unsigned int cmd, + unsigned int data) +{ + static char *speak_status = "Unknown"; + + switch (cmd) { + case EVENT_SPEAKER_STATUS: + switch (data) { + case 1: + speak_status = "All Clear"; + break; + case 2: + speak_status = "Open Circuit"; + break; + case 4: + speak_status = "Short Circuit"; + break; + } + + dev_info(cs35l45->dev, "MBOX event (SPEAKER_STATUS): %s\n", + speak_status); + break; + case EVENT_BOOT_DONE: + dev_dbg(cs35l45->dev, "MBOX event (BOOT_DONE)\n"); + break; + default: + dev_err(cs35l45->dev, "MBOX event not supported %u\n", cmd); + return -EINVAL; + } + + return 0; +} + +static irqreturn_t cs35l45_dsp_virt2_mbox_cb(int irq, void *data) +{ + struct cs35l45_private *cs35l45 = data; + unsigned int mbox_val; + int ret = 0; + + ret = regmap_read(cs35l45->regmap, CS35L45_DSP_VIRT2_MBOX_3, &mbox_val); + if (!ret && mbox_val) + ret = cs35l45_dsp_virt2_mbox3_irq_handle(cs35l45, mbox_val & CS35L45_MBOX3_CMD_MASK, + (mbox_val & CS35L45_MBOX3_DATA_MASK) >> CS35L45_MBOX3_DATA_SHIFT); + + /* Handle DSP trace log IRQ */ + ret = regmap_read(cs35l45->regmap, CS35L45_DSP_VIRT2_MBOX_4, &mbox_val); + if (!ret && mbox_val != 0) { + dev_err(cs35l45->dev, "Spurious DSP MBOX4 IRQ\n"); + } + + return IRQ_RETVAL(ret); +} + static irqreturn_t cs35l45_pll_unlock(int irq, void *data) { struct cs35l45_private *cs35l45 = data; @@ -639,6 +933,7 @@ static const struct cs35l45_irq cs35l45_irqs[] = { CS35L45_IRQ(DSP_WDT_EXPIRE, "DSP Watchdog Timer", cs35l45_spk_safe_err), CS35L45_IRQ(PLL_UNLOCK_FLAG_RISE, "PLL unlock", cs35l45_pll_unlock), CS35L45_IRQ(PLL_LOCK_FLAG, "PLL lock", cs35l45_pll_lock), + CS35L45_IRQ(DSP_VIRT2_MBOX, "DSP virtual MBOX 2 write flag", cs35l45_dsp_virt2_mbox_cb), }; static irqreturn_t cs35l45_spk_safe_err(int irq, void *data) @@ -665,6 +960,7 @@ static const struct regmap_irq cs35l45_reg_irqs[] = { CS35L45_REG_IRQ(IRQ1_EINT_2, DSP_WDT_EXPIRE), CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_UNLOCK_FLAG_RISE), CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_LOCK_FLAG), + CS35L45_REG_IRQ(IRQ1_EINT_2, DSP_VIRT2_MBOX), }; static const struct regmap_irq_chip cs35l45_regmap_irq_chip = { @@ -724,14 +1020,63 @@ static int cs35l45_initialize(struct cs35l45_private *cs35l45) if (ret < 0) return ret; - pm_runtime_set_autosuspend_delay(cs35l45->dev, 3000); - pm_runtime_use_autosuspend(cs35l45->dev); - pm_runtime_set_active(cs35l45->dev); - pm_runtime_enable(cs35l45->dev); - return 0; } +static const struct reg_sequence cs35l45_fs_errata_patch[] = { + {0x02B80080, 0x00000001}, + {0x02B80088, 0x00000001}, + {0x02B80090, 0x00000001}, + {0x02B80098, 0x00000001}, + {0x02B800A0, 0x00000001}, + {0x02B800A8, 0x00000001}, + {0x02B800B0, 0x00000001}, + {0x02B800B8, 0x00000001}, + {0x02B80280, 0x00000001}, + {0x02B80288, 0x00000001}, + {0x02B80290, 0x00000001}, + {0x02B80298, 0x00000001}, + {0x02B802A0, 0x00000001}, + {0x02B802A8, 0x00000001}, + {0x02B802B0, 0x00000001}, + {0x02B802B8, 0x00000001}, +}; + +static const struct cs_dsp_region cs35l45_dsp1_regions[] = { + { .type = WMFW_HALO_PM_PACKED, .base = CS35L45_DSP1_PMEM_0 }, + { .type = WMFW_HALO_XM_PACKED, .base = CS35L45_DSP1_XMEM_PACK_0 }, + { .type = WMFW_HALO_YM_PACKED, .base = CS35L45_DSP1_YMEM_PACK_0 }, + {. type = WMFW_ADSP2_XM, .base = CS35L45_DSP1_XMEM_UNPACK24_0}, + {. type = WMFW_ADSP2_YM, .base = CS35L45_DSP1_YMEM_UNPACK24_0}, +}; + +static int cs35l45_dsp_init(struct cs35l45_private *cs35l45) +{ + struct wm_adsp *dsp = &cs35l45->dsp; + int ret; + + dsp->part = "cs35l45"; + dsp->fw = 9; /* 9 is WM_ADSP_FW_SPK_PROT in wm_adsp.c */ + dsp->toggle_preload = true; + dsp->cs_dsp.num = 1; + dsp->cs_dsp.type = WMFW_HALO; + dsp->cs_dsp.rev = 0; + dsp->cs_dsp.dev = cs35l45->dev; + dsp->cs_dsp.regmap = cs35l45->regmap; + dsp->cs_dsp.base = CS35L45_DSP1_CLOCK_FREQ; + dsp->cs_dsp.base_sysinfo = CS35L45_DSP1_SYS_ID; + dsp->cs_dsp.mem = cs35l45_dsp1_regions; + dsp->cs_dsp.num_mems = ARRAY_SIZE(cs35l45_dsp1_regions); + dsp->cs_dsp.lock_regions = 0xFFFFFFFF; + + ret = wm_halo_init(dsp); + + regmap_multi_reg_write(cs35l45->regmap, cs35l45_fs_errata_patch, + ARRAY_SIZE(cs35l45_fs_errata_patch)); + + return ret; +} + int cs35l45_probe(struct cs35l45_private *cs35l45) { struct device *dev = cs35l45->dev; @@ -781,6 +1126,17 @@ int cs35l45_probe(struct cs35l45_private *cs35l45) if (ret < 0) goto err_reset; + ret = cs35l45_dsp_init(cs35l45); + if (ret < 0) + goto err_reset; + + pm_runtime_set_autosuspend_delay(cs35l45->dev, 3000); + pm_runtime_use_autosuspend(cs35l45->dev); + pm_runtime_mark_last_busy(cs35l45->dev); + pm_runtime_set_active(cs35l45->dev); + pm_runtime_get_noresume(cs35l45->dev); + pm_runtime_enable(cs35l45->dev); + if (cs35l45->irq) { if (cs35l45->irq_invert) irq_pol |= IRQF_TRIGGER_HIGH; @@ -791,7 +1147,7 @@ int cs35l45_probe(struct cs35l45_private *cs35l45) &cs35l45_regmap_irq_chip, &cs35l45->irq_data); if (ret) { dev_err(dev, "Failed to register IRQ chip: %d\n", ret); - goto err_reset; + goto err_dsp; } for (i = 0; i < ARRAY_SIZE(cs35l45_irqs); i++) { @@ -799,7 +1155,7 @@ int cs35l45_probe(struct cs35l45_private *cs35l45) if (irq < 0) { dev_err(dev, "Failed to get %s\n", cs35l45_irqs[i].name); ret = irq; - goto err_reset; + goto err_dsp; } ret = devm_request_threaded_irq(dev, irq, NULL, cs35l45_irqs[i].handler, @@ -807,7 +1163,7 @@ int cs35l45_probe(struct cs35l45_private *cs35l45) if (ret) { dev_err(dev, "Failed to request IRQ %s: %d\n", cs35l45_irqs[i].name, ret); - goto err_reset; + goto err_dsp; } } } @@ -816,10 +1172,17 @@ int cs35l45_probe(struct cs35l45_private *cs35l45) cs35l45_dai, ARRAY_SIZE(cs35l45_dai)); if (ret < 0) - goto err_reset; + goto err_dsp; + + pm_runtime_put_autosuspend(cs35l45->dev); return 0; +err_dsp: + pm_runtime_disable(cs35l45->dev); + pm_runtime_put_noidle(cs35l45->dev); + wm_adsp2_remove(&cs35l45->dsp); + err_reset: gpiod_set_value_cansleep(cs35l45->reset_gpio, 0); err: @@ -832,9 +1195,13 @@ EXPORT_SYMBOL_NS_GPL(cs35l45_probe, SND_SOC_CS35L45); void cs35l45_remove(struct cs35l45_private *cs35l45) { + pm_runtime_get_sync(cs35l45->dev); pm_runtime_disable(cs35l45->dev); + wm_adsp2_remove(&cs35l45->dsp); gpiod_set_value_cansleep(cs35l45->reset_gpio, 0); + + pm_runtime_put_noidle(cs35l45->dev); regulator_disable(cs35l45->vdd_a); /* VDD_BATT must be the last to power-off */ regulator_disable(cs35l45->vdd_batt); diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h index ce92f5068ac5..87032619b341 100644 --- a/sound/soc/codecs/cs35l45.h +++ b/sound/soc/codecs/cs35l45.h @@ -15,6 +15,7 @@ #include #include #include +#include "wm_adsp.h" #define CS35L45_DEVID 0x00000000 #define CS35L45_REVID 0x00000004 @@ -28,6 +29,7 @@ #define CS35L45_SYNC_GPIO1 0x00002430 #define CS35L45_INTB_GPIO2_MCLK_REF 0x00002434 #define CS35L45_GPIO3 0x00002438 +#define CS35L45_PWRMGT_CTL 0x00002900 #define CS35L45_REFCLK_INPUT 0x00002C04 #define CS35L45_GLOBAL_SAMPLE_RATE 0x00002C0C #define CS35L45_BOOST_CCM_CFG 0x00003808 @@ -48,6 +50,14 @@ #define CS35L45_ASPTX3_INPUT 0x00004C28 #define CS35L45_ASPTX4_INPUT 0x00004C2C #define CS35L45_ASPTX5_INPUT 0x00004C30 +#define CS35L45_DSP1RX1_INPUT 0x00004C40 +#define CS35L45_DSP1RX2_INPUT 0x00004C44 +#define CS35L45_DSP1RX3_INPUT 0x00004C48 +#define CS35L45_DSP1RX4_INPUT 0x00004C4C +#define CS35L45_DSP1RX5_INPUT 0x00004C50 +#define CS35L45_DSP1RX6_INPUT 0x00004C54 +#define CS35L45_DSP1RX7_INPUT 0x00004C58 +#define CS35L45_DSP1RX8_INPUT 0x00004C5C #define CS35L45_LDPM_CONFIG 0x00006404 #define CS35L45_AMP_PCM_CONTROL 0x00007000 #define CS35L45_AMP_PCM_HPF_TST 0x00007004 @@ -91,7 +101,55 @@ #define CS35L45_GPIO1_CTRL1 0x0000F008 #define CS35L45_GPIO2_CTRL1 0x0000F00C #define CS35L45_GPIO3_CTRL1 0x0000F010 -#define CS35L45_LASTREG 0x0000F010 +#define CS35L45_DSP_MBOX_1 0x00011000 +#define CS35L45_DSP_MBOX_2 0x00011004 +#define CS35L45_DSP_VIRT1_MBOX_1 0x00011020 +#define CS35L45_DSP_VIRT1_MBOX_2 0x00011024 +#define CS35L45_DSP_VIRT1_MBOX_3 0x00011028 +#define CS35L45_DSP_VIRT1_MBOX_4 0x0001102C +#define CS35L45_DSP_VIRT2_MBOX_1 0x00011040 +#define CS35L45_DSP_VIRT2_MBOX_2 0x00011044 +#define CS35L45_DSP_VIRT2_MBOX_3 0x00011048 +#define CS35L45_DSP_VIRT2_MBOX_4 0x0001104C +#define CS35L45_DSP1_XMEM_PACK_0 0x02000000 +#define CS35L45_DSP1_XMEM_PACK_4607 0x020047FC +#define CS35L45_DSP1_XMEM_UNPACK32_0 0x02400000 +#define CS35L45_DSP1_XMEM_UNPACK32_3071 0x02402FFC +#define CS35L45_DSP1_SYS_ID 0x025E0000 +#define CS35L45_DSP1_XMEM_UNPACK24_0 0x02800000 +#define CS35L45_DSP1_XMEM_UNPACK24_6143 0x02805FFC +#define CS35L45_DSP1_CLOCK_FREQ 0x02B80000 +#define CS35L45_DSP1_RX1_RATE 0x02B80080 +#define CS35L45_DSP1_RX2_RATE 0x02B80088 +#define CS35L45_DSP1_RX3_RATE 0x02B80090 +#define CS35L45_DSP1_RX4_RATE 0x02B80098 +#define CS35L45_DSP1_RX5_RATE 0x02B800A0 +#define CS35L45_DSP1_RX6_RATE 0x02B800A8 +#define CS35L45_DSP1_RX7_RATE 0x02B800B0 +#define CS35L45_DSP1_RX8_RATE 0x02B800B8 +#define CS35L45_DSP1_TX1_RATE 0x02B80280 +#define CS35L45_DSP1_TX2_RATE 0x02B80288 +#define CS35L45_DSP1_TX3_RATE 0x02B80290 +#define CS35L45_DSP1_TX4_RATE 0x02B80298 +#define CS35L45_DSP1_TX5_RATE 0x02B802A0 +#define CS35L45_DSP1_TX6_RATE 0x02B802A8 +#define CS35L45_DSP1_TX7_RATE 0x02B802B0 +#define CS35L45_DSP1_TX8_RATE 0x02B802B8 +#define CS35L45_DSP1_SCRATCH1 0x02B805C0 +#define CS35L45_DSP1_SCRATCH2 0x02B805C8 +#define CS35L45_DSP1_SCRATCH3 0x02B805D0 +#define CS35L45_DSP1_SCRATCH4 0x02B805D8 +#define CS35L45_DSP1_CCM_CORE_CONTROL 0x02BC1000 +#define CS35L45_DSP1_YMEM_PACK_0 0x02C00000 +#define CS35L45_DSP1_YMEM_PACK_1532 0x02C017F0 +#define CS35L45_DSP1_YMEM_UNPACK32_0 0x03000000 +#define CS35L45_DSP1_YMEM_UNPACK32_1022 0x03000FF8 +#define CS35L45_DSP1_YMEM_UNPACK24_0 0x03400000 +#define CS35L45_DSP1_YMEM_UNPACK24_2043 0x03401FEC +#define CS35L45_DSP1_PMEM_0 0x03800000 +#define CS35L45_DSP1_PMEM_3834 0x03803BE8 +#define CS35L45_LASTREG 0x03C6EFE8 + /* SFT_RESET */ #define CS35L45_SOFT_RESET_TRIGGER 0x5A000000 @@ -112,9 +170,20 @@ /* BLOCK_ENABLES2 */ #define CS35L45_ASP_EN_SHIFT 27 +#define CS35L45_MEM_RDY_SHIFT 1 +#define CS35L45_MEM_RDY_MASK BIT(1) + /* ERROR_RELEASE */ #define CS35L45_GLOBAL_ERR_RLS_MASK BIT(11) +/* CCM_CORE */ +#define CS35L45_CCM_CORE_RESET_SHIFT 9 +#define CS35L45_CCM_CORE_RESET_MASK BIT(9) +#define CS35L45_CCM_PM_REMAP_SHIFT 7 +#define CS35L45_CCM_PM_REMAP_MASK BIT(7) +#define CS35L45_CCM_CORE_EN_SHIFT 0 +#define CS35L45_CCM_CORE_EN_MASK BIT(0) + /* REFCLK_INPUT */ #define CS35L45_PLL_FORCE_EN_SHIFT 16 #define CS35L45_PLL_FORCE_EN_MASK BIT(16) @@ -240,6 +309,8 @@ /* CS35L45_IRQ1_EINT_2 */ #define CS35L45_DSP_WDT_EXPIRE_SHIFT 4 #define CS35L45_DSP_WDT_EXPIRE_MASK BIT(4) +#define CS35L45_DSP_VIRT2_MBOX_SHIFT 21 +#define CS35L45_DSP_VIRT2_MBOX_MASK BIT(21) /* CS35L45_IRQ1_EINT_3 */ #define CS35L45_PLL_LOCK_FLAG_SHIFT 1 @@ -266,6 +337,8 @@ #define CS35L45_PCM_SRC_CLASSH_TGT 0x21 #define CS35L45_PCM_SRC_VDD_BATTMON 0x28 #define CS35L45_PCM_SRC_VDD_BSTMON 0x29 +#define CS35L45_PCM_SRC_DSP_TX1 0x32 +#define CS35L45_PCM_SRC_DSP_TX2 0x33 #define CS35L45_PCM_SRC_TEMPMON 0x3A #define CS35L45_PCM_SRC_INTERPOLATOR 0x40 #define CS35L45_PCM_SRC_IL_TARGET 0x48 @@ -275,6 +348,27 @@ #define CS35L45_POST_GLOBAL_EN_US 5000 #define CS35L45_PRE_GLOBAL_DIS_US 3000 +#define CS35L45_SPI_MAX_FREQ 4000000 + +enum cs35l45_cspl_mboxstate { + CSPL_MBOX_STS_RUNNING = 0, + CSPL_MBOX_STS_PAUSED = 1, + CSPL_MBOX_STS_RDY_FOR_REINIT = 2, + CSPL_MBOX_STS_HIBERNATE = 3, +}; + +enum cs35l45_cspl_mboxcmd { + CSPL_MBOX_CMD_NONE = 0, + CSPL_MBOX_CMD_PAUSE = 1, + CSPL_MBOX_CMD_RESUME = 2, + CSPL_MBOX_CMD_REINIT = 3, + CSPL_MBOX_CMD_STOP_PRE_REINIT = 4, + CSPL_MBOX_CMD_HIBERNATE = 5, + CSPL_MBOX_CMD_OUT_OF_HIBERNATE = 6, + CSPL_MBOX_CMD_UNKNOWN_CMD = -1, + CSPL_MBOX_CMD_INVALID_SEQUENCE = -2, +}; + #define CS35L45_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S24_3LE| \ SNDRV_PCM_FMTBIT_S24_LE) @@ -318,10 +412,22 @@ enum cs35l45_irq_list { CS35L45_DSP_WDT_EXPIRE_IRQ, CS35L45_PLL_UNLOCK_FLAG_RISE_IRQ, CS35L45_PLL_LOCK_FLAG_IRQ, + CS35L45_DSP_VIRT2_MBOX_IRQ, CS35L45_NUM_IRQ }; +#define CS35L45_MBOX3_CMD_MASK 0xFF +#define CS35L45_MBOX3_CMD_SHIFT 0 +#define CS35L45_MBOX3_DATA_MASK 0xFFFFFF00 +#define CS35L45_MBOX3_DATA_SHIFT 8 + +enum mbox3_events { + EVENT_SPEAKER_STATUS = 0x66, + EVENT_BOOT_DONE = 0x67, +}; + struct cs35l45_private { + struct wm_adsp dsp; /* needs to be first member */ struct device *dev; struct regmap *regmap; struct gpio_desc *reset_gpio; -- cgit From 6c07be8fe92c6b0c24ee1c599601dce3506b83c7 Mon Sep 17 00:00:00 2001 From: "Vlad.Karpovich" Date: Wed, 15 Mar 2023 10:47:22 -0500 Subject: ASoC: cs35l45: Hibernation support Adds support for a low-power Hibernation State. Add support for a low-power hibernation state for the DSP. In this state the DSP RAM contents are maintained, such that firmware does not need to be re-downloaded, but the rest of the chip's register state is lost. Entry to this state is achieved via the register interface (either by an external driver using the control port, or the programmable DSP). Exit from this state is triggered by activity on device GPIO pins, intended SPI transaction, or I2C transaction with intended slave address. Signed-off-by: Vlad Karpovich Link: https://lore.kernel.org/r/167933511185.26.10641185496218226278@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l45-i2c.c | 2 + sound/soc/codecs/cs35l45-spi.c | 1 + sound/soc/codecs/cs35l45-tables.c | 6 +++ sound/soc/codecs/cs35l45.c | 80 +++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/cs35l45.h | 29 ++++++++++++++ 5 files changed, 118 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l45-i2c.c b/sound/soc/codecs/cs35l45-i2c.c index 33fa6d59e9a4..562f73df7afa 100644 --- a/sound/soc/codecs/cs35l45-i2c.c +++ b/sound/soc/codecs/cs35l45-i2c.c @@ -33,6 +33,8 @@ static int cs35l45_i2c_probe(struct i2c_client *client) cs35l45->dev = dev; cs35l45->irq = client->irq; + cs35l45->bus_type = CONTROL_BUS_I2C; + cs35l45->i2c_addr = client->addr; return cs35l45_probe(cs35l45); } diff --git a/sound/soc/codecs/cs35l45-spi.c b/sound/soc/codecs/cs35l45-spi.c index 99657325a281..a00b23b4180c 100644 --- a/sound/soc/codecs/cs35l45-spi.c +++ b/sound/soc/codecs/cs35l45-spi.c @@ -36,6 +36,7 @@ static int cs35l45_spi_probe(struct spi_device *spi) cs35l45->dev = dev; cs35l45->irq = spi->irq; + cs35l45->bus_type = CONTROL_BUS_SPI; return cs35l45_probe(cs35l45); } diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c index 434a6473070e..46610e64e818 100644 --- a/sound/soc/codecs/cs35l45-tables.c +++ b/sound/soc/codecs/cs35l45-tables.c @@ -47,6 +47,8 @@ static const struct reg_default cs35l45_defaults[] = { { CS35L45_INTB_GPIO2_MCLK_REF, 0x00000005 }, { CS35L45_GPIO3, 0x00000005 }, { CS35L45_PWRMGT_CTL, 0x00000000 }, + { CS35L45_WAKESRC_CTL, 0x00000008 }, + { CS35L45_WKI2C_CTL, 0x00000030 }, { CS35L45_REFCLK_INPUT, 0x00000510 }, { CS35L45_GLOBAL_SAMPLE_RATE, 0x00000003 }, { CS35L45_ASP_ENABLES1, 0x00000000 }, @@ -126,6 +128,9 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg) case CS35L45_INTB_GPIO2_MCLK_REF: case CS35L45_GPIO3: case CS35L45_PWRMGT_CTL: + case CS35L45_WAKESRC_CTL: + case CS35L45_WKI2C_CTL: + case CS35L45_PWRMGT_STS: case CS35L45_REFCLK_INPUT: case CS35L45_GLOBAL_SAMPLE_RATE: case CS35L45_ASP_ENABLES1: @@ -210,6 +215,7 @@ static bool cs35l45_volatile_reg(struct device *dev, unsigned int reg) case CS35L45_GLOBAL_ENABLES: case CS35L45_ERROR_RELEASE: case CS35L45_AMP_PCM_HPF_TST: /* not cachable */ + case CS35L45_PWRMGT_STS: case CS35L45_IRQ1_STATUS: case CS35L45_IRQ1_EINT_1 ... CS35L45_IRQ1_EINT_18: case CS35L45_IRQ1_STS_1 ... CS35L45_IRQ1_STS_18: diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c index 97f6819fa2ad..c31597f6bfae 100644 --- a/sound/soc/codecs/cs35l45.c +++ b/sound/soc/codecs/cs35l45.c @@ -36,6 +36,8 @@ static bool cs35l45_check_cspl_mbox_sts(const enum cs35l45_cspl_mboxcmd cmd, return (sts == CSPL_MBOX_STS_RUNNING); case CSPL_MBOX_CMD_STOP_PRE_REINIT: return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT); + case CSPL_MBOX_CMD_HIBERNATE: + return (sts == CSPL_MBOX_STS_HIBERNATE); default: return false; } @@ -744,11 +746,81 @@ static const struct snd_soc_component_driver cs35l45_component = { .endianness = 1, }; +static void cs35l45_setup_hibernate(struct cs35l45_private *cs35l45) +{ + unsigned int wksrc; + + if (cs35l45->bus_type == CONTROL_BUS_I2C) + wksrc = CS35L45_WKSRC_I2C; + else + wksrc = CS35L45_WKSRC_SPI; + + regmap_update_bits(cs35l45->regmap, CS35L45_WAKESRC_CTL, + CS35L45_WKSRC_EN_MASK, + wksrc << CS35L45_WKSRC_EN_SHIFT); + + regmap_set_bits(cs35l45->regmap, CS35L45_WAKESRC_CTL, + CS35L45_UPDT_WKCTL_MASK); + + regmap_update_bits(cs35l45->regmap, CS35L45_WKI2C_CTL, + CS35L45_WKI2C_ADDR_MASK, cs35l45->i2c_addr); + + regmap_set_bits(cs35l45->regmap, CS35L45_WKI2C_CTL, + CS35L45_UPDT_WKI2C_MASK); +} + +static int cs35l45_enter_hibernate(struct cs35l45_private *cs35l45) +{ + dev_dbg(cs35l45->dev, "Enter hibernate\n"); + + cs35l45_setup_hibernate(cs35l45); + + // Don't wait for ACK since bus activity would wake the device + regmap_write(cs35l45->regmap, CS35L45_DSP_VIRT1_MBOX_1, CSPL_MBOX_CMD_HIBERNATE); + + return 0; +} + +static int cs35l45_exit_hibernate(struct cs35l45_private *cs35l45) +{ + const int wake_retries = 20; + const int sleep_retries = 5; + int ret, i, j; + + for (i = 0; i < sleep_retries; i++) { + dev_dbg(cs35l45->dev, "Exit hibernate\n"); + + for (j = 0; j < wake_retries; j++) { + ret = cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap, + CSPL_MBOX_CMD_OUT_OF_HIBERNATE); + if (!ret) { + dev_dbg(cs35l45->dev, "Wake success at cycle: %d\n", j); + return 0; + } + usleep_range(100, 200); + } + + dev_err(cs35l45->dev, "Wake failed, re-enter hibernate: %d\n", ret); + + cs35l45_setup_hibernate(cs35l45); + } + + dev_err(cs35l45->dev, "Timed out waking device\n"); + + return -ETIMEDOUT; +} + static int __maybe_unused cs35l45_runtime_suspend(struct device *dev) { struct cs35l45_private *cs35l45 = dev_get_drvdata(dev); + if (!cs35l45->dsp.preloaded || !cs35l45->dsp.cs_dsp.running) + return 0; + + cs35l45_enter_hibernate(cs35l45); + regcache_cache_only(cs35l45->regmap, true); + regcache_mark_dirty(cs35l45->regmap); dev_dbg(cs35l45->dev, "Runtime suspended\n"); @@ -760,9 +832,17 @@ static int __maybe_unused cs35l45_runtime_resume(struct device *dev) struct cs35l45_private *cs35l45 = dev_get_drvdata(dev); int ret; + if (!cs35l45->dsp.preloaded || !cs35l45->dsp.cs_dsp.running) + return 0; + dev_dbg(cs35l45->dev, "Runtime resume\n"); regcache_cache_only(cs35l45->regmap, false); + + ret = cs35l45_exit_hibernate(cs35l45); + if (ret) + return ret; + ret = regcache_sync(cs35l45->regmap); if (ret != 0) dev_warn(cs35l45->dev, "regcache_sync failed: %d\n", ret); diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h index 87032619b341..0da28439f628 100644 --- a/sound/soc/codecs/cs35l45.h +++ b/sound/soc/codecs/cs35l45.h @@ -30,6 +30,9 @@ #define CS35L45_INTB_GPIO2_MCLK_REF 0x00002434 #define CS35L45_GPIO3 0x00002438 #define CS35L45_PWRMGT_CTL 0x00002900 +#define CS35L45_WAKESRC_CTL 0x00002904 +#define CS35L45_WKI2C_CTL 0x00002908 +#define CS35L45_PWRMGT_STS 0x0000290C #define CS35L45_REFCLK_INPUT 0x00002C04 #define CS35L45_GLOBAL_SAMPLE_RATE 0x00002C0C #define CS35L45_BOOST_CCM_CFG 0x00003808 @@ -348,6 +351,25 @@ #define CS35L45_POST_GLOBAL_EN_US 5000 #define CS35L45_PRE_GLOBAL_DIS_US 3000 +/* WAKESRC_CTL */ +#define CS35L45_WKSRC_SYNC_GPIO1 BIT(0) +#define CS35L45_WKSRC_INT_GPIO2 BIT(1) +#define CS35L45_WKSRC_GPIO3 BIT(2) +#define CS35L45_WKSRC_SPI BIT(3) +#define CS35L45_WKSRC_I2C BIT(4) +#define CS35L45_UPDT_WKCTL_SHIFT 15 +#define CS35L45_UPDT_WKCTL_MASK BIT(15) +#define CS35L45_WKSRC_EN_SHIFT 8 +#define CS35L45_WKSRC_EN_MASK GENMASK(12, 8) +#define CS35L45_WKSRC_POL_SHIFT 0 +#define CS35L45_WKSRC_POL_MASK GENMASK(3, 0) + +/* WAKEI2C_CTL */ +#define CS35L45_UPDT_WKI2C_SHIFT 15 +#define CS35L45_UPDT_WKI2C_MASK BIT(15) +#define CS35L45_WKI2C_ADDR_SHIFT 0 +#define CS35L45_WKI2C_ADDR_MASK GENMASK(6, 0) + #define CS35L45_SPI_MAX_FREQ 4000000 enum cs35l45_cspl_mboxstate { @@ -369,6 +391,11 @@ enum cs35l45_cspl_mboxcmd { CSPL_MBOX_CMD_INVALID_SEQUENCE = -2, }; +enum control_bus_type { + CONTROL_BUS_I2C = 0, + CONTROL_BUS_SPI = 1, +}; + #define CS35L45_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S24_3LE| \ SNDRV_PCM_FMTBIT_S24_LE) @@ -439,6 +466,8 @@ struct cs35l45_private { u8 slot_count; int irq_invert; int irq; + unsigned int i2c_addr; + enum control_bus_type bus_type; struct regmap_irq_chip_data *irq_data; }; -- cgit From 1c12e032cc43256d75fdd22e60a7df85e8df4549 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 21 Mar 2023 16:56:51 +0200 Subject: ASoC: SOF: ipc4-control: Return on error in sof_ipc4_widget_kcontrol_setup() The patch adding the bytes control support moved the error check outside of the list_for_each_entry() which was not correct as at the end of the list_for_each_entry() the scontrol will no longer point where the error happened, but it to the list head. Restore the original logic and return on the first error with the error code. Fixes: a062c8899fed ("ASoC: SOF: ipc4-control: Add support for bytes control get and put") Reported-by: Dan Carpenter Link: https://lore.kernel.org/alsa-devel/6be945d2-40cb-46fb-67ba-ed3a19cddfa4@linux.intel.com/T/#t Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230321145651.9118-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-control.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-control.c b/sound/soc/sof/ipc4-control.c index d26ed2a6029f..6f0698be9451 100644 --- a/sound/soc/sof/ipc4-control.c +++ b/sound/soc/sof/ipc4-control.c @@ -429,14 +429,17 @@ static int sof_ipc4_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_s default: break; } + + if (ret < 0) { + dev_err(sdev->dev, + "kcontrol %d set up failed for widget %s\n", + scontrol->comp_id, swidget->widget->name); + return ret; + } } } - if (ret < 0) - dev_err(sdev->dev, "kcontrol %d set up failed for widget %s\n", - scontrol->comp_id, swidget->widget->name); - - return ret; + return 0; } static int -- cgit From e51f49512d98783b90799c9cc2002895ec3aa0eb Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 22 Mar 2023 10:55:38 +0200 Subject: ASoC: SOF: ipc4: Ensure DSP is in D0I0 during sof_ipc4_set_get_data() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The set_get_data() IPC op bypasses the check for the no_pm flag as done with the regular IPC tx_msg op. Since set_get_data should be performed when the DSP is in D0I0, set the DSP power state to D0I0 before sending the IPC's in sof_ipc4_set_get_data(). Fixes: ceb89acc4dc8 ("ASoC: SOF: ipc4: Add support for mandatory message handling functionality") Signed-off-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230322085538.10214-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c index 8ede4b952997..246b56d24a6f 100644 --- a/sound/soc/sof/ipc4.c +++ b/sound/soc/sof/ipc4.c @@ -405,6 +405,9 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data, size_t payload_bytes, bool set) { + const struct sof_dsp_power_state target_state = { + .state = SOF_DSP_PM_D0, + }; size_t payload_limit = sdev->ipc->max_payload_size; struct sof_ipc4_msg *ipc4_msg = data; struct sof_ipc4_msg tx = {{ 0 }}; @@ -435,6 +438,11 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data, tx.extension |= SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK(1); + /* ensure the DSP is in D0i0 before sending IPC */ + ret = snd_sof_dsp_set_power_state(sdev, &target_state); + if (ret < 0) + return ret; + /* Serialise IPC TX */ mutex_lock(&sdev->ipc->tx_mutex); -- cgit From 1bf83fa6654ce8959948878aad14a6db586125b8 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 22 Mar 2023 11:43:44 +0200 Subject: ASoC: SOF: Intel: hda-dai: Do not perform DMA cleanup during stop In the case of repeated start/stop without involving hw_free, the stream tag needs to be preserved for the subsequent starts. So, skip performing the DMA clean up during stop and handle it only during suspend or hw_free. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230322094346.6019-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 9637f0f44b01..46a17afdd1ea 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -305,7 +305,6 @@ static int hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct switch (cmd) { case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: ret = hda_link_dma_cleanup(substream, hext_stream, dai, codec_dai); if (ret < 0) { dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); -- cgit From 7d6f623c6a9d05195d1b19120383d4f42a1747db Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 22 Mar 2023 11:43:45 +0200 Subject: ASoC: SOF: pcm: Make hw_params reset conditional for IPC3 In the case of IPC4, since there is no PCM_PARAMS IPC to send the new stream tag when restarting a stream without a hw_free, the original stream tag needs to be preserved. So, add new a flag as part of struct sof_ipc_pcm_ops, reset_hw_params_during_stop and set it only for IPC3. This will ensure that the host DMA stream tag will not be given up during the STOP trigger for IPC4. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230322094346.6019-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc3-pcm.c | 1 + sound/soc/sof/pcm.c | 3 ++- sound/soc/sof/sof-audio.h | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c index b29d93e0d216..b7f1eb21ca26 100644 --- a/sound/soc/sof/ipc3-pcm.c +++ b/sound/soc/sof/ipc3-pcm.c @@ -382,4 +382,5 @@ const struct sof_ipc_pcm_ops ipc3_pcm_ops = { .hw_free = sof_ipc3_pcm_hw_free, .trigger = sof_ipc3_pcm_trigger, .dai_link_fixup = sof_ipc3_pcm_dai_link_fixup, + .reset_hw_params_during_stop = true, }; diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 445acb5c3a21..f75b161125fa 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -328,7 +328,8 @@ static int sof_pcm_trigger(struct snd_soc_component *component, fallthrough; case SNDRV_PCM_TRIGGER_STOP: ipc_first = true; - reset_hw_params = true; + if (pcm_ops && pcm_ops->reset_hw_params_during_stop) + reset_hw_params = true; break; default: dev_err(component->dev, "Unhandled trigger cmd %d\n", cmd); diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index d220af5f08fb..81685e778ad6 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -104,6 +104,8 @@ struct snd_sof_dai_config_data { * @pcm_free: Function pointer for PCM free that can be used for freeing any * additional memory in the SOF PCM stream structure * @delay: Function pointer for pcm delay calculation + * @reset_hw_params_during_stop: Flag indicating whether the hw_params should be reset during the + * STOP pcm trigger */ struct sof_ipc_pcm_ops { int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream, @@ -117,6 +119,7 @@ struct sof_ipc_pcm_ops { void (*pcm_free)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm); snd_pcm_sframes_t (*delay)(struct snd_soc_component *component, struct snd_pcm_substream *substream); + bool reset_hw_params_during_stop; }; /** -- cgit From 51ce3e6effab4fd4e13a3f187f4e256259f6e5a4 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 22 Mar 2023 11:43:46 +0200 Subject: ASoC: SOF: pcm: Improve the pcm trigger sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The recommended sequence for triggering the host DMA is to first program the DMA in the FW before setting the RUN bit to start the stream in the host. With IPC3, this sequence is honored because the FW programs the DMA when the HW_PARAMS IPC is sent during PCM hw_params and then the host sets the RUN bit during sof_pcm_trigger(). But with IPC4, sof_pcm_trigger() sends the SET_PIPELINE_STATE IPC to program the DMA in the FW after the DMA RUN bit is set. In order to minimize the impact for IPC3, introduce a new flag as part of struct sof_ipc_pcm_ops, ipc_first_on_start, which will be set for IPC4 only. With this flag set, the SET_PIPELINE_STATE IPC will be sent before the DMA RUN bit is set by the host during the START/PAUSE_RELEASE triggers. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230322094346.6019-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-pcm.c | 3 ++- sound/soc/sof/pcm.c | 26 ++++++++++++++++++++------ sound/soc/sof/sof-audio.h | 3 +++ 3 files changed, 25 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index db64200ba1e5..a2cd21256e44 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -835,5 +835,6 @@ const struct sof_ipc_pcm_ops ipc4_pcm_ops = { .dai_link_fixup = sof_ipc4_pcm_dai_link_fixup, .pcm_setup = sof_ipc4_pcm_setup, .pcm_free = sof_ipc4_pcm_free, - .delay = sof_ipc4_pcm_delay + .delay = sof_ipc4_pcm_delay, + .ipc_first_on_start = true }; diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index f75b161125fa..d9b4633bba7a 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -301,6 +301,8 @@ static int sof_pcm_trigger(struct snd_soc_component *component, ipc_first = true; break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (pcm_ops && pcm_ops->ipc_first_on_start) + ipc_first = true; break; case SNDRV_PCM_TRIGGER_START: if (spcm->stream[substream->stream].suspend_ignored) { @@ -312,6 +314,9 @@ static int sof_pcm_trigger(struct snd_soc_component *component, spcm->stream[substream->stream].suspend_ignored = false; return 0; } + + if (pcm_ops && pcm_ops->ipc_first_on_start) + ipc_first = true; break; case SNDRV_PCM_TRIGGER_SUSPEND: if (sdev->system_suspend_target == SOF_SUSPEND_S0IX && @@ -336,19 +341,28 @@ static int sof_pcm_trigger(struct snd_soc_component *component, return -EINVAL; } - /* - * DMA and IPC sequence is different for start and stop. Need to send - * STOP IPC before stop DMA - */ if (!ipc_first) snd_sof_pcm_platform_trigger(sdev, substream, cmd); if (pcm_ops && pcm_ops->trigger) ret = pcm_ops->trigger(component, substream, cmd); - /* need to STOP DMA even if trigger IPC failed */ - if (ipc_first) + switch (cmd) { + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_START: + /* invoke platform trigger to start DMA only if pcm_ops is successful */ + if (ipc_first && !ret) + snd_sof_pcm_platform_trigger(sdev, substream, cmd); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: + /* invoke platform trigger to stop DMA even if pcm_ops failed */ snd_sof_pcm_platform_trigger(sdev, substream, cmd); + break; + default: + break; + } /* free PCM if reset_hw_params is set and the STOP IPC is successful */ if (!ret && reset_hw_params) diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 81685e778ad6..6c64376858b3 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -106,6 +106,8 @@ struct snd_sof_dai_config_data { * @delay: Function pointer for pcm delay calculation * @reset_hw_params_during_stop: Flag indicating whether the hw_params should be reset during the * STOP pcm trigger + * @ipc_first_on_start: Send IPC before invoking platform trigger during + * START/PAUSE_RELEASE triggers */ struct sof_ipc_pcm_ops { int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream, @@ -120,6 +122,7 @@ struct sof_ipc_pcm_ops { snd_pcm_sframes_t (*delay)(struct snd_soc_component *component, struct snd_pcm_substream *substream); bool reset_hw_params_during_stop; + bool ipc_first_on_start; }; /** -- cgit From 54e288766906569a9e5ca2ff3a09fb4e4cc25a37 Mon Sep 17 00:00:00 2001 From: Uday M Bhat Date: Wed, 22 Mar 2023 09:49:15 +0200 Subject: ASoC: Intel: sof_rt5682: Update BT offload config for Rex For Rex, SSP1 is used for BT offload. This is enabled in the sof_rt5682_quirk_table Signed-off-by: Uday M Bhat Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230322074916.23225-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 2eec32846078..01a2a4db498c 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -234,7 +234,9 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { SOF_SPEAKER_AMP_PRESENT | SOF_MAX98360A_SPEAKER_AMP_PRESENT | SOF_RT5682_SSP_AMP(0) | - SOF_RT5682_NUM_HDMIDEV(4) + SOF_RT5682_NUM_HDMIDEV(4) | + SOF_BT_OFFLOAD_SSP(1) | + SOF_SSP_BT_OFFLOAD_PRESENT ), }, { @@ -246,7 +248,9 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { SOF_RT5682_SSP_CODEC(2) | SOF_SPEAKER_AMP_PRESENT | SOF_RT5682_SSP_AMP(0) | - SOF_RT5682_NUM_HDMIDEV(4) + SOF_RT5682_NUM_HDMIDEV(4) | + SOF_BT_OFFLOAD_SSP(1) | + SOF_SSP_BT_OFFLOAD_PRESENT ), }, {} -- cgit From f19f24d47900656962cafa51426660c8aa32744d Mon Sep 17 00:00:00 2001 From: Uday M Bhat Date: Wed, 22 Mar 2023 09:49:16 +0200 Subject: ASoC: Intel: sof_rt5682: Update BT offload config for MTL RVP For MTL RVP, SSP2 is used for BT offload. This is enabled in the sof_rt5682_quirk_table Signed-off-by: Uday M Bhat Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230322074916.23225-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 01a2a4db498c..c6c82e89b754 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -1123,7 +1123,9 @@ static const struct platform_device_id board_ids[] = { SOF_RT5682_SSP_CODEC(0) | SOF_SPEAKER_AMP_PRESENT | SOF_RT5682_SSP_AMP(1) | - SOF_RT5682_NUM_HDMIDEV(4)), + SOF_RT5682_NUM_HDMIDEV(4) | + SOF_BT_OFFLOAD_SSP(2) | + SOF_SSP_BT_OFFLOAD_PRESENT), }, { .name = "mtl_mx98360_rt5682", -- cgit From 3e1a334ad5b6e1aee25fd7f09400000f9b7b1f82 Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Wed, 22 Mar 2023 09:50:12 +0200 Subject: ASoC: Intel: sof_rt5682: Remove conditional dpcm_capture setting The dpcm_capture is set unconditionally, we can drop the conditional setting of it. Signed-off-by: Yong Zhi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230322075012.23463-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 2eec32846078..76ee2e35e1ef 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -793,7 +793,6 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, } links[id].init = max_98390_spk_codec_init; links[id].ops = &max_98390_ops; - links[id].dpcm_capture = 1; } else { max_98357a_dai_link(&links[id]); -- cgit From dcf084247e376b35c139c922d30917f4ff716a4c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 22 Mar 2023 01:12:24 +0000 Subject: ASoC: simple-card: add comment to indicate don't remove platforms Basically CPU and Platform are different Component, but if CPU is using soc-generic-dmaengine-pcm, same dev will be shared between CPU and Platform, and Simple Card had been supporting it. When we focus to clean up Simple Card driver, we tend to remove platforms if no Platform was selected, but it is wrong because of above reasons. This patch adds comment why we shouldn't remove platforms. In case of CPU is not using soc-generic-dmaengine-pcm, CPU and Platform will be duplicated, but it will be ignored by snd_soc_rtd_add_component(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/875yattwqv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 13 ++++++++++++- sound/soc/generic/audio-graph-card2.c | 17 +++++++++++++++++ sound/soc/generic/simple-card-utils.c | 11 ++++++++++- sound/soc/generic/simple-card.c | 22 +++++++++++++++++++++- 4 files changed, 60 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index d788f5f23a8a..4e85536a1b26 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -613,10 +613,16 @@ static int graph_count_noml(struct asoc_simple_priv *priv, return -EINVAL; } + /* + * DON'T REMOVE platforms + * see + * simple-card.c :: simple_count_noml() + */ li->num[li->link].cpus = 1; - li->num[li->link].codecs = 1; li->num[li->link].platforms = 1; + li->num[li->link].codecs = 1; + li->link += 1; /* 1xCPU-Codec */ dev_dbg(dev, "Count As Normal\n"); @@ -637,6 +643,11 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, } if (li->cpu) { + /* + * DON'T REMOVE platforms + * see + * simple-card.c :: simple_count_noml() + */ li->num[li->link].cpus = 1; li->num[li->link].platforms = 1; diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 259544f64df9..d145b74d41e4 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -1046,8 +1046,14 @@ static int graph_count_normal(struct asoc_simple_priv *priv, * => lnk: port { endpoint { .. }; }; * }; */ + /* + * DON'T REMOVE platforms + * see + * simple-card.c :: simple_count_noml() + */ li->num[li->link].cpus = li->num[li->link].platforms = graph_counter(cpu_port); + li->num[li->link].codecs = graph_counter(codec_port); of_node_put(cpu_ep); @@ -1079,6 +1085,11 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, */ if (asoc_graph_is_ports0(lnk)) { + /* + * DON'T REMOVE platforms + * see + * simple-card.c :: simple_count_noml() + */ li->num[li->link].cpus = graph_counter(rport); /* FE */ li->num[li->link].platforms = graph_counter(rport); } else { @@ -1113,8 +1124,14 @@ static int graph_count_c2c(struct asoc_simple_priv *priv, * }; * }; */ + /* + * DON'T REMOVE platforms + * see + * simple-card.c :: simple_count_noml() + */ li->num[li->link].cpus = li->num[li->link].platforms = graph_counter(codec0); + li->num[li->link].codecs = graph_counter(codec1); of_node_put(ports); diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 56552a616f21..34a9b91e676f 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -638,7 +638,16 @@ EXPORT_SYMBOL_GPL(asoc_simple_dai_init); void asoc_simple_canonicalize_platform(struct snd_soc_dai_link_component *platforms, struct snd_soc_dai_link_component *cpus) { - /* Assumes platform == cpu */ + /* + * Assumes Platform == CPU + * + * Some CPU might be using soc-generic-dmaengine-pcm. This means CPU and Platform + * are different Component, but are sharing same component->dev. + * + * Let's assume Platform is same as CPU if it doesn't identify Platform on DT. + * see + * simple-card.c :: simple_count_noml() + */ if (!platforms->of_node) platforms->of_node = cpus->of_node; } diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index e98932c16754..fcd6c44f89f6 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -509,10 +509,25 @@ static int simple_count_noml(struct asoc_simple_priv *priv, return -EINVAL; } + /* + * DON'T REMOVE platforms + * + * Some CPU might be using soc-generic-dmaengine-pcm. This means CPU and Platform + * are different Component, but are sharing same component->dev. + * Simple Card had been supported it without special Platform selection. + * We need platforms here. + * + * In case of no Platform, it will be Platform == CPU, but Platform will be + * ignored by snd_soc_rtd_add_component(). + * + * see + * simple-card-utils.c :: asoc_simple_canonicalize_platform() + */ li->num[li->link].cpus = 1; - li->num[li->link].codecs = 1; li->num[li->link].platforms = 1; + li->num[li->link].codecs = 1; + li->link += 1; return 0; @@ -531,6 +546,11 @@ static int simple_count_dpcm(struct asoc_simple_priv *priv, } if (li->cpu) { + /* + * DON'T REMOVE platforms + * see + * simple_count_noml() + */ li->num[li->link].cpus = 1; li->num[li->link].platforms = 1; -- cgit From 59385ed41c37b609c70a1ebb46003e4cc6685ec0 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Wed, 22 Mar 2023 09:43:30 +0800 Subject: ASoC: tegra: remove unneeded semicolon ./sound/soc/tegra/tegra_asoc_machine.c:206:3-4: Unneeded semicolon. Reported-by: Abaci Robot Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=4583 Signed-off-by: Jiapeng Chong Link: https://lore.kernel.org/r/20230322014330.97079-1-jiapeng.chong@linux.alibaba.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_asoc_machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c index c2aaa496468c..f5092b410926 100644 --- a/sound/soc/tegra/tegra_asoc_machine.c +++ b/sound/soc/tegra/tegra_asoc_machine.c @@ -203,7 +203,7 @@ int tegra_asoc_machine_init(struct snd_soc_pcm_runtime *rtd) "nvidia,coupled-mic-hp-det")) { tegra_machine_mic_jack_gpio.desc = machine->gpiod_hp_det; tegra_machine_mic_jack_gpio.jack_status_check = coupled_mic_hp_check; - }; + } err = snd_soc_jack_add_gpios(&tegra_machine_mic_jack, 1, &tegra_machine_mic_jack_gpio); -- cgit From 935d31fdda2c69324b3eeb648a73fdedf4131474 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Wed, 22 Mar 2023 20:18:30 +0200 Subject: ASoC: SOF: ipc4/intel: Add missing mutex_unlock() There was a missing mutex_unlock() in sof_ipc4_widget_free() use_chain_dma if-branch that caused a static analysis error. The branch should not be used in a normal working configuration and if its used its an indication of a bad topology. Add missing mutex_unlock() and a warning print if the if-branch is taken, and another warning print to a symmetric place in sof_ipc4_widget_setup(). Fixes: ca5ce0caa67fa9 ("ASoC: SOF: ipc4/intel: Add support for chained DMA") Reported-by: kernel test robot Reported-by: Dan Carpenter Link: https://lore.kernel.org/r/202303222050.dCw0fPCW-lkp@intel.com/ Signed-off-by: Jyri Sarha Link: https://lore.kernel.org/r/20230322181830.574635-1-jyri.sarha@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index f1e1aed94da4..12775fcb6b54 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1989,8 +1989,11 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget case snd_soc_dapm_scheduler: pipeline = swidget->private; - if (pipeline->use_chain_dma) + if (pipeline->use_chain_dma) { + dev_warn(sdev->dev, "use_chain_dma set for schduler %s", + swidget->widget->name); return 0; + } dev_dbg(sdev->dev, "pipeline: %d memory pages: %d\n", swidget->pipeline_id, pipeline->mem_usage); @@ -2145,8 +2148,12 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget struct sof_ipc4_msg msg = {{ 0 }}; u32 header; - if (pipeline->use_chain_dma) + if (pipeline->use_chain_dma) { + dev_warn(sdev->dev, "use_chain_dma set for schduler %s", + swidget->widget->name); + mutex_unlock(&ipc4_data->pipeline_state_mutex); return 0; + } header = SOF_IPC4_GLB_PIPE_INSTANCE_ID(swidget->instance_id); header |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_DELETE_PIPELINE); -- cgit From e38c5e80c3d293a883c6f1d553f2146ec0bda35e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 22 Mar 2023 15:53:32 +0100 Subject: ASoC: Intel: bytcr_rt5640: Add quirk for the Acer Iconia One 7 B1-750 The Acer Iconia One 7 B1-750 tablet mostly works fine with the defaults for an Bay Trail CR tablet. Except for the internal mic, instead of an analog mic on IN3 a digital mic on DMIC1 is uses. Add a quirk with these settings for this tablet. Acked-by: Pierre-Louis Bossart Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20230322145332.131525-1-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'sound') diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 79e0039c79a3..5a12940ef907 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -533,6 +533,18 @@ static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream, /* Please keep this list alphabetically sorted */ static const struct dmi_system_id byt_rt5640_quirk_table[] = { + { /* Acer Iconia One 7 B1-750 */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "VESPA2"), + }, + .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | + BYT_RT5640_JD_SRC_JD1_IN4P | + BYT_RT5640_OVCD_TH_1500UA | + BYT_RT5640_OVCD_SF_0P75 | + BYT_RT5640_SSP0_AIF1 | + BYT_RT5640_MCLK_EN), + }, { /* Acer Iconia Tab 8 W1-810 */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"), -- cgit From 056db840115653659d86a3931a78b3c504edb2cc Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 23 Mar 2023 09:05:31 +0000 Subject: ASoC: SOF: ipc4/intel: Fix spelling mistake "schduler" -> "scheduler" There are two spelling mistakes in dev_warn messages. Fix them. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20230323090531.67679-1-colin.i.king@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 12775fcb6b54..de7213237b27 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1990,7 +1990,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget pipeline = swidget->private; if (pipeline->use_chain_dma) { - dev_warn(sdev->dev, "use_chain_dma set for schduler %s", + dev_warn(sdev->dev, "use_chain_dma set for scheduler %s", swidget->widget->name); return 0; } @@ -2149,7 +2149,7 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget u32 header; if (pipeline->use_chain_dma) { - dev_warn(sdev->dev, "use_chain_dma set for schduler %s", + dev_warn(sdev->dev, "use_chain_dma set for scheduler %s", swidget->widget->name); mutex_unlock(&ipc4_data->pipeline_state_mutex); return 0; -- cgit From a4a3203426f4b67535d6442ddc5dca8878a0678f Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 23 Mar 2023 11:01:25 +0000 Subject: ASoC: codecs: lpass: fix the order or clks turn off during suspend The order in which clocks are stopped matters as some of the clock like NPL are derived from MCLK. Without this patch, Dragonboard RB5 DSP would crash with below error: qcom_q6v5_pas 17300000.remoteproc: fatal error received: ABT_dal.c:278:ABTimeout: AHB Bus hang is detected, Number of bus hang detected := 2 , addr0 = 0x3370000 , addr1 = 0x0!!! Turn off fsgen first, followed by npl and then finally mclk, which is exactly the opposite order of enable sequence. Fixes: 1dc3459009c3 ("ASoC: codecs: lpass: register mclk after runtime pm") Reported-by: Amit Pundir Signed-off-by: Srinivas Kandagatla Tested-by: Amit Pundir Link: https://lore.kernel.org/r/20230323110125.23790-1-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-rx-macro.c | 4 ++-- sound/soc/codecs/lpass-tx-macro.c | 4 ++-- sound/soc/codecs/lpass-wsa-macro.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index a73a7d7a1c0a..faba4237bd3d 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -3670,9 +3670,9 @@ static int __maybe_unused rx_macro_runtime_suspend(struct device *dev) regcache_cache_only(rx->regmap, true); regcache_mark_dirty(rx->regmap); - clk_disable_unprepare(rx->mclk); - clk_disable_unprepare(rx->npl); clk_disable_unprepare(rx->fsgen); + clk_disable_unprepare(rx->npl); + clk_disable_unprepare(rx->mclk); return 0; } diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index 473d3cd39554..589c490a8c48 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -2098,9 +2098,9 @@ static int __maybe_unused tx_macro_runtime_suspend(struct device *dev) regcache_cache_only(tx->regmap, true); regcache_mark_dirty(tx->regmap); - clk_disable_unprepare(tx->mclk); - clk_disable_unprepare(tx->npl); clk_disable_unprepare(tx->fsgen); + clk_disable_unprepare(tx->npl); + clk_disable_unprepare(tx->mclk); return 0; } diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index ba7480f3831e..3f6f1bdd4e03 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -2506,9 +2506,9 @@ static int __maybe_unused wsa_macro_runtime_suspend(struct device *dev) regcache_cache_only(wsa->regmap, true); regcache_mark_dirty(wsa->regmap); - clk_disable_unprepare(wsa->mclk); - clk_disable_unprepare(wsa->npl); clk_disable_unprepare(wsa->fsgen); + clk_disable_unprepare(wsa->npl); + clk_disable_unprepare(wsa->mclk); return 0; } -- cgit From 33683cbf49b5412061cb1e4c876063fdef86def4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Mar 2023 22:53:29 +0000 Subject: ASoC: fsl: remove unnecessary dai_link->platform dai_link->platform is no longer needed if CPU and Platform are same Component. This patch removes unnecessary dai_link->platform. Dummy Platform is also not necessary. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87o7ojjd06.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmix.c | 14 ++++---------- sound/soc/fsl/imx-spdif.c | 5 +---- 2 files changed, 5 insertions(+), 14 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index 1292a845c424..2c57fe9d2d08 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -207,8 +207,8 @@ static int imx_audmix_probe(struct platform_device *pdev) for (i = 0; i < num_dai; i++) { struct snd_soc_dai_link_component *dlc; - /* for CPU/Codec/Platform x 2 */ - dlc = devm_kcalloc(&pdev->dev, 6, sizeof(*dlc), GFP_KERNEL); + /* for CPU/Codec x 2 */ + dlc = devm_kcalloc(&pdev->dev, 4, sizeof(*dlc), GFP_KERNEL); if (!dlc) return -ENOMEM; @@ -240,11 +240,9 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[i].cpus = &dlc[0]; priv->dai[i].codecs = &dlc[1]; - priv->dai[i].platforms = &dlc[2]; priv->dai[i].num_cpus = 1; priv->dai[i].num_codecs = 1; - priv->dai[i].num_platforms = 1; priv->dai[i].name = dai_name; priv->dai[i].stream_name = "HiFi-AUDMIX-FE"; @@ -252,7 +250,6 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[i].codecs->name = "snd-soc-dummy"; priv->dai[i].cpus->of_node = args.np; priv->dai[i].cpus->dai_name = dev_name(&cpu_pdev->dev); - priv->dai[i].platforms->of_node = args.np; priv->dai[i].dynamic = 1; priv->dai[i].dpcm_playback = 1; priv->dai[i].dpcm_capture = (i == 0 ? 1 : 0); @@ -267,20 +264,17 @@ static int imx_audmix_probe(struct platform_device *pdev) be_cp = devm_kasprintf(&pdev->dev, GFP_KERNEL, "AUDMIX-Capture-%d", i); - priv->dai[num_dai + i].cpus = &dlc[3]; - priv->dai[num_dai + i].codecs = &dlc[4]; - priv->dai[num_dai + i].platforms = &dlc[5]; + priv->dai[num_dai + i].cpus = &dlc[2]; + priv->dai[num_dai + i].codecs = &dlc[3]; priv->dai[num_dai + i].num_cpus = 1; priv->dai[num_dai + i].num_codecs = 1; - priv->dai[num_dai + i].num_platforms = 1; priv->dai[num_dai + i].name = be_name; priv->dai[num_dai + i].codecs->dai_name = "snd-soc-dummy-dai"; priv->dai[num_dai + i].codecs->name = "snd-soc-dummy"; priv->dai[num_dai + i].cpus->of_node = audmix_np; priv->dai[num_dai + i].cpus->dai_name = be_name; - priv->dai[num_dai + i].platforms->name = "snd-soc-dummy"; priv->dai[num_dai + i].no_pcm = 1; priv->dai[num_dai + i].dpcm_playback = 1; priv->dai[num_dai + i].dpcm_capture = 1; diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index 4446fba755b9..114b49660193 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c @@ -26,7 +26,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(&pdev->dev, 2 * sizeof(*comp), GFP_KERNEL); if (!data || !comp) { ret = -ENOMEM; goto end; @@ -34,18 +34,15 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) data->dai.cpus = &comp[0]; data->dai.codecs = &comp[1]; - data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; - data->dai.num_platforms = 1; data->dai.name = "S/PDIF PCM"; data->dai.stream_name = "S/PDIF PCM"; data->dai.codecs->dai_name = "snd-soc-dummy-dai"; data->dai.codecs->name = "snd-soc-dummy"; data->dai.cpus->of_node = spdif_np; - data->dai.platforms->of_node = spdif_np; data->dai.playback_only = true; data->dai.capture_only = true; -- cgit From 2f650f87c03cab72e751fc739f42a1e257bdc6b9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Mar 2023 22:53:35 +0000 Subject: ASoC: atmel: remove unnecessary dai_link->platform dai_link->platform is no longer needed if CPU and Platform are same Component. This patch removes unnecessary dai_link->platform. Signed-off-by: Kuninori Morimoto Acked-by: Nicolas Ferre Link: https://lore.kernel.org/r/87mt43jd00.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-classd.c | 5 +---- sound/soc/atmel/atmel-pdmic.c | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index 9883e6867fd1..007ab746973d 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -473,24 +473,21 @@ static int atmel_classd_asoc_card_init(struct device *dev, if (!dai_link) return -ENOMEM; - comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); if (!comp) return -ENOMEM; dai_link->cpus = &comp[0]; dai_link->codecs = &comp[1]; - dai_link->platforms = &comp[2]; dai_link->num_cpus = 1; dai_link->num_codecs = 1; - dai_link->num_platforms = 1; dai_link->name = "CLASSD"; dai_link->stream_name = "CLASSD PCM"; dai_link->codecs->dai_name = "snd-soc-dummy-dai"; dai_link->cpus->dai_name = dev_name(dev); dai_link->codecs->name = "snd-soc-dummy"; - dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; card->num_links = 1; diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c index 12cd40b15644..00c7b3a34ef5 100644 --- a/sound/soc/atmel/atmel-pdmic.c +++ b/sound/soc/atmel/atmel-pdmic.c @@ -496,24 +496,21 @@ static int atmel_pdmic_asoc_card_init(struct device *dev, if (!dai_link) return -ENOMEM; - comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); if (!comp) return -ENOMEM; dai_link->cpus = &comp[0]; dai_link->codecs = &comp[1]; - dai_link->platforms = &comp[2]; dai_link->num_cpus = 1; dai_link->num_codecs = 1; - dai_link->num_platforms = 1; dai_link->name = "PDMIC"; dai_link->stream_name = "PDMIC PCM"; dai_link->codecs->dai_name = "snd-soc-dummy-dai"; dai_link->cpus->dai_name = dev_name(dev); dai_link->codecs->name = "snd-soc-dummy"; - dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; card->num_links = 1; -- cgit From 3b0db249cf8fe0027e2a4161d27a8566d82fcd80 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Mar 2023 22:53:41 +0000 Subject: ASoC: ti: remove unnecessary dai_link->platform dai_link->platform is no longer needed if CPU and Platform are same Component. This patch removes unnecessary dai_link->platform. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87lejnjczu.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/ti/omap-hdmi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c index ad37785e05d8..96c3569d7643 100644 --- a/sound/soc/ti/omap-hdmi.c +++ b/sound/soc/ti/omap-hdmi.c @@ -365,20 +365,17 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) if (!card->dai_link) return -ENOMEM; - compnent = devm_kzalloc(dev, 3 * sizeof(*compnent), GFP_KERNEL); + compnent = devm_kzalloc(dev, 2 * sizeof(*compnent), GFP_KERNEL); if (!compnent) return -ENOMEM; card->dai_link->cpus = &compnent[0]; card->dai_link->num_cpus = 1; card->dai_link->codecs = &compnent[1]; card->dai_link->num_codecs = 1; - card->dai_link->platforms = &compnent[2]; - card->dai_link->num_platforms = 1; card->dai_link->name = card->name; card->dai_link->stream_name = card->name; card->dai_link->cpus->dai_name = dev_name(ad->dssdev); - card->dai_link->platforms->name = dev_name(ad->dssdev); card->dai_link->codecs->name = "snd-soc-dummy"; card->dai_link->codecs->dai_name = "snd-soc-dummy-dai"; card->num_links = 1; -- cgit From e7098ba9b3785d626326040d300f95fec79aa765 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Mar 2023 22:53:46 +0000 Subject: ASoC: soc-topology.c: remove unnecessary dai_link->platform dai_link->platform is no longer needed if CPU and Platform are same Component. This patch removes unnecessary dai_link->platform. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87jzz7jczp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 07421f5d4ebd..7f6424fa59ab 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1685,8 +1685,8 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, struct snd_soc_dai_link_component *dlc; int ret; - /* link + cpu + codec + platform */ - link = devm_kzalloc(tplg->dev, sizeof(*link) + (3 * sizeof(*dlc)), GFP_KERNEL); + /* link + cpu + codec */ + link = devm_kzalloc(tplg->dev, sizeof(*link) + (2 * sizeof(*dlc)), GFP_KERNEL); if (link == NULL) return -ENOMEM; @@ -1694,11 +1694,9 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->cpus = &dlc[0]; link->codecs = &dlc[1]; - link->platforms = &dlc[2]; link->num_cpus = 1; link->num_codecs = 1; - link->num_platforms = 1; link->dobj.index = tplg->index; link->dobj.type = SND_SOC_DOBJ_DAI_LINK; @@ -1726,8 +1724,6 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->codecs->name = "snd-soc-dummy"; link->codecs->dai_name = "snd-soc-dummy-dai"; - link->platforms->name = "snd-soc-dummy"; - /* enable DPCM */ link->dynamic = 1; link->ignore_pmdown_time = 1; -- cgit From 92405802a7d6aa1953915af869192296d1792d18 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Mar 2023 22:56:08 +0000 Subject: ASoC: simple-card.c: add missing of_node_put() It is missing of_node_put() for platform. This patch fixup it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ilerjcvr.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index fcd6c44f89f6..6f044cc8357e 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -422,6 +422,7 @@ static int __simple_for_each_link(struct asoc_simple_priv *priv, } of_node_put(codec); + of_node_put(plat); node = of_get_next_child(top, node); } while (!is_top && node); -- cgit From ab76c891a687ae871f7e76dbf9bc3a0e32b53423 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Fri, 24 Mar 2023 10:23:03 +0800 Subject: ASoC: cs35l56: Fix an unsigned comparison which can never be negative The variable 'rv' is defined as unsigned type, so the following if statement is invalid, we can modify the type of rv to int. if (rv < 0) { dev_err(cs35l56->dev, "irq: failed to get pm_runtime: %d\n", rv); goto err_unlock; } ./sound/soc/codecs/cs35l56.c:333:5-7: WARNING: Unsigned expression compared with zero: rv < 0. Reported-by: Abaci Robot Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=4599 Signed-off-by: Jiapeng Chong Reviewed-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230324022303.121485-1-jiapeng.chong@linux.alibaba.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 90fc79b5666d..d97b465f0d3c 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -321,7 +321,9 @@ irqreturn_t cs35l56_irq(int irq, void *data) struct cs35l56_private *cs35l56 = data; unsigned int status1 = 0, status8 = 0, status20 = 0; unsigned int mask1, mask8, mask20; - unsigned int rv, val; + unsigned int val; + int rv; + irqreturn_t ret = IRQ_NONE; if (!cs35l56->init_done) -- cgit From 37b58becc1cee4d591024f2056d7ffa99c6089e0 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Fri, 24 Mar 2023 14:40:19 +0200 Subject: ASoC: soc-compress: Inherit atomicity from DAI link for Compress FE After commit bbf7d3b1c4f40 ("ASoC: soc-pcm: align BE 'atomicity' with that of the FE") BE and FE atomicity must match. In the case of Compress PCM there is a mismatch in atomicity between FE and BE and we get errors like this: [ 36.434566] sai1-wm8960-hifi: dpcm_be_connect: FE is atomic but BE is nonatomic, invalid configuration [ 36.444278] PCM Deep Buffer: ASoC: can't connect SAI1.OUT In order to fix this we must inherit the atomicity from DAI link associated with current PCM Compress FE. Fixes: bbf7d3b1c4f4 ("ASoC: soc-pcm: align BE 'atomicity' with that of the FE") Signed-off-by: Daniel Baluta Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20230324124019.30826-1-daniel.baluta@oss.nxp.com Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 554c329ec87f..6e74a6c48986 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -615,6 +615,9 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) return ret; } + /* inherit atomicity from DAI link */ + be_pcm->nonatomic = rtd->dai_link->nonatomic; + rtd->pcm = be_pcm; rtd->fe_compr = 1; if (rtd->dai_link->dpcm_playback) -- cgit From 283771e8eefcbe4a0a84c6a00a0b7a210bbc5846 Mon Sep 17 00:00:00 2001 From: Harshit Mogalapalli Date: Fri, 24 Mar 2023 07:55:35 -0700 Subject: ASoC: cs35l56: Remove redundant return statement in cs35l56_spi_probe() We have unreachable 'return ret' statement in cs35l56_spi_probe(), delete it as its dead code.. This is found by static analysis with smatch. Fixes: e49611252900 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") Signed-off-by: Harshit Mogalapalli Reviewed-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230324145535.3951689-1-harshit.m.mogalapalli@oracle.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-spi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c index 80dcf37daae2..4b2084e85f29 100644 --- a/sound/soc/codecs/cs35l56-spi.c +++ b/sound/soc/codecs/cs35l56-spi.c @@ -29,7 +29,6 @@ static int cs35l56_spi_probe(struct spi_device *spi) if (IS_ERR(cs35l56->regmap)) { ret = PTR_ERR(cs35l56->regmap); return dev_err_probe(&spi->dev, ret, "Failed to allocate register map\n"); - return ret; } cs35l56->dev = &spi->dev; -- cgit From f6887a71bdd2f0dcba9b8180dd2223cfa8637e85 Mon Sep 17 00:00:00 2001 From: Jason Montleon Date: Fri, 24 Mar 2023 13:07:11 -0400 Subject: ASoC: hdac_hdmi: use set_stream() instead of set_tdm_slots() hdac_hdmi was not updated to use set_stream() instead of set_tdm_slots() in the original commit so HDMI no longer produces audio. Cc: stable@vger.kernel.org Link: https://lore.kernel.org/regressions/CAJD_bPKQdtaExvVEKxhQ47G-ZXDA=k+gzhMJRHLBe=mysPnuKA@mail.gmail.com/ Fixes: 636110411ca7 ("ASoC: Intel/SOF: use set_stream() instead of set_tdm_slots() for HDAudio") Signed-off-by: Jason Montleon Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20230324170711.2526-1-jmontleo@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index ed4f7cdda04f..8b6b76029694 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -436,23 +436,28 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_device *hdev, return 0; } -static int hdac_hdmi_set_tdm_slot(struct snd_soc_dai *dai, - unsigned int tx_mask, unsigned int rx_mask, - int slots, int slot_width) +static int hdac_hdmi_set_stream(struct snd_soc_dai *dai, + void *stream, int direction) { struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai); struct hdac_device *hdev = hdmi->hdev; struct hdac_hdmi_dai_port_map *dai_map; struct hdac_hdmi_pcm *pcm; + struct hdac_stream *hstream; - dev_dbg(&hdev->dev, "%s: strm_tag: %d\n", __func__, tx_mask); + if (!stream) + return -EINVAL; + + hstream = (struct hdac_stream *)stream; + + dev_dbg(&hdev->dev, "%s: strm_tag: %d\n", __func__, hstream->stream_tag); dai_map = &hdmi->dai_map[dai->id]; pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt); if (pcm) - pcm->stream_tag = (tx_mask << 4); + pcm->stream_tag = (hstream->stream_tag << 4); return 0; } @@ -1544,7 +1549,7 @@ static const struct snd_soc_dai_ops hdmi_dai_ops = { .startup = hdac_hdmi_pcm_open, .shutdown = hdac_hdmi_pcm_close, .hw_params = hdac_hdmi_set_hw_params, - .set_tdm_slot = hdac_hdmi_set_tdm_slot, + .set_stream = hdac_hdmi_set_stream, }; /* -- cgit From 65d4d7259bfec376b6b1483b4fe4058a5ba2259b Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 26 Mar 2023 14:43:38 +0200 Subject: ASoC: meson: Use the devm_clk_get_optional() helper Use devm_clk_get_optional() instead of hand writing it. This saves some loC and improves the semantic. Signed-off-by: Christophe JAILLET Reviewed-by: Jerome Brunet Link: https://lore.kernel.org/r/8dab942d6ce47657a9c038295959be80bb2ee09e.1679834598.git.christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/meson/axg-tdm-interface.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'sound') diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index 7624aafe9009..5e5e4c56d505 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -496,7 +496,7 @@ static int axg_tdm_iface_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct snd_soc_dai_driver *dai_drv; struct axg_tdm_iface *iface; - int ret, i; + int i; iface = devm_kzalloc(dev, sizeof(*iface), GFP_KERNEL); if (!iface) @@ -533,14 +533,9 @@ static int axg_tdm_iface_probe(struct platform_device *pdev) * At this point, ignore the error if mclk is missing. We'll * throw an error if the cpu dai is master and mclk is missing */ - iface->mclk = devm_clk_get(dev, "mclk"); - if (IS_ERR(iface->mclk)) { - ret = PTR_ERR(iface->mclk); - if (ret == -ENOENT) - iface->mclk = NULL; - else - return dev_err_probe(dev, ret, "failed to get mclk\n"); - } + iface->mclk = devm_clk_get_optional(dev, "mclk"); + if (IS_ERR(iface->mclk)) + return dev_err_probe(dev, PTR_ERR(iface->mclk), "failed to get mclk\n"); return devm_snd_soc_register_component(dev, &axg_tdm_iface_component_drv, dai_drv, -- cgit From ad58151fa04280a938c173bcba05ba42a4073d92 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 27 Mar 2023 04:33:41 +0000 Subject: ASoC: audio-graph-card2-custom-sample.dtsi: use card->name to avoid long name Current Card2 Custom Sample will be too long Card name, and be error audio-graph-card2-custom-sample audio-graph-card2-custom-sample \ ASoC: driver name too long \ audio-graph-card2-custom-sample' -> 'audio-graph-car' This patch uses short name to avoid it Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87bkke7qzf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card2-custom-sample.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/soc/generic/audio-graph-card2-custom-sample.c b/sound/soc/generic/audio-graph-card2-custom-sample.c index 4a2c743e286c..a3142be9323e 100644 --- a/sound/soc/generic/audio-graph-card2-custom-sample.c +++ b/sound/soc/generic/audio-graph-card2-custom-sample.c @@ -151,6 +151,9 @@ static int custom_probe(struct platform_device *pdev) simple_priv = &custom_priv->simple_priv; simple_priv->ops = &custom_ops; /* customize dai_link ops */ + /* "audio-graph-card2-custom-sample" is too long */ + simple_priv->snd_card.name = "card2-custom"; + /* use audio-graph-card2 parsing with own custom hooks */ ret = audio_graph2_parse_of(simple_priv, dev, &custom_hooks); if (ret < 0) -- cgit From 8908c36dabad7dd52872034f9f42c6c077bc7270 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 27 Mar 2023 16:55:55 +0200 Subject: ASoC: qcom: audioreach: drop stray 'get' from error message Drop the stray 'get', which appears to be a copy-paste error, from the registration-failure error message. Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230327145555.19351-1-johan+linaro@kernel.org Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6apm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c index 994c9e823a88..a7a3f973eb6d 100644 --- a/sound/soc/qcom/qdsp6/q6apm.c +++ b/sound/soc/qcom/qdsp6/q6apm.c @@ -676,7 +676,7 @@ static int apm_probe(gpr_device_t *gdev) ret = devm_snd_soc_register_component(dev, &q6apm_audio_component, NULL, 0); if (ret < 0) { - dev_err(dev, "failed to get register q6apm: %d\n", ret); + dev_err(dev, "failed to register q6apm: %d\n", ret); return ret; } -- cgit From ffaf886e249ee269f9084c21fbd8617ce9b83817 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 27 Mar 2023 00:34:26 +0000 Subject: ASoC: soc-core.c: add snd_soc_add_pcm_runtimes() Current ASoC supports snd_soc_add_pcm_runtime(), but user need to call it one-by-one if it has multi dai_links. This patch adds snd_soc_add_pcm_runtimes() which supports multi dai_links. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87h6u76nhq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/hdaudio.c | 10 ++++------ sound/soc/soc-core.c | 31 +++++++++++++++++++++---------- sound/soc/soc-topology.c | 2 +- 3 files changed, 26 insertions(+), 17 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/avs/boards/hdaudio.c b/sound/soc/intel/avs/boards/hdaudio.c index e68c4c7aa2ba..a542a67e21d0 100644 --- a/sound/soc/intel/avs/boards/hdaudio.c +++ b/sound/soc/intel/avs/boards/hdaudio.c @@ -194,12 +194,10 @@ static int avs_probing_link_init(struct snd_soc_pcm_runtime *rtm) return ret; } - for (n = 0; n < pcm_count; n++) { - ret = snd_soc_add_pcm_runtime(card, &links[n]); - if (ret < 0) { - dev_err(card->dev, "add links failed: %d\n", ret); - return ret; - } + ret = snd_soc_add_pcm_runtimes(card, links, pcm_count); + if (ret < 0) { + dev_err(card->dev, "add links failed: %d\n", ret); + return ret; } ret = avs_create_dapm_routes(card->dev, codec, pcm_count, &routes, &n); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2faa0d8d0d8e..9bbcff492c1e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -959,8 +959,8 @@ EXPORT_SYMBOL_GPL(snd_soc_remove_pcm_runtime); * topology component. And machine drivers can still define static * DAI links in dai_link array. */ -int snd_soc_add_pcm_runtime(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_link) +static int snd_soc_add_pcm_runtime(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link) { struct snd_soc_pcm_runtime *rtd; struct snd_soc_dai_link_component *codec, *platform, *cpu; @@ -1027,7 +1027,21 @@ _err_defer: snd_soc_remove_pcm_runtime(card, rtd); return -EPROBE_DEFER; } -EXPORT_SYMBOL_GPL(snd_soc_add_pcm_runtime); + +int snd_soc_add_pcm_runtimes(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link, + int num_dai_link) +{ + for (int i = 0; i < num_dai_link; i++) { + int ret = snd_soc_add_pcm_runtime(card, dai_link + i); + + if (ret < 0) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_add_pcm_runtimes); static void snd_soc_runtime_get_dai_fmt(struct snd_soc_pcm_runtime *rtd) { @@ -1921,8 +1935,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) { struct snd_soc_pcm_runtime *rtd; struct snd_soc_component *component; - struct snd_soc_dai_link *dai_link; - int ret, i; + int ret; mutex_lock(&client_mutex); mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); @@ -1939,11 +1952,9 @@ static int snd_soc_bind_card(struct snd_soc_card *card) /* add predefined DAI links to the list */ card->num_rtd = 0; - for_each_card_prelinks(card, i, dai_link) { - ret = snd_soc_add_pcm_runtime(card, dai_link); - if (ret < 0) - goto probe_end; - } + ret = snd_soc_add_pcm_runtimes(card, card->dai_link, card->num_links); + if (ret < 0) + goto probe_end; /* card bind complete so register a sound card */ ret = snd_card_new(card->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 7f6424fa59ab..be9849749713 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1741,7 +1741,7 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, goto err; } - ret = snd_soc_add_pcm_runtime(tplg->comp->card, link); + ret = snd_soc_add_pcm_runtimes(tplg->comp->card, link, 1); if (ret < 0) { dev_err(tplg->dev, "ASoC: adding FE link failed\n"); goto err; -- cgit From 44378cd113e5f15bb0a89f5ac5a0e687b52feb90 Mon Sep 17 00:00:00 2001 From: Duy Nguyen Date: Tue, 28 Mar 2023 00:03:03 +0000 Subject: ASoC: da7213.c: add missing pm_runtime_disable() da7213.c is missing pm_runtime_disable(), thus we will get below error when rmmod -> insmod. $ rmmod snd-soc-da7213.ko $ insmod snd-soc-da7213.ko da7213 0-001a: Unbalanced pm_runtime_enable!" [Kuninori adjusted to latest upstream] Signed-off-by: Duy Nguyen Signed-off-by: Kuninori Morimoto Tested-by: Khanh Le Link: https://lore.kernel.org/r/87mt3xg2tk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/da7213.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 0068780fe0a7..1c1f211a8e2e 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -2022,6 +2022,11 @@ static int da7213_i2c_probe(struct i2c_client *i2c) return ret; } +static void da7213_i2c_remove(struct i2c_client *i2c) +{ + pm_runtime_disable(&i2c->dev); +} + static int __maybe_unused da7213_runtime_suspend(struct device *dev) { struct da7213_priv *da7213 = dev_get_drvdata(dev); @@ -2065,6 +2070,7 @@ static struct i2c_driver da7213_i2c_driver = { .pm = &da7213_pm, }, .probe_new = da7213_i2c_probe, + .remove = da7213_i2c_remove, .id_table = da7213_i2c_id, }; -- cgit From 492fe974fed0754f7076580e069e1e182e7b3603 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 13 Mar 2023 08:54:39 +0100 Subject: ASoC: codecs: lpass-rx-macro: add support for SM8550 Add support for the RX macro codec on Qualcomm SM8550. SM8550 does not use NPL clock, thus add flags allowing to skip it. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230313075445.17160-3-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-macro-common.h | 3 +++ sound/soc/codecs/lpass-rx-macro.c | 36 +++++++++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/lpass-macro-common.h b/sound/soc/codecs/lpass-macro-common.h index f2cbf9fe2c6e..4eb886565ea3 100644 --- a/sound/soc/codecs/lpass-macro-common.h +++ b/sound/soc/codecs/lpass-macro-common.h @@ -6,6 +6,9 @@ #ifndef __LPASS_MACRO_COMMON_H__ #define __LPASS_MACRO_COMMON_H__ +/* NPL clock is expected */ +#define LPASS_MACRO_FLAG_HAS_NPL_CLOCK BIT(0) + struct lpass_macro { struct device *macro_pd; struct device *dcodec_pd; diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 9e0a4e8a46c3..532b19b1980d 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -3491,7 +3491,10 @@ static int rx_macro_register_mclk_output(struct rx_macro *rx) struct clk_init_data init; int ret; - parent_clk_name = __clk_get_name(rx->npl); + if (rx->npl) + parent_clk_name = __clk_get_name(rx->npl); + else + parent_clk_name = __clk_get_name(rx->mclk); init.name = clk_name; init.ops = &swclk_gate_ops; @@ -3521,10 +3524,13 @@ static const struct snd_soc_component_driver rx_macro_component_drv = { static int rx_macro_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + kernel_ulong_t flags; struct rx_macro *rx; void __iomem *base; int ret; + flags = (kernel_ulong_t)device_get_match_data(dev); + rx = devm_kzalloc(dev, sizeof(*rx), GFP_KERNEL); if (!rx) return -ENOMEM; @@ -3541,9 +3547,11 @@ static int rx_macro_probe(struct platform_device *pdev) if (IS_ERR(rx->mclk)) return PTR_ERR(rx->mclk); - rx->npl = devm_clk_get(dev, "npl"); - if (IS_ERR(rx->npl)) - return PTR_ERR(rx->npl); + if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { + rx->npl = devm_clk_get(dev, "npl"); + if (IS_ERR(rx->npl)) + return PTR_ERR(rx->npl); + } rx->fsgen = devm_clk_get(dev, "fsgen"); if (IS_ERR(rx->fsgen)) @@ -3653,10 +3661,22 @@ static void rx_macro_remove(struct platform_device *pdev) } static const struct of_device_id rx_macro_dt_match[] = { - { .compatible = "qcom,sc7280-lpass-rx-macro" }, - { .compatible = "qcom,sm8250-lpass-rx-macro" }, - { .compatible = "qcom,sm8450-lpass-rx-macro" }, - { .compatible = "qcom,sc8280xp-lpass-rx-macro" }, + { + .compatible = "qcom,sc7280-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + + }, { + .compatible = "qcom,sm8250-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8450-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8550-lpass-rx-macro", + }, { + .compatible = "qcom,sc8280xp-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { } }; MODULE_DEVICE_TABLE(of, rx_macro_dt_match); -- cgit From 5faf6a1c5256559af98c998b7416e4db8fb09b75 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 13 Mar 2023 08:54:42 +0100 Subject: ASoC: codecs: lpass-tx-macro: add support for SM8550 Add support for the TX macro codec on Qualcomm SM8550. SM8550 does not use NPL clock, thus add flags allowing to skip it. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230313075445.17160-6-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-tx-macro.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index b044c9c6f89b..ae01e464502c 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -1915,7 +1915,10 @@ static int tx_macro_register_mclk_output(struct tx_macro *tx) struct clk_init_data init; int ret; - parent_clk_name = __clk_get_name(tx->npl); + if (tx->npl) + parent_clk_name = __clk_get_name(tx->npl); + else + parent_clk_name = __clk_get_name(tx->mclk); init.name = clk_name; init.ops = &swclk_gate_ops; @@ -1946,10 +1949,13 @@ static int tx_macro_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + kernel_ulong_t flags; struct tx_macro *tx; void __iomem *base; int ret, reg; + flags = (kernel_ulong_t)device_get_match_data(dev); + tx = devm_kzalloc(dev, sizeof(*tx), GFP_KERNEL); if (!tx) return -ENOMEM; @@ -1966,9 +1972,11 @@ static int tx_macro_probe(struct platform_device *pdev) if (IS_ERR(tx->mclk)) return PTR_ERR(tx->mclk); - tx->npl = devm_clk_get(dev, "npl"); - if (IS_ERR(tx->npl)) - return PTR_ERR(tx->npl); + if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { + tx->npl = devm_clk_get(dev, "npl"); + if (IS_ERR(tx->npl)) + return PTR_ERR(tx->npl); + } tx->fsgen = devm_clk_get(dev, "fsgen"); if (IS_ERR(tx->fsgen)) @@ -2143,10 +2151,21 @@ static const struct dev_pm_ops tx_macro_pm_ops = { }; static const struct of_device_id tx_macro_dt_match[] = { - { .compatible = "qcom,sc7280-lpass-tx-macro" }, - { .compatible = "qcom,sm8250-lpass-tx-macro" }, - { .compatible = "qcom,sm8450-lpass-tx-macro" }, - { .compatible = "qcom,sc8280xp-lpass-tx-macro" }, + { + .compatible = "qcom,sc7280-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8250-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8450-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8550-lpass-tx-macro", + }, { + .compatible = "qcom,sc8280xp-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { } }; MODULE_DEVICE_TABLE(of, tx_macro_dt_match); -- cgit From 6b004b836ced4d9ce655b5f1c810833c1a880369 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 13 Mar 2023 08:54:45 +0100 Subject: ASoC: codecs: lpass-wsa-macro: add support for SM8550 Add support for the WSA macro codec on Qualcomm SM8550. SM8550 does not use NPL clock, thus add flags allowing to skip it. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230313075445.17160-9-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-wsa-macro.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 728f26d12ab0..3cbcbfc219b2 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -14,6 +14,8 @@ #include #include #include + +#include "lpass-macro-common.h" #include "lpass-wsa-macro.h" #define CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL (0x0000) @@ -2346,7 +2348,10 @@ static int wsa_macro_register_mclk_output(struct wsa_macro *wsa) struct clk_init_data init; int ret; - parent_clk_name = __clk_get_name(wsa->npl); + if (wsa->npl) + parent_clk_name = __clk_get_name(wsa->npl); + else + parent_clk_name = __clk_get_name(wsa->mclk); init.name = "mclk"; of_property_read_string(dev_of_node(dev), "clock-output-names", @@ -2379,9 +2384,12 @@ static int wsa_macro_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct wsa_macro *wsa; + kernel_ulong_t flags; void __iomem *base; int ret; + flags = (kernel_ulong_t)device_get_match_data(dev); + wsa = devm_kzalloc(dev, sizeof(*wsa), GFP_KERNEL); if (!wsa) return -ENOMEM; @@ -2398,9 +2406,11 @@ static int wsa_macro_probe(struct platform_device *pdev) if (IS_ERR(wsa->mclk)) return PTR_ERR(wsa->mclk); - wsa->npl = devm_clk_get(dev, "npl"); - if (IS_ERR(wsa->npl)) - return PTR_ERR(wsa->npl); + if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { + wsa->npl = devm_clk_get(dev, "npl"); + if (IS_ERR(wsa->npl)) + return PTR_ERR(wsa->npl); + } wsa->fsgen = devm_clk_get(dev, "fsgen"); if (IS_ERR(wsa->fsgen)) @@ -2551,10 +2561,21 @@ static const struct dev_pm_ops wsa_macro_pm_ops = { }; static const struct of_device_id wsa_macro_dt_match[] = { - {.compatible = "qcom,sc7280-lpass-wsa-macro"}, - {.compatible = "qcom,sm8250-lpass-wsa-macro"}, - {.compatible = "qcom,sm8450-lpass-wsa-macro"}, - {.compatible = "qcom,sc8280xp-lpass-wsa-macro" }, + { + .compatible = "qcom,sc7280-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8250-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8450-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8550-lpass-wsa-macro", + }, { + .compatible = "qcom,sc8280xp-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, {} }; MODULE_DEVICE_TABLE(of, wsa_macro_dt_match); -- cgit From 39db65a0a17b54915b269d3685f253a4731f344c Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 28 Mar 2023 12:49:01 +0300 Subject: ASoC: es8316: Handle optional IRQ assignment The driver is able to work fine without relying on a mandatory interrupt being assigned to the I2C device. This is only needed when making use of the jack-detect support. However, the following warning message is always emitted when there is no such interrupt available: es8316 0-0011: Failed to get IRQ 0: -22 Do not attempt to request an IRQ if it is not available/valid. This also ensures the rather misleading message is not displayed anymore. Also note the IRQ validation relies on commit dab472eb931bc291 ("i2c / ACPI: Use 0 to indicate that device does not have interrupt assigned"). Fixes: 822257661031 ("ASoC: es8316: Add jack-detect support") Signed-off-by: Cristian Ciocaltea Reviewed-by: Hans de Goede Link: https://lore.kernel.org/r/20230328094901.50763-1-cristian.ciocaltea@collabora.com Signed-off-by: Mark Brown --- sound/soc/codecs/es8316.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index 056c3082fe02..f7d7a9c91e04 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -842,12 +842,14 @@ static int es8316_i2c_probe(struct i2c_client *i2c_client) es8316->irq = i2c_client->irq; mutex_init(&es8316->lock); - ret = devm_request_threaded_irq(dev, es8316->irq, NULL, es8316_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN, - "es8316", es8316); - if (ret) { - dev_warn(dev, "Failed to get IRQ %d: %d\n", es8316->irq, ret); - es8316->irq = -ENXIO; + if (es8316->irq > 0) { + ret = devm_request_threaded_irq(dev, es8316->irq, NULL, es8316_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN, + "es8316", es8316); + if (ret) { + dev_warn(dev, "Failed to get IRQ %d: %d\n", es8316->irq, ret); + es8316->irq = -ENXIO; + } } return devm_snd_soc_register_component(&i2c_client->dev, -- cgit From 7739b152776655a86568103afded77aa240f3ad4 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 28 Mar 2023 10:58:19 +0100 Subject: ASoC: wm8903: Remove outdated DMIC comment Support for DMICs was added in commit 97945c46a23d ("ASoC: WM8903: Implement DMIC support"). Remove them from the TODO list at the top of the driver. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20230328095819.1632802-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8903.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 41346e5ec5ad..1dc8e20bdace 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -9,7 +9,6 @@ * * TODO: * - TDM mode configuration. - * - Digital microphone support. */ #include -- cgit From ef36ca92754b4e50289aee99453e69c6ff13edad Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 29 Mar 2023 00:21:03 +0000 Subject: ASoC: soc-topology.c: dai_link->platform again On SOF, many topology is assuming dai_link->platform exists, and is allowed to be overwritten on each link_load(). This patch restore the removed dai_link->platform for SOF, and add the comment. Fixes: e7098ba9b378 ("ASoC: soc-topology.c: remove unnecessary dai_link->platform") Reported-by: Peter Ujfalusi Link: https://lore.kernel.org/r/87jzz7jczp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto Tested-by: Peter Ujfalusi Link: https://lore.kernel.org/r/87v8ikcsr5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index be9849749713..d0aca6b9058b 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1685,8 +1685,8 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, struct snd_soc_dai_link_component *dlc; int ret; - /* link + cpu + codec */ - link = devm_kzalloc(tplg->dev, sizeof(*link) + (2 * sizeof(*dlc)), GFP_KERNEL); + /* link + cpu + codec + platform */ + link = devm_kzalloc(tplg->dev, sizeof(*link) + (3 * sizeof(*dlc)), GFP_KERNEL); if (link == NULL) return -ENOMEM; @@ -1724,6 +1724,14 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->codecs->name = "snd-soc-dummy"; link->codecs->dai_name = "snd-soc-dummy-dai"; + /* + * Many topology is assuming link has Platform. + * This might be overwritten at soc_tplg_dai_link_load(). + */ + link->platforms = &dlc[2]; + link->platforms->name = "snd-soc-dummy"; + link->num_platforms = 1; + /* enable DPCM */ link->dynamic = 1; link->ignore_pmdown_time = 1; -- cgit From 3e226b4db21fc339423c318ec7d238424c884d11 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 27 Mar 2023 15:22:47 +0200 Subject: ASoC: codecs: lpass-rx-macro: add support for SM8550 Add support for the RX macro codec on Qualcomm SM8550. SM8550 does not use NPL clock, thus add flags allowing to skip it. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230327132254.147975-4-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-macro-common.h | 3 +++ sound/soc/codecs/lpass-rx-macro.c | 36 +++++++++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/lpass-macro-common.h b/sound/soc/codecs/lpass-macro-common.h index f2cbf9fe2c6e..4eb886565ea3 100644 --- a/sound/soc/codecs/lpass-macro-common.h +++ b/sound/soc/codecs/lpass-macro-common.h @@ -6,6 +6,9 @@ #ifndef __LPASS_MACRO_COMMON_H__ #define __LPASS_MACRO_COMMON_H__ +/* NPL clock is expected */ +#define LPASS_MACRO_FLAG_HAS_NPL_CLOCK BIT(0) + struct lpass_macro { struct device *macro_pd; struct device *dcodec_pd; diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 9e0a4e8a46c3..532b19b1980d 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -3491,7 +3491,10 @@ static int rx_macro_register_mclk_output(struct rx_macro *rx) struct clk_init_data init; int ret; - parent_clk_name = __clk_get_name(rx->npl); + if (rx->npl) + parent_clk_name = __clk_get_name(rx->npl); + else + parent_clk_name = __clk_get_name(rx->mclk); init.name = clk_name; init.ops = &swclk_gate_ops; @@ -3521,10 +3524,13 @@ static const struct snd_soc_component_driver rx_macro_component_drv = { static int rx_macro_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + kernel_ulong_t flags; struct rx_macro *rx; void __iomem *base; int ret; + flags = (kernel_ulong_t)device_get_match_data(dev); + rx = devm_kzalloc(dev, sizeof(*rx), GFP_KERNEL); if (!rx) return -ENOMEM; @@ -3541,9 +3547,11 @@ static int rx_macro_probe(struct platform_device *pdev) if (IS_ERR(rx->mclk)) return PTR_ERR(rx->mclk); - rx->npl = devm_clk_get(dev, "npl"); - if (IS_ERR(rx->npl)) - return PTR_ERR(rx->npl); + if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { + rx->npl = devm_clk_get(dev, "npl"); + if (IS_ERR(rx->npl)) + return PTR_ERR(rx->npl); + } rx->fsgen = devm_clk_get(dev, "fsgen"); if (IS_ERR(rx->fsgen)) @@ -3653,10 +3661,22 @@ static void rx_macro_remove(struct platform_device *pdev) } static const struct of_device_id rx_macro_dt_match[] = { - { .compatible = "qcom,sc7280-lpass-rx-macro" }, - { .compatible = "qcom,sm8250-lpass-rx-macro" }, - { .compatible = "qcom,sm8450-lpass-rx-macro" }, - { .compatible = "qcom,sc8280xp-lpass-rx-macro" }, + { + .compatible = "qcom,sc7280-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + + }, { + .compatible = "qcom,sm8250-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8450-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8550-lpass-rx-macro", + }, { + .compatible = "qcom,sc8280xp-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { } }; MODULE_DEVICE_TABLE(of, rx_macro_dt_match); -- cgit From f03038baacb8e1d8a16556215807ac9ee2dbeada Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 27 Mar 2023 15:22:50 +0200 Subject: ASoC: codecs: lpass-tx-macro: add support for SM8550 Add support for the TX macro codec on Qualcomm SM8550. SM8550 does not use NPL clock, thus add flags allowing to skip it. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230327132254.147975-7-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-tx-macro.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index b044c9c6f89b..ae01e464502c 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -1915,7 +1915,10 @@ static int tx_macro_register_mclk_output(struct tx_macro *tx) struct clk_init_data init; int ret; - parent_clk_name = __clk_get_name(tx->npl); + if (tx->npl) + parent_clk_name = __clk_get_name(tx->npl); + else + parent_clk_name = __clk_get_name(tx->mclk); init.name = clk_name; init.ops = &swclk_gate_ops; @@ -1946,10 +1949,13 @@ static int tx_macro_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + kernel_ulong_t flags; struct tx_macro *tx; void __iomem *base; int ret, reg; + flags = (kernel_ulong_t)device_get_match_data(dev); + tx = devm_kzalloc(dev, sizeof(*tx), GFP_KERNEL); if (!tx) return -ENOMEM; @@ -1966,9 +1972,11 @@ static int tx_macro_probe(struct platform_device *pdev) if (IS_ERR(tx->mclk)) return PTR_ERR(tx->mclk); - tx->npl = devm_clk_get(dev, "npl"); - if (IS_ERR(tx->npl)) - return PTR_ERR(tx->npl); + if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { + tx->npl = devm_clk_get(dev, "npl"); + if (IS_ERR(tx->npl)) + return PTR_ERR(tx->npl); + } tx->fsgen = devm_clk_get(dev, "fsgen"); if (IS_ERR(tx->fsgen)) @@ -2143,10 +2151,21 @@ static const struct dev_pm_ops tx_macro_pm_ops = { }; static const struct of_device_id tx_macro_dt_match[] = { - { .compatible = "qcom,sc7280-lpass-tx-macro" }, - { .compatible = "qcom,sm8250-lpass-tx-macro" }, - { .compatible = "qcom,sm8450-lpass-tx-macro" }, - { .compatible = "qcom,sc8280xp-lpass-tx-macro" }, + { + .compatible = "qcom,sc7280-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8250-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8450-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8550-lpass-tx-macro", + }, { + .compatible = "qcom,sc8280xp-lpass-tx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { } }; MODULE_DEVICE_TABLE(of, tx_macro_dt_match); -- cgit From 63e280a549140d0c162e5b958ddf02840bf35f0f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 27 Mar 2023 15:22:54 +0200 Subject: ASoC: codecs: lpass-wsa-macro: add support for SM8550 Add support for the WSA macro codec on Qualcomm SM8550. SM8550 does not use NPL clock, thus add flags allowing to skip it. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230327132254.147975-11-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-wsa-macro.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 728f26d12ab0..3cbcbfc219b2 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -14,6 +14,8 @@ #include #include #include + +#include "lpass-macro-common.h" #include "lpass-wsa-macro.h" #define CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL (0x0000) @@ -2346,7 +2348,10 @@ static int wsa_macro_register_mclk_output(struct wsa_macro *wsa) struct clk_init_data init; int ret; - parent_clk_name = __clk_get_name(wsa->npl); + if (wsa->npl) + parent_clk_name = __clk_get_name(wsa->npl); + else + parent_clk_name = __clk_get_name(wsa->mclk); init.name = "mclk"; of_property_read_string(dev_of_node(dev), "clock-output-names", @@ -2379,9 +2384,12 @@ static int wsa_macro_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct wsa_macro *wsa; + kernel_ulong_t flags; void __iomem *base; int ret; + flags = (kernel_ulong_t)device_get_match_data(dev); + wsa = devm_kzalloc(dev, sizeof(*wsa), GFP_KERNEL); if (!wsa) return -ENOMEM; @@ -2398,9 +2406,11 @@ static int wsa_macro_probe(struct platform_device *pdev) if (IS_ERR(wsa->mclk)) return PTR_ERR(wsa->mclk); - wsa->npl = devm_clk_get(dev, "npl"); - if (IS_ERR(wsa->npl)) - return PTR_ERR(wsa->npl); + if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { + wsa->npl = devm_clk_get(dev, "npl"); + if (IS_ERR(wsa->npl)) + return PTR_ERR(wsa->npl); + } wsa->fsgen = devm_clk_get(dev, "fsgen"); if (IS_ERR(wsa->fsgen)) @@ -2551,10 +2561,21 @@ static const struct dev_pm_ops wsa_macro_pm_ops = { }; static const struct of_device_id wsa_macro_dt_match[] = { - {.compatible = "qcom,sc7280-lpass-wsa-macro"}, - {.compatible = "qcom,sm8250-lpass-wsa-macro"}, - {.compatible = "qcom,sm8450-lpass-wsa-macro"}, - {.compatible = "qcom,sc8280xp-lpass-wsa-macro" }, + { + .compatible = "qcom,sc7280-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8250-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8450-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,sm8550-lpass-wsa-macro", + }, { + .compatible = "qcom,sc8280xp-lpass-wsa-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, {} }; MODULE_DEVICE_TABLE(of, wsa_macro_dt_match); -- cgit From e3720f92e0237921da537e47a0b24e27899203f8 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 29 Mar 2023 14:38:28 +0300 Subject: ASoC: SOF: avoid a NULL dereference with unsupported widgets If an IPC4 topology contains an unsupported widget, its .module_info field won't be set, then sof_ipc4_route_setup() will cause a kernel Oops trying to dereference it. Add a check for such cases. Cc: stable@vger.kernel.org # 6.2 Signed-off-by: Guennadi Liakhovetski Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230329113828.28562-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index a623707c8ffc..669b99a4f76e 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1805,6 +1805,14 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * u32 header, extension; int ret; + if (!src_fw_module || !sink_fw_module) { + /* The NULL module will print as "(efault)" */ + dev_err(sdev->dev, "source %s or sink %s widget weren't set up properly\n", + src_fw_module->man4_module_entry.name, + sink_fw_module->man4_module_entry.name); + return -ENODEV; + } + sroute->src_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget, SOF_PIN_TYPE_SOURCE); if (sroute->src_queue_id < 0) { -- cgit From 892855d57c47c32f475e9efa36c1a3452cc19918 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:43:56 +0800 Subject: ASoC: codecs: cs42l42-sdw: clear stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The API requires the stream info to be cleared when the argument is NULL. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42-sdw.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs42l42-sdw.c b/sound/soc/codecs/cs42l42-sdw.c index 7b539ee55499..eeab07c850f9 100644 --- a/sound/soc/codecs/cs42l42-sdw.c +++ b/sound/soc/codecs/cs42l42-sdw.c @@ -152,9 +152,6 @@ static int cs42l42_sdw_port_prep(struct sdw_slave *slave, static int cs42l42_sdw_dai_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - if (!sdw_stream) - return 0; - snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; -- cgit From f3def177876450df07fab6f28ad24a70397dc94d Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:43:57 +0800 Subject: ASoC: codecs: sdw-mockup: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/sdw-mockup.c | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/sdw-mockup.c b/sound/soc/codecs/sdw-mockup.c index 62b02d764f09..5498ff027c58 100644 --- a/sound/soc/codecs/sdw-mockup.c +++ b/sound/soc/codecs/sdw-mockup.c @@ -23,10 +23,6 @@ struct sdw_mockup_priv { struct sdw_slave *slave; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - static int sdw_mockup_component_probe(struct snd_soc_component *component) { return 0; @@ -45,19 +41,7 @@ static const struct snd_soc_component_driver snd_soc_sdw_mockup_component = { static int sdw_mockup_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -65,11 +49,7 @@ static int sdw_mockup_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void sdw_mockup_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int sdw_mockup_pcm_hw_params(struct snd_pcm_substream *substream, @@ -80,11 +60,10 @@ static int sdw_mockup_pcm_hw_params(struct snd_pcm_substream *substream, struct sdw_mockup_priv *sdw_mockup = snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); int ret; - stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!sdw_mockup->slave) @@ -99,7 +78,7 @@ static int sdw_mockup_pcm_hw_params(struct snd_pcm_substream *substream, port_config.num = 8; ret = sdw_stream_add_slave(sdw_mockup->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (ret) dev_err(dai->dev, "Unable to configure port\n"); @@ -111,13 +90,12 @@ static int sdw_mockup_pcm_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct sdw_mockup_priv *sdw_mockup = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = - snd_soc_dai_get_dma_data(dai, substream); + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!sdw_mockup->slave) return -EINVAL; - sdw_stream_remove_slave(sdw_mockup->slave, stream->sdw_stream); + sdw_stream_remove_slave(sdw_mockup->slave, sdw_stream); return 0; } -- cgit From 658d6f7381b1be5a6fec7d90c865fb593b8c78b6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:43:58 +0800 Subject: ASoC: codecs: max98373-sdw: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-4-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98373-sdw.c | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index c9a2d4dabd3c..df92242af960 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -20,10 +20,6 @@ #include "max98373.h" #include "max98373-sdw.h" -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - static const u32 max98373_sdw_cache_reg[] = { MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, @@ -536,12 +532,12 @@ static int max98373_sdw_dai_hw_params(struct snd_pcm_substream *substream, snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int ret, chan_sz, sampling_rate; - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!max98373->slave) @@ -565,7 +561,7 @@ static int max98373_sdw_dai_hw_params(struct snd_pcm_substream *substream, } ret = sdw_stream_add_slave(max98373->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (ret) { dev_err(dai->dev, "Unable to configure port\n"); return ret; @@ -664,32 +660,20 @@ static int max98373_pcm_hw_free(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!max98373->slave) return -EINVAL; - sdw_stream_remove_slave(max98373->slave, stream->sdw_stream); + sdw_stream_remove_slave(max98373->slave, sdw_stream); return 0; } static int max98373_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -697,11 +681,7 @@ static int max98373_set_sdw_stream(struct snd_soc_dai *dai, static void max98373_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int max98373_sdw_set_tdm_slot(struct snd_soc_dai *dai, -- cgit From ce8ffc1bac7bee5015eb68faf214b39fcbd65d15 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:43:59 +0800 Subject: ASoC: codecs: rt1308-sdw: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-5-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308-sdw.c | 30 +++++++----------------------- sound/soc/codecs/rt1308-sdw.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index 45544b530d3d..1797af824f60 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -496,19 +496,7 @@ static const struct snd_soc_dapm_route rt1308_dapm_routes[] = { static int rt1308_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -516,11 +504,7 @@ static int rt1308_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt1308_sdw_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt1308_sdw_set_tdm_slot(struct snd_soc_dai *dai, @@ -553,13 +537,13 @@ static int rt1308_sdw_hw_params(struct snd_pcm_substream *substream, snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt1308->sdw_slave) @@ -580,7 +564,7 @@ static int rt1308_sdw_hw_params(struct snd_pcm_substream *substream, } retval = sdw_stream_add_slave(rt1308->sdw_slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -595,13 +579,13 @@ static int rt1308_sdw_pcm_hw_free(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct rt1308_sdw_priv *rt1308 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt1308->sdw_slave) return -EINVAL; - sdw_stream_remove_slave(rt1308->sdw_slave, stream->sdw_stream); + sdw_stream_remove_slave(rt1308->sdw_slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt1308-sdw.h b/sound/soc/codecs/rt1308-sdw.h index 1eaaef9f351b..04ff18fa18e2 100644 --- a/sound/soc/codecs/rt1308-sdw.h +++ b/sound/soc/codecs/rt1308-sdw.h @@ -170,8 +170,4 @@ struct rt1308_sdw_priv { unsigned int bq_params_cnt; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - #endif /* __RT1308_SDW_H__ */ -- cgit From 1294d7d71f6abad6299a12cf6911f8e5622c7865 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:00 +0800 Subject: ASoC: codecs: rt1316-sdw: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-6-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1316-sdw.c | 30 +++++++----------------------- sound/soc/codecs/rt1316-sdw.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c index b45121ee7533..2ee5e763e345 100644 --- a/sound/soc/codecs/rt1316-sdw.c +++ b/sound/soc/codecs/rt1316-sdw.c @@ -494,19 +494,7 @@ static const struct snd_soc_dapm_route rt1316_dapm_routes[] = { static int rt1316_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -514,11 +502,7 @@ static int rt1316_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt1316_sdw_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt1316_sdw_hw_params(struct snd_pcm_substream *substream, @@ -529,13 +513,13 @@ static int rt1316_sdw_hw_params(struct snd_pcm_substream *substream, snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt1316->sdw_slave) @@ -551,7 +535,7 @@ static int rt1316_sdw_hw_params(struct snd_pcm_substream *substream, port_config.num = 2; retval = sdw_stream_add_slave(rt1316->sdw_slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -566,13 +550,13 @@ static int rt1316_sdw_pcm_hw_free(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct rt1316_sdw_priv *rt1316 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt1316->sdw_slave) return -EINVAL; - sdw_stream_remove_slave(rt1316->sdw_slave, stream->sdw_stream); + sdw_stream_remove_slave(rt1316->sdw_slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt1316-sdw.h b/sound/soc/codecs/rt1316-sdw.h index 57dbd49993b0..e37121655bc1 100644 --- a/sound/soc/codecs/rt1316-sdw.h +++ b/sound/soc/codecs/rt1316-sdw.h @@ -50,8 +50,4 @@ struct rt1316_sdw_priv { unsigned int bq_params_cnt; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - #endif /* __RT1316_SDW_H__ */ -- cgit From be8e5a850eb1780bae360b9b48b6d2ab70e5fb03 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:01 +0800 Subject: ASoC: codecs: rt1318-sdw: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-7-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1318-sdw.c | 30 +++++++----------------------- sound/soc/codecs/rt1318-sdw.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt1318-sdw.c b/sound/soc/codecs/rt1318-sdw.c index c32d8ae77981..795accedc22c 100644 --- a/sound/soc/codecs/rt1318-sdw.c +++ b/sound/soc/codecs/rt1318-sdw.c @@ -562,19 +562,7 @@ static const struct snd_soc_dapm_route rt1318_dapm_routes[] = { static int rt1318_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -582,11 +570,7 @@ static int rt1318_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt1318_sdw_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt1318_sdw_hw_params(struct snd_pcm_substream *substream, @@ -598,14 +582,14 @@ static int rt1318_sdw_hw_params(struct snd_pcm_substream *substream, struct sdw_stream_config stream_config; struct sdw_port_config port_config; enum sdw_data_direction direction; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval, port, num_channels, ch_mask; unsigned int sampling_rate; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt1318->sdw_slave) @@ -633,7 +617,7 @@ static int rt1318_sdw_hw_params(struct snd_pcm_substream *substream, port_config.num = port; retval = sdw_stream_add_slave(rt1318->sdw_slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -679,13 +663,13 @@ static int rt1318_sdw_pcm_hw_free(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct rt1318_sdw_priv *rt1318 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt1318->sdw_slave) return -EINVAL; - sdw_stream_remove_slave(rt1318->sdw_slave, stream->sdw_stream); + sdw_stream_remove_slave(rt1318->sdw_slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt1318-sdw.h b/sound/soc/codecs/rt1318-sdw.h index 4d7ac9c4bd8d..85918c184f16 100644 --- a/sound/soc/codecs/rt1318-sdw.h +++ b/sound/soc/codecs/rt1318-sdw.h @@ -94,8 +94,4 @@ struct rt1318_sdw_priv { bool first_hw_init; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - #endif /* __RT1318_SDW_H__ */ -- cgit From 3bcced019eb266e91b7eecc1f8fd3da5f55ca4cd Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:02 +0800 Subject: ASoC: codecs: rt700-sdw: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-8-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt700.c | 30 +++++++----------------------- sound/soc/codecs/rt700.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c index 659ce26e9f3b..a04b9246256b 100644 --- a/sound/soc/codecs/rt700.c +++ b/sound/soc/codecs/rt700.c @@ -875,19 +875,7 @@ static const struct snd_soc_component_driver soc_codec_dev_rt700 = { static int rt700_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -895,11 +883,7 @@ static int rt700_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt700_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt700_pcm_hw_params(struct snd_pcm_substream *substream, @@ -910,14 +894,14 @@ static int rt700_pcm_hw_params(struct snd_pcm_substream *substream, struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; unsigned int val = 0; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt700->slave) @@ -944,7 +928,7 @@ static int rt700_pcm_hw_params(struct snd_pcm_substream *substream, } retval = sdw_stream_add_slave(rt700->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -991,13 +975,13 @@ static int rt700_pcm_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt700->slave) return -EINVAL; - sdw_stream_remove_slave(rt700->slave, stream->sdw_stream); + sdw_stream_remove_slave(rt700->slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt700.h b/sound/soc/codecs/rt700.h index bed9d1de6d5b..93c44005d38c 100644 --- a/sound/soc/codecs/rt700.h +++ b/sound/soc/codecs/rt700.h @@ -27,10 +27,6 @@ struct rt700_priv { bool disable_irq; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - /* NID */ #define RT700_AUDIO_FUNCTION_GROUP 0x01 #define RT700_DAC_OUT1 0x02 -- cgit From fa55b31fb65347ceab617af7541f0a31b53901f1 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:03 +0800 Subject: ASoC: codecs: rt711-sdw: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-9-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt711.c | 30 +++++++----------------------- sound/soc/codecs/rt711.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 862f50950565..af53cbcc7bf2 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -964,19 +964,7 @@ static const struct snd_soc_component_driver soc_codec_dev_rt711 = { static int rt711_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -984,11 +972,7 @@ static int rt711_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt711_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt711_pcm_hw_params(struct snd_pcm_substream *substream, @@ -999,14 +983,14 @@ static int rt711_pcm_hw_params(struct snd_pcm_substream *substream, struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; unsigned int val = 0; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt711->slave) @@ -1027,7 +1011,7 @@ static int rt711_pcm_hw_params(struct snd_pcm_substream *substream, } retval = sdw_stream_add_slave(rt711->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -1075,13 +1059,13 @@ static int rt711_pcm_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt711->slave) return -EINVAL; - sdw_stream_remove_slave(rt711->slave, stream->sdw_stream); + sdw_stream_remove_slave(rt711->slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt711.h b/sound/soc/codecs/rt711.h index f50f8c8d0934..b31351f11df9 100644 --- a/sound/soc/codecs/rt711.h +++ b/sound/soc/codecs/rt711.h @@ -29,10 +29,6 @@ struct rt711_priv { bool disable_irq; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - /* NID */ #define RT711_AUDIO_FUNCTION_GROUP 0x01 #define RT711_DAC_OUT2 0x03 -- cgit From b2790eccc0bc755d37ed5cd8d225cec0d72798c8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:04 +0800 Subject: ASoC: codecs: rt711-sdca: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-10-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt711-sdca.c | 30 +++++++----------------------- sound/soc/codecs/rt711-sdca.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index c65abe812a4c..07640d2f6e56 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -1237,19 +1237,7 @@ static const struct snd_soc_component_driver soc_sdca_dev_rt711 = { static int rt711_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -1257,11 +1245,7 @@ static int rt711_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt711_sdca_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt711_sdca_pcm_hw_params(struct snd_pcm_substream *substream, @@ -1272,14 +1256,14 @@ static int rt711_sdca_pcm_hw_params(struct snd_pcm_substream *substream, struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; unsigned int sampling_rate; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt711->slave) @@ -1300,7 +1284,7 @@ static int rt711_sdca_pcm_hw_params(struct snd_pcm_substream *substream, } retval = sdw_stream_add_slave(rt711->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -1351,13 +1335,13 @@ static int rt711_sdca_pcm_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt711->slave) return -EINVAL; - sdw_stream_remove_slave(rt711->slave, stream->sdw_stream); + sdw_stream_remove_slave(rt711->slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt711-sdca.h b/sound/soc/codecs/rt711-sdca.h index 10e3c801b813..22076f268577 100644 --- a/sound/soc/codecs/rt711-sdca.h +++ b/sound/soc/codecs/rt711-sdca.h @@ -36,10 +36,6 @@ struct rt711_sdca_priv { bool fu1e_dapm_mute, fu1e_mixer_l_mute, fu1e_mixer_r_mute; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - /* NID */ #define RT711_AUDIO_FUNCTION_GROUP 0x01 #define RT711_DAC_OUT2 0x03 -- cgit From 278432084b093f7257cf96c75bb33f155e4a8232 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:05 +0800 Subject: ASoC: codecs: rt712-sdca: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-11-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt712-sdca.c | 30 +++++++----------------------- sound/soc/codecs/rt712-sdca.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt712-sdca.c b/sound/soc/codecs/rt712-sdca.c index 8d2fa769bb2e..89d245655ca4 100644 --- a/sound/soc/codecs/rt712-sdca.c +++ b/sound/soc/codecs/rt712-sdca.c @@ -992,19 +992,7 @@ static const struct snd_soc_component_driver soc_sdca_dev_rt712 = { static int rt712_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -1012,11 +1000,7 @@ static int rt712_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt712_sdca_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream, @@ -1028,14 +1012,14 @@ static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream, struct sdw_stream_config stream_config; struct sdw_port_config port_config; enum sdw_data_direction direction; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval, port, num_channels; unsigned int sampling_rate; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt712->slave) @@ -1068,7 +1052,7 @@ static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream, port_config.num = port; retval = sdw_stream_add_slave(rt712->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -1128,13 +1112,13 @@ static int rt712_sdca_pcm_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt712->slave) return -EINVAL; - sdw_stream_remove_slave(rt712->slave, stream->sdw_stream); + sdw_stream_remove_slave(rt712->slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt712-sdca.h b/sound/soc/codecs/rt712-sdca.h index cf647162f9da..c6a94a23f46e 100644 --- a/sound/soc/codecs/rt712-sdca.h +++ b/sound/soc/codecs/rt712-sdca.h @@ -40,10 +40,6 @@ struct rt712_sdca_priv { bool fu0f_mixer_r_mute; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - /* NID */ #define RT712_VENDOR_REG 0x20 #define RT712_VENDOR_CALI 0x58 -- cgit From e506b2bd1d2e9daaedd1db2ef9868f7b8c4c86c3 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:06 +0800 Subject: ASoC: codecs: rt715: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-12-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt715.c | 30 +++++++----------------------- sound/soc/codecs/rt715.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt715.c b/sound/soc/codecs/rt715.c index c6dd9df7be45..6c2e165dd621 100644 --- a/sound/soc/codecs/rt715.c +++ b/sound/soc/codecs/rt715.c @@ -765,19 +765,7 @@ static int rt715_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -786,11 +774,7 @@ static void rt715_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt715_pcm_hw_params(struct snd_pcm_substream *substream, @@ -801,13 +785,13 @@ static int rt715_pcm_hw_params(struct snd_pcm_substream *substream, struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; unsigned int val = 0; - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt715->slave) @@ -830,7 +814,7 @@ static int rt715_pcm_hw_params(struct snd_pcm_substream *substream, } retval = sdw_stream_add_slave(rt715->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -893,13 +877,13 @@ static int rt715_pcm_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt715->slave) return -EINVAL; - sdw_stream_remove_slave(rt715->slave, stream->sdw_stream); + sdw_stream_remove_slave(rt715->slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt715.h b/sound/soc/codecs/rt715.h index 25dba61f1760..17a8d041c1c3 100644 --- a/sound/soc/codecs/rt715.h +++ b/sound/soc/codecs/rt715.h @@ -27,10 +27,6 @@ struct rt715_priv { unsigned int kctl_8ch_vol_ori[8]; }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - /* NID */ #define RT715_AUDIO_FUNCTION_GROUP 0x01 #define RT715_MIC_ADC 0x07 -- cgit From cf1d6a3ad07c982a09455bf8720dc75754909932 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:07 +0800 Subject: ASoC: codecs: rt715-sdca: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-13-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt715-sdca.c | 30 +++++++----------------------- sound/soc/codecs/rt715-sdca.h | 4 ---- 2 files changed, 7 insertions(+), 27 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt715-sdca.c b/sound/soc/codecs/rt715-sdca.c index 920510365fd7..b989f907784b 100644 --- a/sound/soc/codecs/rt715-sdca.c +++ b/sound/soc/codecs/rt715-sdca.c @@ -784,16 +784,7 @@ static const struct snd_soc_component_driver soc_codec_dev_rt715_sdca = { static int rt715_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct rt715_sdw_stream_data *stream; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -802,14 +793,7 @@ static void rt715_sdca_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct rt715_sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) - return; - snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt715_sdca_pcm_hw_params(struct snd_pcm_substream *substream, @@ -820,13 +804,13 @@ static int rt715_sdca_pcm_hw_params(struct snd_pcm_substream *substream, struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct rt715_sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; unsigned int val; - stream = snd_soc_dai_get_dma_data(dai, substream); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + if (!sdw_stream) return -EINVAL; if (!rt715->slave) @@ -851,7 +835,7 @@ static int rt715_sdca_pcm_hw_params(struct snd_pcm_substream *substream, } retval = sdw_stream_add_slave(rt715->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(component->dev, "Unable to configure port, retval:%d\n", retval); @@ -922,13 +906,13 @@ static int rt715_sdca_pcm_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); - struct rt715_sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt715->slave) return -EINVAL; - sdw_stream_remove_slave(rt715->slave, stream->sdw_stream); + sdw_stream_remove_slave(rt715->slave, sdw_stream); return 0; } diff --git a/sound/soc/codecs/rt715-sdca.h b/sound/soc/codecs/rt715-sdca.h index 90881b455ece..7577f3151934 100644 --- a/sound/soc/codecs/rt715-sdca.h +++ b/sound/soc/codecs/rt715-sdca.h @@ -37,10 +37,6 @@ struct rt715_sdca_priv { int kctl_8ch_orig[8]; }; -struct rt715_sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - struct rt715_sdca_kcontrol_private { unsigned int reg_base; unsigned int count; -- cgit From b3a2e00e20671091f7175f8f36b7f9c9ea2e77bb Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 24 Mar 2023 09:44:08 +0800 Subject: ASoC: codecs: rt5682-sdw: simplify set_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a dynamic allocation to store a single pointer is not very efficient/useful. Worse, the memory is released in the SoundWire stream.c file, but still accessed in the DAI shutdown, leading to kmemleak reports. And last the API requires the previous stream information to be cleared when the argument is NULL. Simplify the code to address all 3 problems. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20230324014408.1677505-14-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682-sdw.c | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 5f80a5d59b65..23f17f70d7e9 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -88,26 +88,10 @@ static const struct regmap_config rt5682_sdw_indirect_regmap = { .reg_write = rt5682_sdw_write, }; -struct sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction) { - struct sdw_stream_data *stream; - - if (!sdw_stream) - return 0; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - snd_soc_dai_dma_data_set(dai, direction, stream); + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); return 0; } @@ -115,11 +99,7 @@ static int rt5682_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, static void rt5682_sdw_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); } static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream, @@ -130,14 +110,14 @@ static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream, struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); struct sdw_stream_config stream_config = {0}; struct sdw_port_config port_config = {0}; - struct sdw_stream_data *stream; + struct sdw_stream_runtime *sdw_stream; int retval; unsigned int val_p = 0, val_c = 0, osr_p = 0, osr_c = 0; dev_dbg(dai->dev, "%s %s", __func__, dai->name); - stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); + if (!sdw_stream) return -ENOMEM; if (!rt5682->slave) @@ -152,7 +132,7 @@ static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream, port_config.num = 2; retval = sdw_stream_add_slave(rt5682->slave, &stream_config, - &port_config, 1, stream->sdw_stream); + &port_config, 1, sdw_stream); if (retval) { dev_err(dai->dev, "Unable to configure port\n"); return retval; @@ -246,13 +226,13 @@ static int rt5682_sdw_hw_free(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); - struct sdw_stream_data *stream = + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); if (!rt5682->slave) return -EINVAL; - sdw_stream_remove_slave(rt5682->slave, stream->sdw_stream); + sdw_stream_remove_slave(rt5682->slave, sdw_stream); return 0; } -- cgit From 6a7c51b4d91b5d73aae2647356990573643b2ae4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 29 Mar 2023 00:21:03 +0000 Subject: ASoC: soc-topology.c: dai_link->platform again On SOF, many topology is assuming dai_link->platform exists, and is allowed to be overwritten on each link_load(). This patch restore the removed dai_link->platform for SOF, and add the comment. Fixes: e7098ba9b378 ("ASoC: soc-topology.c: remove unnecessary dai_link->platform") Reported-by: Peter Ujfalusi Link: https://lore.kernel.org/r/87jzz7jczp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto Tested-by: Peter Ujfalusi Link: https://lore.kernel.org/r/87v8ikcsr5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index be9849749713..d0aca6b9058b 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1685,8 +1685,8 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, struct snd_soc_dai_link_component *dlc; int ret; - /* link + cpu + codec */ - link = devm_kzalloc(tplg->dev, sizeof(*link) + (2 * sizeof(*dlc)), GFP_KERNEL); + /* link + cpu + codec + platform */ + link = devm_kzalloc(tplg->dev, sizeof(*link) + (3 * sizeof(*dlc)), GFP_KERNEL); if (link == NULL) return -ENOMEM; @@ -1724,6 +1724,14 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->codecs->name = "snd-soc-dummy"; link->codecs->dai_name = "snd-soc-dummy-dai"; + /* + * Many topology is assuming link has Platform. + * This might be overwritten at soc_tplg_dai_link_load(). + */ + link->platforms = &dlc[2]; + link->platforms->name = "snd-soc-dummy"; + link->num_platforms = 1; + /* enable DPCM */ link->dynamic = 1; link->ignore_pmdown_time = 1; -- cgit From 24e9e57f581dd3e90c4b63f066dab96c6ba4e05f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 24 Mar 2023 16:33:28 +0000 Subject: ASoC: dapm: Sort speakers after other outputs Currently we sequence speakers with line and headphone outputs in DAPM. This works well when speakers are integrate into a CODEC but when there is an external speaker driver connected to a line or headphone output it can mean that the speaker driver ends up getting sequenced such that it picks up pops and clicks from the CODEC. Mask this by moving speakers after the other outputs in DAPM. We may want to consider doing this for headphones too but separate drivers are less common there and headphone drivers often also function as line outputs so the situation is less clear. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20230324-asoc-dapm-spk-v1-1-e1f27f766505@kernel.org Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 74 ++++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 5d9a671e50f1..34fdcb7ee079 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -99,52 +99,52 @@ static int dapm_up_seq[] = { [snd_soc_dapm_adc] = 11, [snd_soc_dapm_out_drv] = 12, [snd_soc_dapm_hp] = 12, - [snd_soc_dapm_spk] = 12, [snd_soc_dapm_line] = 12, [snd_soc_dapm_sink] = 12, - [snd_soc_dapm_kcontrol] = 13, - [snd_soc_dapm_post] = 14, + [snd_soc_dapm_spk] = 13, + [snd_soc_dapm_kcontrol] = 14, + [snd_soc_dapm_post] = 15, }; static int dapm_down_seq[] = { [snd_soc_dapm_pre] = 1, [snd_soc_dapm_kcontrol] = 2, [snd_soc_dapm_adc] = 3, - [snd_soc_dapm_hp] = 4, [snd_soc_dapm_spk] = 4, - [snd_soc_dapm_line] = 4, - [snd_soc_dapm_out_drv] = 4, - [snd_soc_dapm_sink] = 4, - [snd_soc_dapm_pga] = 5, - [snd_soc_dapm_buffer] = 5, - [snd_soc_dapm_scheduler] = 5, - [snd_soc_dapm_effect] = 5, - [snd_soc_dapm_src] = 5, - [snd_soc_dapm_asrc] = 5, - [snd_soc_dapm_encoder] = 5, - [snd_soc_dapm_decoder] = 5, - [snd_soc_dapm_switch] = 6, - [snd_soc_dapm_mixer_named_ctl] = 6, - [snd_soc_dapm_mixer] = 6, - [snd_soc_dapm_dac] = 7, - [snd_soc_dapm_mic] = 8, - [snd_soc_dapm_siggen] = 8, - [snd_soc_dapm_input] = 8, - [snd_soc_dapm_output] = 8, - [snd_soc_dapm_micbias] = 9, - [snd_soc_dapm_vmid] = 9, - [snd_soc_dapm_mux] = 10, - [snd_soc_dapm_demux] = 10, - [snd_soc_dapm_aif_in] = 11, - [snd_soc_dapm_aif_out] = 11, - [snd_soc_dapm_dai_in] = 11, - [snd_soc_dapm_dai_out] = 11, - [snd_soc_dapm_dai_link] = 12, - [snd_soc_dapm_supply] = 13, - [snd_soc_dapm_clock_supply] = 14, - [snd_soc_dapm_pinctrl] = 14, - [snd_soc_dapm_regulator_supply] = 14, - [snd_soc_dapm_post] = 15, + [snd_soc_dapm_hp] = 5, + [snd_soc_dapm_line] = 5, + [snd_soc_dapm_out_drv] = 5, + [snd_soc_dapm_sink] = 6, + [snd_soc_dapm_pga] = 6, + [snd_soc_dapm_buffer] = 6, + [snd_soc_dapm_scheduler] = 6, + [snd_soc_dapm_effect] = 6, + [snd_soc_dapm_src] = 6, + [snd_soc_dapm_asrc] = 6, + [snd_soc_dapm_encoder] = 6, + [snd_soc_dapm_decoder] = 6, + [snd_soc_dapm_switch] = 7, + [snd_soc_dapm_mixer_named_ctl] = 7, + [snd_soc_dapm_mixer] = 7, + [snd_soc_dapm_dac] = 8, + [snd_soc_dapm_mic] = 9, + [snd_soc_dapm_siggen] = 9, + [snd_soc_dapm_input] = 9, + [snd_soc_dapm_output] = 9, + [snd_soc_dapm_micbias] = 10, + [snd_soc_dapm_vmid] = 10, + [snd_soc_dapm_mux] = 11, + [snd_soc_dapm_demux] = 11, + [snd_soc_dapm_aif_in] = 12, + [snd_soc_dapm_aif_out] = 12, + [snd_soc_dapm_dai_in] = 12, + [snd_soc_dapm_dai_out] = 12, + [snd_soc_dapm_dai_link] = 13, + [snd_soc_dapm_supply] = 14, + [snd_soc_dapm_clock_supply] = 15, + [snd_soc_dapm_pinctrl] = 15, + [snd_soc_dapm_regulator_supply] = 15, + [snd_soc_dapm_post] = 16, }; static void dapm_assert_locked(struct snd_soc_dapm_context *dapm) -- cgit From 18c0af945fa35766730d3f729adcf417a3d1ad5d Mon Sep 17 00:00:00 2001 From: Ryan Lee Date: Thu, 30 Mar 2023 16:43:18 -0700 Subject: ASoC: max98363: add soundwire amplifier driver Added Analog Devices MAX98363 SoundWire Amplifier Driver. The MAX98363 is a SoundWire peripheral device that supports MIPI SoundWire v1.2-compatible digital interface for audio and control data. Signed-off-by: Ryan Lee Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20230330234319.6841-1-ryan.lee.analog@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 11 ++ sound/soc/codecs/Makefile | 2 + sound/soc/codecs/max98363.c | 464 ++++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/max98363.h | 36 ++++ 4 files changed, 513 insertions(+) create mode 100644 sound/soc/codecs/max98363.c create mode 100644 sound/soc/codecs/max98363.h (limited to 'sound') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 03630d13d35f..4062fe3fbb1c 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -133,6 +133,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_MAX98925 imply SND_SOC_MAX98926 imply SND_SOC_MAX98927 + imply SND_SOC_MAX98363 imply SND_SOC_MAX98373_I2C imply SND_SOC_MAX98373_SDW imply SND_SOC_MAX98390 @@ -1133,6 +1134,16 @@ config SND_SOC_MAX98520 To compile this driver as a module, choose M here. +config SND_SOC_MAX98363 + tristate "Analog Devices MAX98363 Soundwire Speaker Amplifier" + depends on SOUNDWIRE + select REGMAP_SOUNDWIRE + help + Enable support for Analog Devices MAX98363 Soundwire + amplifier. MAX98363 supports the MIPI SoundWire v1.2 + compatible interface for audio and control data. + This amplifier does not support I2C and I2S. + config SND_SOC_MAX98373 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 25ebce58a0ba..44ea747579fd 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -148,6 +148,7 @@ snd-soc-max98925-objs := max98925.o snd-soc-max98926-objs := max98926.o snd-soc-max98927-objs := max98927.o snd-soc-max98520-objs := max98520.o +snd-soc-max98363-objs := max98363.o snd-soc-max98373-objs := max98373.o snd-soc-max98373-i2c-objs := max98373-i2c.o snd-soc-max98373-sdw-objs := max98373-sdw.o @@ -515,6 +516,7 @@ obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o obj-$(CONFIG_SND_SOC_MAX98520) += snd-soc-max98520.o +obj-$(CONFIG_SND_SOC_MAX98363) += snd-soc-max98363.o obj-$(CONFIG_SND_SOC_MAX98373) += snd-soc-max98373.o obj-$(CONFIG_SND_SOC_MAX98373_I2C) += snd-soc-max98373-i2c.o obj-$(CONFIG_SND_SOC_MAX98373_SDW) += snd-soc-max98373-sdw.o diff --git a/sound/soc/codecs/max98363.c b/sound/soc/codecs/max98363.c new file mode 100644 index 000000000000..4585ebb1e82c --- /dev/null +++ b/sound/soc/codecs/max98363.c @@ -0,0 +1,464 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2022, Analog Devices Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "max98363.h" + +static struct reg_default max98363_reg[] = { + {MAX98363_R2001_INTR_RAW, 0x0}, + {MAX98363_R2003_INTR_STATE, 0x0}, + {MAX98363_R2005_INTR_FALG, 0x0}, + {MAX98363_R2007_INTR_EN, 0x0}, + {MAX98363_R2009_INTR_CLR, 0x0}, + {MAX98363_R2021_ERR_MON_CTRL, 0x0}, + {MAX98363_R2022_SPK_MON_THRESH, 0x0}, + {MAX98363_R2023_SPK_MON_DURATION, 0x0}, + {MAX98363_R2030_TONE_GEN_CFG, 0x0}, + {MAX98363_R203F_TONE_GEN_EN, 0x0}, + {MAX98363_R2040_AMP_VOL, 0x0}, + {MAX98363_R2041_AMP_GAIN, 0x5}, + {MAX98363_R2042_DSP_CFG, 0x0}, + {MAX98363_R21FF_REV_ID, 0x0}, +}; + +static bool max98363_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98363_R2001_INTR_RAW: + case MAX98363_R2003_INTR_STATE: + case MAX98363_R2005_INTR_FALG: + case MAX98363_R2007_INTR_EN: + case MAX98363_R2009_INTR_CLR: + case MAX98363_R2021_ERR_MON_CTRL ... MAX98363_R2023_SPK_MON_DURATION: + case MAX98363_R2030_TONE_GEN_CFG: + case MAX98363_R203F_TONE_GEN_EN: + case MAX98363_R2040_AMP_VOL: + case MAX98363_R2041_AMP_GAIN: + case MAX98363_R2042_DSP_CFG: + case MAX98363_R21FF_REV_ID: + return true; + default: + return false; + } +}; + +static bool max98363_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98363_R2001_INTR_RAW: + case MAX98363_R2003_INTR_STATE: + case MAX98363_R2005_INTR_FALG: + case MAX98363_R2007_INTR_EN: + case MAX98363_R2009_INTR_CLR: + case MAX98363_R21FF_REV_ID: + return true; + default: + return false; + } +} + +static const struct regmap_config max98363_sdw_regmap = { + .reg_bits = 32, + .val_bits = 8, + .max_register = MAX98363_R21FF_REV_ID, + .reg_defaults = max98363_reg, + .num_reg_defaults = ARRAY_SIZE(max98363_reg), + .readable_reg = max98363_readable_register, + .volatile_reg = max98363_volatile_reg, + .cache_type = REGCACHE_RBTREE, + .use_single_read = true, + .use_single_write = true, +}; + +static int max98363_suspend(struct device *dev) +{ + struct max98363_priv *max98363 = dev_get_drvdata(dev); + + regcache_cache_only(max98363->regmap, true); + regcache_mark_dirty(max98363->regmap); + + return 0; +} + +#define MAX98363_PROBE_TIMEOUT 5000 + +static int max98363_resume(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct max98363_priv *max98363 = dev_get_drvdata(dev); + unsigned long time; + + if (!max98363->first_hw_init) + return 0; + + if (!slave->unattach_request) + goto regmap_sync; + + time = wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(MAX98363_PROBE_TIMEOUT)); + if (!time) { + dev_err(dev, "Initialization not complete, timed out\n"); + return -ETIMEDOUT; + } + +regmap_sync: + + slave->unattach_request = 0; + regcache_cache_only(max98363->regmap, false); + regcache_sync(max98363->regmap); + + return 0; +} + +static DEFINE_RUNTIME_DEV_PM_OPS(max98363_pm, max98363_suspend, max98363_resume, NULL); + +static int max98363_read_prop(struct sdw_slave *slave) +{ + struct sdw_slave_prop *prop = &slave->prop; + int nval, i; + u32 bit; + unsigned long addr; + struct sdw_dpn_prop *dpn; + + prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + + /* BITMAP: 00000010 Dataport 1 is active */ + prop->sink_ports = BIT(1); + prop->paging_support = true; + prop->clk_stop_timeout = 20; + prop->simple_clk_stop_capable = true; + prop->clock_reg_supported = true; + + nval = hweight32(prop->sink_ports); + prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->sink_dpn_prop), + GFP_KERNEL); + if (!prop->sink_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->sink_dpn_prop; + addr = prop->sink_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + dpn[i].ch_prep_timeout = 10; + i++; + } + + return 0; +} + +static int max98363_io_init(struct sdw_slave *slave) +{ + struct device *dev = &slave->dev; + struct max98363_priv *max98363 = dev_get_drvdata(dev); + int ret, reg; + + if (max98363->first_hw_init) { + regcache_cache_only(max98363->regmap, false); + regcache_cache_bypass(max98363->regmap, true); + } + + /* + * PM runtime is only enabled when a Slave reports as Attached + */ + if (!max98363->first_hw_init) { + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(dev, 3000); + pm_runtime_use_autosuspend(dev); + + /* update count of parent 'active' children */ + pm_runtime_set_active(dev); + + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(dev); + + pm_runtime_enable(dev); + } + + pm_runtime_get_noresume(dev); + + ret = regmap_read(max98363->regmap, MAX98363_R21FF_REV_ID, ®); + if (!ret) { + dev_info(dev, "Revision ID: %X\n", reg); + return ret; + } + + if (max98363->first_hw_init) { + regcache_cache_bypass(max98363->regmap, false); + regcache_mark_dirty(max98363->regmap); + } + + max98363->first_hw_init = true; + max98363->hw_init = true; + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return 0; +} + +#define MAX98363_RATES SNDRV_PCM_RATE_8000_192000 +#define MAX98363_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) + +static int max98363_sdw_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct max98363_priv *max98363 = + snd_soc_component_get_drvdata(component); + + struct sdw_stream_config stream_config; + struct sdw_port_config port_config; + enum sdw_data_direction direction; + struct sdw_stream_runtime *stream; + struct snd_pcm_runtime *runtime = substream->runtime; + + int ret; + + stream = snd_soc_dai_get_dma_data(dai, substream); + + if (!stream) + return -EINVAL; + + if (!max98363->slave) + return -EINVAL; + + if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) + return -EINVAL; + + direction = SDW_DATA_DIR_RX; + port_config.num = 1; + + stream_config.frame_rate = params_rate(params); + stream_config.bps = snd_pcm_format_width(params_format(params)); + stream_config.direction = direction; + stream_config.ch_count = params_channels(params); + + if (stream_config.ch_count > runtime->hw.channels_max) { + stream_config.ch_count = runtime->hw.channels_max; + dev_info(dai->dev, "Number of channels: %d (requested: %d)\n", + stream_config.ch_count, params_channels(params)); + } + port_config.ch_mask = GENMASK((int)stream_config.ch_count - 1, 0); + + ret = sdw_stream_add_slave(max98363->slave, &stream_config, + &port_config, 1, stream); + if (ret) { + dev_err(dai->dev, "Unable to configure port\n"); + return ret; + } + + dev_dbg(component->dev, "Format supported %d", params_format(params)); + + return 0; +} + +static int max98363_pcm_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct max98363_priv *max98363 = + snd_soc_component_get_drvdata(component); + struct sdw_stream_runtime *stream = + snd_soc_dai_get_dma_data(dai, substream); + + if (!max98363->slave) + return -EINVAL; + + sdw_stream_remove_slave(max98363->slave, stream); + + return 0; +} + +static int max98363_set_sdw_stream(struct snd_soc_dai *dai, + void *sdw_stream, int direction) +{ + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); + + return 0; +} + +static const struct snd_soc_dai_ops max98363_dai_sdw_ops = { + .hw_params = max98363_sdw_dai_hw_params, + .hw_free = max98363_pcm_hw_free, + .set_stream = max98363_set_sdw_stream, +}; + +static struct snd_soc_dai_driver max98363_dai[] = { + { + .name = "max98363-aif1", + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 1, + .rates = MAX98363_RATES, + .formats = MAX98363_FORMATS, + }, + .ops = &max98363_dai_sdw_ops, + } +}; + +static int max98363_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + struct max98363_priv *max98363 = dev_get_drvdata(&slave->dev); + + if (status == SDW_SLAVE_UNATTACHED) + max98363->hw_init = false; + + /* + * Perform initialization only if slave status is SDW_SLAVE_ATTACHED + */ + if (max98363->hw_init || status != SDW_SLAVE_ATTACHED) + return 0; + + /* perform I/O transfers required for Slave initialization */ + return max98363_io_init(slave); +} + +static struct sdw_slave_ops max98363_slave_ops = { + .read_prop = max98363_read_prop, + .update_status = max98363_update_status, +}; + +static DECLARE_TLV_DB_SCALE(max98363_digital_tlv, -6350, 50, 1); +static const DECLARE_TLV_DB_RANGE(max98363_spk_tlv, + 0, 5, TLV_DB_SCALE_ITEM(-300, 300, 0), +); + +static const char * const max98363_tone_cfg_text[] = { + "Reserved", "0", "+FS/2", "-FS/2", "1KHz", + "12KHz", "8KHz", "6KHz", "4KHz", "3KHz", + "2KHz", "1.5KHz", "Reserved", "500Hz", "250Hz" +}; + +static SOC_ENUM_SINGLE_DECL(max98363_tone_cfg_enum, + MAX98363_R2030_TONE_GEN_CFG, 0, + max98363_tone_cfg_text); + +static const char * const max98363_spkmon_duration_text[] = { + "8ms", "20ms", "40ms", "60ms", + "80ms", "160ms", "240ms", "320ms", + "400ms", "480ms", "560ms", "640ms", + "720ms", "800ms", "880ms", "960ms" +}; + +static SOC_ENUM_SINGLE_DECL(max98363_spkmon_duration_enum, + MAX98363_R2023_SPK_MON_DURATION, 0, + max98363_spkmon_duration_text); + +static const struct snd_kcontrol_new max98363_snd_controls[] = { + SOC_SINGLE_TLV("Digital Volume", MAX98363_R2040_AMP_VOL, + 0, 0x7F, 1, max98363_digital_tlv), + SOC_SINGLE_TLV("Speaker Volume", MAX98363_R2041_AMP_GAIN, + 0, 10, 0, max98363_spk_tlv), + SOC_SINGLE("Tone Generator Switch", MAX98363_R203F_TONE_GEN_EN, + 0, 1, 0), + SOC_ENUM("Tone Config", max98363_tone_cfg_enum), + SOC_SINGLE("Ramp Switch", MAX98363_R2042_DSP_CFG, + MAX98363_AMP_DSP_CFG_RMP_SHIFT, 1, 0), + SOC_SINGLE("CLK Monitor Switch", MAX98363_R2021_ERR_MON_CTRL, + MAX98363_CLOCK_MON_SHIFT, 1, 0), + SOC_SINGLE("SPKMON Monitor Switch", MAX98363_R2021_ERR_MON_CTRL, + MAX98363_SPKMON_SHIFT, 1, 0), + SOC_SINGLE("SPKMON Thresh", MAX98363_R2022_SPK_MON_THRESH, 0, 0xFF, 0), + SOC_ENUM("SPKMON Duration", max98363_spkmon_duration_enum), +}; + +static const struct snd_soc_dapm_widget max98363_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("AIFIN", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_OUTPUT("BE_OUT"), +}; + +static const struct snd_soc_dapm_route max98363_audio_map[] = { + /* Plabyack */ + {"BE_OUT", NULL, "AIFIN"}, +}; + +const struct snd_soc_component_driver soc_codec_dev_max98363 = { + .controls = max98363_snd_controls, + .num_controls = ARRAY_SIZE(max98363_snd_controls), + .dapm_widgets = max98363_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98363_dapm_widgets), + .dapm_routes = max98363_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98363_audio_map), + .use_pmdown_time = 1, + .endianness = 1, +}; + +static int max98363_init(struct sdw_slave *slave, struct regmap *regmap) +{ + struct max98363_priv *max98363; + int ret; + struct device *dev = &slave->dev; + + /* Allocate and assign private driver data structure */ + max98363 = devm_kzalloc(dev, sizeof(*max98363), GFP_KERNEL); + if (!max98363) + return -ENOMEM; + + dev_set_drvdata(dev, max98363); + max98363->regmap = regmap; + max98363->slave = slave; + + max98363->hw_init = false; + max98363->first_hw_init = false; + + /* codec registration */ + ret = devm_snd_soc_register_component(dev, &soc_codec_dev_max98363, + max98363_dai, + ARRAY_SIZE(max98363_dai)); + if (ret < 0) + dev_err(dev, "Failed to register codec: %d\n", ret); + + return ret; +} + +static int max98363_sdw_probe(struct sdw_slave *slave, + const struct sdw_device_id *id) +{ + struct regmap *regmap; + + /* Regmap Initialization */ + regmap = devm_regmap_init_sdw(slave, &max98363_sdw_regmap); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return max98363_init(slave, regmap); +} + +static const struct sdw_device_id max98363_id[] = { + SDW_SLAVE_ENTRY(0x019F, 0x8363, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, max98363_id); + +static struct sdw_driver max98363_sdw_driver = { + .driver = { + .name = "max98363", + .pm = pm_ptr(&max98363_pm), + }, + .probe = max98363_sdw_probe, + .ops = &max98363_slave_ops, + .id_table = max98363_id, +}; + +module_sdw_driver(max98363_sdw_driver); + +MODULE_DESCRIPTION("ASoC MAX98363 driver SDW"); +MODULE_AUTHOR("Ryan Lee "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/max98363.h b/sound/soc/codecs/max98363.h new file mode 100644 index 000000000000..2b6743d3a2cf --- /dev/null +++ b/sound/soc/codecs/max98363.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2022 Analog Devices Inc. */ + +#ifndef _MAX98363_H +#define _MAX98363_H + +#define MAX98363_R2000_SW_RESET 0x2000 +#define MAX98363_R2001_INTR_RAW 0x2001 +#define MAX98363_R2003_INTR_STATE 0x2003 +#define MAX98363_R2005_INTR_FALG 0x2005 +#define MAX98363_R2007_INTR_EN 0x2007 +#define MAX98363_R2009_INTR_CLR 0x2009 +#define MAX98363_R2021_ERR_MON_CTRL 0x2021 +#define MAX98363_R2022_SPK_MON_THRESH 0x2022 +#define MAX98363_R2023_SPK_MON_DURATION 0x2023 +#define MAX98363_R2030_TONE_GEN_CFG 0x2030 +#define MAX98363_R203F_TONE_GEN_EN 0x203F +#define MAX98363_R2040_AMP_VOL 0x2040 +#define MAX98363_R2041_AMP_GAIN 0x2041 +#define MAX98363_R2042_DSP_CFG 0x2042 +#define MAX98363_R21FF_REV_ID 0x21FF + +/* MAX98363_R2021_ERR_MON_CTRL */ +#define MAX98363_SPKMON_SHIFT (3) +#define MAX98363_CLOCK_MON_SHIFT (0) + +/* MAX98363_R2042_DSP_CFG */ +#define MAX98363_AMP_DSP_CFG_RMP_SHIFT (3) + +struct max98363_priv { + struct regmap *regmap; + struct sdw_slave *slave; + bool hw_init; + bool first_hw_init; +}; +#endif -- cgit From a4d432e9132c0b29d857b09ca2ec4c1f455b5948 Mon Sep 17 00:00:00 2001 From: Syed Saba Kareem Date: Fri, 31 Mar 2023 10:50:23 +0530 Subject: ASoC: amd: ps: update the acp clock source. Updating the clock source from ACLK to default clock Signed-off-by: Syed Saba Kareem Link: https://lore.kernel.org/r/20230331052102.2211115-1-Syed.SabaKareem@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/pci-ps.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index e86f23d97584..688a1d4643d9 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -91,7 +91,6 @@ static int acp63_init(void __iomem *acp_base, struct device *dev) dev_err(dev, "ACP reset failed\n"); return ret; } - acp63_writel(0x03, acp_base + ACP_CLKMUX_SEL); acp63_enable_interrupts(acp_base); return 0; } @@ -106,7 +105,6 @@ static int acp63_deinit(void __iomem *acp_base, struct device *dev) dev_err(dev, "ACP reset failed\n"); return ret; } - acp63_writel(0, acp_base + ACP_CLKMUX_SEL); acp63_writel(0, acp_base + ACP_CONTROL); return 0; } -- cgit From ee4281de4d60288b9c802bb0906061ec355ecef2 Mon Sep 17 00:00:00 2001 From: Prajna Sariputra Date: Sun, 2 Apr 2023 02:21:30 +1100 Subject: ASoC: amd: yc: Add DMI entries to support HP OMEN 16-n0xxx (8A42) This model requires an additional detection quirk to enable the internal microphone. Signed-off-by: Prajna Sariputra Link: https://lore.kernel.org/r/2283110.ElGaqSPkdT@n0067ax-linux62 Signed-off-by: Mark Brown --- sound/soc/amd/yc/acp6x-mach.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sound') diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index 0acdf0156f07..a428e17f0325 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -262,6 +262,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16z-n000"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8A42"), + } + }, { .driver_data = &acp6x_card, .matches = { -- cgit From 56e008146e5b46059c5469a8b47478ab78f5b895 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Mon, 3 Apr 2023 12:46:41 +0530 Subject: ASoC: SOF: amd: remove unused code During initial SOF driver bring up on AMD platforms, only DMIC support was added. As of today, we have a complete SOF solution for I2S endpoints along with DMIC endpoint. This code is no longer required. Remove unused code from RMB and RN platform ACP PCI driver. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20230403071651.919027-1-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/pci-rmb.c | 70 +-------------------------------------------- sound/soc/sof/amd/pci-rn.c | 70 +-------------------------------------------- 2 files changed, 2 insertions(+), 138 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/amd/pci-rmb.c b/sound/soc/sof/amd/pci-rmb.c index 4e1de462b431..d0a56e8f09c0 100644 --- a/sound/soc/sof/amd/pci-rmb.c +++ b/sound/soc/sof/amd/pci-rmb.c @@ -27,22 +27,6 @@ #define ACP6x_REG_END 0x125C000 static struct platform_device *dmic_dev; -static struct platform_device *pdev; - -static const struct resource rembrandt_res[] = { - { - .start = 0, - .end = ACP6x_REG_END - ACP6x_REG_START, - .name = "acp_mem", - .flags = IORESOURCE_MEM, - }, - { - .start = 0, - .end = 0, - .name = "acp_dai_irq", - .flags = IORESOURCE_IRQ, - }, -}; static const struct sof_amd_acp_desc rembrandt_chip_info = { .rev = 6, @@ -83,11 +67,8 @@ static const struct sof_dev_desc rembrandt_desc = { static int acp_pci_rmb_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - struct platform_device_info pdevinfo; struct device *dev = &pci->dev; - const struct resource *res_i2s; - struct resource *res; - unsigned int flag, i, addr; + unsigned int flag; int ret; flag = snd_amd_acp_find_config(pci); @@ -104,53 +85,6 @@ static int acp_pci_rmb_probe(struct pci_dev *pci, const struct pci_device_id *pc sof_pci_remove(pci); return PTR_ERR(dmic_dev); } - - /* Register platform device only if flag set to FLAG_AMD_SOF_ONLY_DMIC */ - if (flag != FLAG_AMD_SOF_ONLY_DMIC) - return 0; - - addr = pci_resource_start(pci, 0); - res = devm_kzalloc(&pci->dev, sizeof(struct resource) * ARRAY_SIZE(rembrandt_res), - GFP_KERNEL); - if (!res) { - platform_device_unregister(dmic_dev); - sof_pci_remove(pci); - return -ENOMEM; - } - - res_i2s = rembrandt_res; - for (i = 0; i < ARRAY_SIZE(rembrandt_res); i++, res_i2s++) { - res[i].name = res_i2s->name; - res[i].flags = res_i2s->flags; - res[i].start = addr + res_i2s->start; - res[i].end = addr + res_i2s->end; - if (res_i2s->flags == IORESOURCE_IRQ) { - res[i].start = pci->irq; - res[i].end = res[i].start; - } - } - - memset(&pdevinfo, 0, sizeof(pdevinfo)); - - /* - * We have common PCI driver probe for ACP device but we have to support I2S without SOF - * for some distributions. Register platform device that will be used to support non dsp - * ACP's audio ends points on some machines. - */ - pdevinfo.name = "acp_asoc_rembrandt"; - pdevinfo.id = 0; - pdevinfo.parent = &pci->dev; - pdevinfo.num_res = ARRAY_SIZE(rembrandt_res); - pdevinfo.res = &res[0]; - - pdev = platform_device_register_full(&pdevinfo); - if (IS_ERR(pdev)) { - dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name); - platform_device_unregister(dmic_dev); - sof_pci_remove(pci); - ret = PTR_ERR(pdev); - } - return ret; }; @@ -158,8 +92,6 @@ static void acp_pci_rmb_remove(struct pci_dev *pci) { if (dmic_dev) platform_device_unregister(dmic_dev); - if (pdev) - platform_device_unregister(pdev); sof_pci_remove(pci); } diff --git a/sound/soc/sof/amd/pci-rn.c b/sound/soc/sof/amd/pci-rn.c index fca40b261671..faab4c33a24d 100644 --- a/sound/soc/sof/amd/pci-rn.c +++ b/sound/soc/sof/amd/pci-rn.c @@ -27,22 +27,6 @@ #define ACP3x_REG_END 0x125C000 static struct platform_device *dmic_dev; -static struct platform_device *pdev; - -static const struct resource renoir_res[] = { - { - .start = 0, - .end = ACP3x_REG_END - ACP3x_REG_START, - .name = "acp_mem", - .flags = IORESOURCE_MEM, - }, - { - .start = 0, - .end = 0, - .name = "acp_dai_irq", - .flags = IORESOURCE_IRQ, - }, -}; static const struct sof_amd_acp_desc renoir_chip_info = { .rev = 3, @@ -83,11 +67,8 @@ static const struct sof_dev_desc renoir_desc = { static int acp_pci_rn_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - struct platform_device_info pdevinfo; struct device *dev = &pci->dev; - const struct resource *res_i2s; - struct resource *res; - unsigned int flag, i, addr; + unsigned int flag; int ret; flag = snd_amd_acp_find_config(pci); @@ -104,53 +85,6 @@ static int acp_pci_rn_probe(struct pci_dev *pci, const struct pci_device_id *pci sof_pci_remove(pci); return PTR_ERR(dmic_dev); } - - /* Register platform device only if flag set to FLAG_AMD_SOF_ONLY_DMIC */ - if (flag != FLAG_AMD_SOF_ONLY_DMIC) - return 0; - - addr = pci_resource_start(pci, 0); - res = devm_kzalloc(&pci->dev, sizeof(struct resource) * ARRAY_SIZE(renoir_res), GFP_KERNEL); - if (!res) { - sof_pci_remove(pci); - platform_device_unregister(dmic_dev); - return -ENOMEM; - } - - res_i2s = renoir_res; - for (i = 0; i < ARRAY_SIZE(renoir_res); i++, res_i2s++) { - res[i].name = res_i2s->name; - res[i].flags = res_i2s->flags; - res[i].start = addr + res_i2s->start; - res[i].end = addr + res_i2s->end; - if (res_i2s->flags == IORESOURCE_IRQ) { - res[i].start = pci->irq; - res[i].end = res[i].start; - } - } - - memset(&pdevinfo, 0, sizeof(pdevinfo)); - - /* - * We have common PCI driver probe for ACP device but we have to support I2S without SOF - * for some distributions. Register platform device that will be used to support non dsp - * ACP's audio ends points on some machines. - */ - - pdevinfo.name = "acp_asoc_renoir"; - pdevinfo.id = 0; - pdevinfo.parent = &pci->dev; - pdevinfo.num_res = ARRAY_SIZE(renoir_res); - pdevinfo.res = &res[0]; - - pdev = platform_device_register_full(&pdevinfo); - if (IS_ERR(pdev)) { - dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name); - sof_pci_remove(pci); - platform_device_unregister(dmic_dev); - ret = PTR_ERR(pdev); - } - return ret; }; @@ -158,8 +92,6 @@ static void acp_pci_rn_remove(struct pci_dev *pci) { if (dmic_dev) platform_device_unregister(dmic_dev); - if (pdev) - platform_device_unregister(pdev); return sof_pci_remove(pci); } -- cgit From 9eb48aeddd8dcf2defd94a837a65e052576cf42b Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Mon, 3 Apr 2023 12:46:42 +0530 Subject: ASoC: SOF: amd: remove acp_dai_probe() function ACP SOF driver supports different audio configurations. Explicit condition check for I2S configuration will break other audio endpoint configurations. acp_dai_probe() function is not required as we have machine select logic to select the exact machine. Remove acp_dai_probe() from existing AMD PCI driver code base. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20230403071651.919027-2-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp-common.c | 16 ---------------- sound/soc/sof/amd/acp.h | 1 - sound/soc/sof/amd/rembrandt.c | 4 ---- sound/soc/sof/amd/renoir.c | 3 --- 4 files changed, 24 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c index 8ce4c8956933..df36b411a12e 100644 --- a/sound/soc/sof/amd/acp-common.c +++ b/sound/soc/sof/amd/acp-common.c @@ -18,22 +18,6 @@ #include "acp-dsp-offset.h" #include -int acp_dai_probe(struct snd_soc_dai *dai) -{ - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); - const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata); - unsigned int val; - - val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->i2s_pin_config_offset); - if (val != desc->i2s_mode) { - dev_err(sdev->dev, "I2S Mode is not supported (I2S_PIN_CONFIG: %#x)\n", val); - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL_NS(acp_dai_probe, SND_SOC_SOF_AMD_COMMON); - /** * amd_sof_ipc_dump() - This function is called when IPC tx times out. * @sdev: SOF device. diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index acad57947616..d7fc24917b3c 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -248,7 +248,6 @@ int sof_renoir_ops_init(struct snd_sof_dev *sdev); extern struct snd_sof_dsp_ops sof_rembrandt_ops; int sof_rembrandt_ops_init(struct snd_sof_dev *sdev); -int acp_dai_probe(struct snd_soc_dai *dai); struct snd_soc_acpi_mach *amd_sof_machine_select(struct snd_sof_dev *sdev); /* Machine configuration */ int snd_amd_acp_find_config(struct pci_dev *pci); diff --git a/sound/soc/sof/amd/rembrandt.c b/sound/soc/sof/amd/rembrandt.c index 5288ab882fc9..f1d1ba57ab3a 100644 --- a/sound/soc/sof/amd/rembrandt.c +++ b/sound/soc/sof/amd/rembrandt.c @@ -48,7 +48,6 @@ static struct snd_soc_dai_driver rembrandt_sof_dai[] = { .rate_min = 8000, .rate_max = 48000, }, - .probe = &acp_dai_probe, }, [I2S_BT_INSTANCE] = { @@ -73,7 +72,6 @@ static struct snd_soc_dai_driver rembrandt_sof_dai[] = { .rate_min = 8000, .rate_max = 48000, }, - .probe = &acp_dai_probe, }, [I2S_SP_INSTANCE] = { @@ -98,7 +96,6 @@ static struct snd_soc_dai_driver rembrandt_sof_dai[] = { .rate_min = 8000, .rate_max = 48000, }, - .probe = &acp_dai_probe, }, [PDM_DMIC_INSTANCE] = { @@ -126,7 +123,6 @@ static struct snd_soc_dai_driver rembrandt_sof_dai[] = { .rate_min = 8000, .rate_max = 96000, }, - .probe = &acp_dai_probe, }, }; diff --git a/sound/soc/sof/amd/renoir.c b/sound/soc/sof/amd/renoir.c index adade2e3d3be..47b863f6258c 100644 --- a/sound/soc/sof/amd/renoir.c +++ b/sound/soc/sof/amd/renoir.c @@ -47,7 +47,6 @@ static struct snd_soc_dai_driver renoir_sof_dai[] = { .rate_min = 8000, .rate_max = 48000, }, - .probe = &acp_dai_probe, }, [I2S_SP_INSTANCE] = { @@ -72,7 +71,6 @@ static struct snd_soc_dai_driver renoir_sof_dai[] = { .rate_min = 8000, .rate_max = 48000, }, - .probe = &acp_dai_probe, }, [PDM_DMIC_INSTANCE] = { @@ -100,7 +98,6 @@ static struct snd_soc_dai_driver renoir_sof_dai[] = { .rate_min = 8000, .rate_max = 96000, }, - .probe = &acp_dai_probe, }, }; -- cgit From 2675de62de702dbda936eb0f9a20ce3d8fed5ab5 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Mon, 3 Apr 2023 12:46:43 +0530 Subject: ASoC: SOF: amd: remove unused variables Remove unused variables - i2s_mode, i2s_pin_config_offset from code. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20230403071651.919027-3-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp.h | 2 -- sound/soc/sof/amd/pci-rmb.c | 2 -- sound/soc/sof/amd/pci-rn.c | 2 -- 3 files changed, 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index d7fc24917b3c..fd04e5ae7303 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -158,12 +158,10 @@ struct acp_dsp_stream { struct sof_amd_acp_desc { unsigned int rev; unsigned int host_bridge_id; - unsigned int i2s_mode; u32 pgfsm_base; u32 ext_intr_stat; u32 dsp_intr_base; u32 sram_pte_offset; - u32 i2s_pin_config_offset; u32 hw_semaphore_offset; u32 acp_clkmux_sel; u32 fusion_dsp_offset; diff --git a/sound/soc/sof/amd/pci-rmb.c b/sound/soc/sof/amd/pci-rmb.c index d0a56e8f09c0..2b84f95072d3 100644 --- a/sound/soc/sof/amd/pci-rmb.c +++ b/sound/soc/sof/amd/pci-rmb.c @@ -31,12 +31,10 @@ static struct platform_device *dmic_dev; static const struct sof_amd_acp_desc rembrandt_chip_info = { .rev = 6, .host_bridge_id = HOST_BRIDGE_RMB, - .i2s_mode = 0x0a, .pgfsm_base = ACP6X_PGFSM_BASE, .ext_intr_stat = ACP6X_EXT_INTR_STAT, .dsp_intr_base = ACP6X_DSP_SW_INTR_BASE, .sram_pte_offset = ACP6X_SRAM_PTE_OFFSET, - .i2s_pin_config_offset = ACP6X_I2S_PIN_CONFIG, .hw_semaphore_offset = ACP6X_AXI2DAGB_SEM_0, .acp_clkmux_sel = ACP6X_CLKMUX_SEL, .fusion_dsp_offset = ACP6X_DSP_FUSION_RUNSTALL, diff --git a/sound/soc/sof/amd/pci-rn.c b/sound/soc/sof/amd/pci-rn.c index faab4c33a24d..a17b15552a7d 100644 --- a/sound/soc/sof/amd/pci-rn.c +++ b/sound/soc/sof/amd/pci-rn.c @@ -31,12 +31,10 @@ static struct platform_device *dmic_dev; static const struct sof_amd_acp_desc renoir_chip_info = { .rev = 3, .host_bridge_id = HOST_BRIDGE_CZN, - .i2s_mode = 0x04, .pgfsm_base = ACP3X_PGFSM_BASE, .ext_intr_stat = ACP3X_EXT_INTR_STAT, .dsp_intr_base = ACP3X_DSP_SW_INTR_BASE, .sram_pte_offset = ACP3X_SRAM_PTE_OFFSET, - .i2s_pin_config_offset = ACP3X_I2S_PIN_CONFIG, .hw_semaphore_offset = ACP3X_AXI2DAGB_SEM_0, .acp_clkmux_sel = ACP3X_CLKMUX_SEL, }; -- cgit From 292b544ef4555ec5c69522e9c6eace6a90c4cd00 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Mon, 3 Apr 2023 12:46:44 +0530 Subject: ASoC: SOF: amd: refactor get_chip_info callback Move get_chip_info callback to the start of API. This should be first check in probe() call. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20230403071651.919027-4-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index d5ccd4d09278..e8fe324c23d0 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -470,6 +470,11 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) unsigned int addr; int ret; + chip = get_chip_info(sdev->pdata); + if (!chip) { + dev_err(sdev->dev, "no such device supported, chip id:%x\n", pci->device); + return -EIO; + } adata = devm_kzalloc(sdev->dev, sizeof(struct acp_dev_data), GFP_KERNEL); if (!adata) @@ -486,13 +491,6 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) pci_set_master(pci); sdev->pdata->hw_pdata = adata; - - chip = get_chip_info(sdev->pdata); - if (!chip) { - dev_err(sdev->dev, "no such device supported, chip id:%x\n", pci->device); - return -EIO; - } - adata->smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, chip->host_bridge_id, NULL); if (!adata->smn_dev) { dev_err(sdev->dev, "Failed to get host bridge device\n"); -- cgit From c7a3662f14d7e0add7b50dc2f971e77bebb333cc Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Mon, 3 Apr 2023 12:46:45 +0530 Subject: ASoC: SOF: amd: refactor error checks in probe call Refactor error checks code in probe() callback. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20230403071651.919027-5-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index e8fe324c23d0..dbf9ee6d79ed 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -503,16 +503,12 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "failed to register IRQ %d\n", sdev->ipc_irq); - pci_dev_put(adata->smn_dev); - return ret; + goto free_smn_dev; } ret = acp_init(sdev); - if (ret < 0) { - free_irq(sdev->ipc_irq, sdev); - pci_dev_put(adata->smn_dev); - return ret; - } + if (ret < 0) + goto free_ipc_irq; sdev->dsp_box.offset = 0; sdev->dsp_box.size = BOX_SIZE_512; @@ -528,6 +524,12 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) acp_dsp_stream_init(sdev); return 0; + +free_ipc_irq: + free_irq(sdev->ipc_irq, sdev); +free_smn_dev: + pci_dev_put(adata->smn_dev); + return ret; } EXPORT_SYMBOL_NS(amd_sof_acp_probe, SND_SOC_SOF_AMD_COMMON); -- cgit From dd6bdd8b4d41b8f9db4b88dff2d10c0c62dbeb1d Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Mon, 3 Apr 2023 12:46:46 +0530 Subject: ASoC: SOF: amd: refactor dmic codec platform device creation Under snd_sof_dev device scope, create platform device for dmic codec. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/168050621098.26.7486882101201297853@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp.c | 17 +++++++++++++++-- sound/soc/sof/amd/acp.h | 2 ++ sound/soc/sof/amd/pci-rmb.c | 19 +------------------ sound/soc/sof/amd/pci-rn.c | 19 +------------------ 4 files changed, 19 insertions(+), 38 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index dbf9ee6d79ed..2ae76bcd3590 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -481,11 +481,18 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) return -ENOMEM; adata->dev = sdev; + adata->dmic_dev = platform_device_register_data(sdev->dev, "dmic-codec", + PLATFORM_DEVID_NONE, NULL, 0); + if (IS_ERR(adata->dmic_dev)) { + dev_err(sdev->dev, "failed to register platform for dmic codec\n"); + return PTR_ERR(adata->dmic_dev); + } addr = pci_resource_start(pci, ACP_DSP_BAR); sdev->bar[ACP_DSP_BAR] = devm_ioremap(sdev->dev, addr, pci_resource_len(pci, ACP_DSP_BAR)); if (!sdev->bar[ACP_DSP_BAR]) { dev_err(sdev->dev, "ioremap error\n"); - return -ENXIO; + ret = -ENXIO; + goto unregister_dev; } pci_set_master(pci); @@ -494,7 +501,8 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) adata->smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, chip->host_bridge_id, NULL); if (!adata->smn_dev) { dev_err(sdev->dev, "Failed to get host bridge device\n"); - return -ENODEV; + ret = -ENODEV; + goto unregister_dev; } sdev->ipc_irq = pci->irq; @@ -529,6 +537,8 @@ free_ipc_irq: free_irq(sdev->ipc_irq, sdev); free_smn_dev: pci_dev_put(adata->smn_dev); +unregister_dev: + platform_device_unregister(adata->dmic_dev); return ret; } EXPORT_SYMBOL_NS(amd_sof_acp_probe, SND_SOC_SOF_AMD_COMMON); @@ -543,6 +553,9 @@ int amd_sof_acp_remove(struct snd_sof_dev *sdev) if (sdev->ipc_irq) free_irq(sdev->ipc_irq, sdev); + if (adata->dmic_dev) + platform_device_unregister(adata->dmic_dev); + return acp_reset(sdev); } EXPORT_SYMBOL_NS(amd_sof_acp_remove, SND_SOC_SOF_AMD_COMMON); diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index fd04e5ae7303..1c535cc6c3a9 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -170,6 +170,8 @@ struct sof_amd_acp_desc { /* Common device data struct for ACP devices */ struct acp_dev_data { struct snd_sof_dev *dev; + /* DMIC device */ + struct platform_device *dmic_dev; unsigned int fw_bin_size; unsigned int fw_data_bin_size; u32 fw_bin_page_count; diff --git a/sound/soc/sof/amd/pci-rmb.c b/sound/soc/sof/amd/pci-rmb.c index 2b84f95072d3..eaf70ea6e556 100644 --- a/sound/soc/sof/amd/pci-rmb.c +++ b/sound/soc/sof/amd/pci-rmb.c @@ -26,8 +26,6 @@ #define ACP6x_REG_START 0x1240000 #define ACP6x_REG_END 0x125C000 -static struct platform_device *dmic_dev; - static const struct sof_amd_acp_desc rembrandt_chip_info = { .rev = 6, .host_bridge_id = HOST_BRIDGE_RMB, @@ -65,32 +63,17 @@ static const struct sof_dev_desc rembrandt_desc = { static int acp_pci_rmb_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - struct device *dev = &pci->dev; unsigned int flag; - int ret; flag = snd_amd_acp_find_config(pci); if (flag != FLAG_AMD_SOF && flag != FLAG_AMD_SOF_ONLY_DMIC) return -ENODEV; - ret = sof_pci_probe(pci, pci_id); - if (ret != 0) - return ret; - - dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0); - if (IS_ERR(dmic_dev)) { - dev_err(dev, "failed to create DMIC device\n"); - sof_pci_remove(pci); - return PTR_ERR(dmic_dev); - } - return ret; + return sof_pci_probe(pci, pci_id); }; static void acp_pci_rmb_remove(struct pci_dev *pci) { - if (dmic_dev) - platform_device_unregister(dmic_dev); - sof_pci_remove(pci); } diff --git a/sound/soc/sof/amd/pci-rn.c b/sound/soc/sof/amd/pci-rn.c index a17b15552a7d..4809cb644152 100644 --- a/sound/soc/sof/amd/pci-rn.c +++ b/sound/soc/sof/amd/pci-rn.c @@ -26,8 +26,6 @@ #define ACP3x_REG_START 0x1240000 #define ACP3x_REG_END 0x125C000 -static struct platform_device *dmic_dev; - static const struct sof_amd_acp_desc renoir_chip_info = { .rev = 3, .host_bridge_id = HOST_BRIDGE_CZN, @@ -65,32 +63,17 @@ static const struct sof_dev_desc renoir_desc = { static int acp_pci_rn_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - struct device *dev = &pci->dev; unsigned int flag; - int ret; flag = snd_amd_acp_find_config(pci); if (flag != FLAG_AMD_SOF && flag != FLAG_AMD_SOF_ONLY_DMIC) return -ENODEV; - ret = sof_pci_probe(pci, pci_id); - if (ret != 0) - return ret; - - dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0); - if (IS_ERR(dmic_dev)) { - dev_err(dev, "failed to create DMIC device\n"); - sof_pci_remove(pci); - return PTR_ERR(dmic_dev); - } - return ret; + return sof_pci_probe(pci, pci_id); }; static void acp_pci_rn_remove(struct pci_dev *pci) { - if (dmic_dev) - platform_device_unregister(dmic_dev); - return sof_pci_remove(pci); } -- cgit From 3af24372964a8f999d62427c0585d9a4693ae4e4 Mon Sep 17 00:00:00 2001 From: Allen-KH Cheng Date: Wed, 29 Mar 2023 16:04:18 +0800 Subject: ASoC: mediatek: mt8186: Move some prints to debug level There are many log messages scattered throughout the mt8186 sound drivers, and they are frequently triggered. To avoid spamming the console, move these messages to the debug level. Signed-off-by: Allen-KH Cheng Link: https://lore.kernel.org/r/20230329080418.1100-1-allen-kh.cheng@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-afe-gpio.c | 26 +++++++++++----------- sound/soc/mediatek/mt8186/mt8186-dai-adda.c | 4 ++-- .../mt8186/mt8186-mt6366-da7219-max98357.c | 2 +- .../mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c | 6 ++--- 4 files changed, 19 insertions(+), 19 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c index eda913fa147a..20b9f5d810ec 100644 --- a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c +++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c @@ -85,7 +85,7 @@ int mt8186_afe_gpio_init(struct device *dev) aud_gpios[i].name); if (IS_ERR(aud_gpios[i].gpioctrl)) { ret = PTR_ERR(aud_gpios[i].gpioctrl); - dev_info(dev, "%s(), pinctrl_lookup_state %s fail, ret %d\n", + dev_dbg(dev, "%s(), pinctrl_lookup_state %s fail, ret %d\n", __func__, aud_gpios[i].name, ret); } else { aud_gpios[i].gpio_prepare = true; @@ -108,13 +108,13 @@ static int mt8186_afe_gpio_select(struct device *dev, int ret = 0; if (type < 0 || type >= MT8186_AFE_GPIO_GPIO_NUM) { - dev_err(dev, "%s(), error, invalid gpio type %d\n", + dev_dbg(dev, "%s(), error, invalid gpio type %d\n", __func__, type); return -EINVAL; } if (!aud_gpios[type].gpio_prepare) { - dev_err(dev, "%s(), error, gpio type %d not prepared\n", + dev_dbg(dev, "%s(), error, gpio type %d not prepared\n", __func__, type); return -EIO; } @@ -122,7 +122,7 @@ static int mt8186_afe_gpio_select(struct device *dev, ret = pinctrl_select_state(aud_pinctrl, aud_gpios[type].gpioctrl); if (ret) { - dev_err(dev, "%s(), error, can not set gpio type %d\n", + dev_dbg(dev, "%s(), error, can not set gpio type %d\n", __func__, type); return ret; } @@ -137,25 +137,25 @@ static int mt8186_afe_gpio_adda_dl(struct device *dev, bool enable) if (enable) { ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_ON); if (ret) { - dev_err(dev, "%s(), MOSI CLK ON select fail!\n", __func__); + dev_dbg(dev, "%s(), MOSI CLK ON select fail!\n", __func__); return ret; } ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_ON); if (ret) { - dev_err(dev, "%s(), MOSI DAT ON select fail!\n", __func__); + dev_dbg(dev, "%s(), MOSI DAT ON select fail!\n", __func__); return ret; } } else { ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_OFF); if (ret) { - dev_err(dev, "%s(), MOSI DAT OFF select fail!\n", __func__); + dev_dbg(dev, "%s(), MOSI DAT OFF select fail!\n", __func__); return ret; } ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_OFF); if (ret) { - dev_err(dev, "%s(), MOSI CLK ON select fail!\n", __func__); + dev_dbg(dev, "%s(), MOSI CLK ON select fail!\n", __func__); return ret; } } @@ -170,25 +170,25 @@ static int mt8186_afe_gpio_adda_ul(struct device *dev, bool enable) if (enable) { ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MISO_ON); if (ret) { - dev_err(dev, "%s(), MISO CLK ON select fail!\n", __func__); + dev_dbg(dev, "%s(), MISO CLK ON select fail!\n", __func__); return ret; } ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MISO_ON); if (ret) { - dev_err(dev, "%s(), MISO DAT ON select fail!\n", __func__); + dev_dbg(dev, "%s(), MISO DAT ON select fail!\n", __func__); return ret; } } else { ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MISO_OFF); if (ret) { - dev_err(dev, "%s(), MISO DAT OFF select fail!\n", __func__); + dev_dbg(dev, "%s(), MISO DAT OFF select fail!\n", __func__); return ret; } ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MISO_OFF); if (ret) { - dev_err(dev, "%s(), MISO CLK OFF select fail!\n", __func__); + dev_dbg(dev, "%s(), MISO CLK OFF select fail!\n", __func__); return ret; } } @@ -230,7 +230,7 @@ int mt8186_afe_gpio_request(struct device *dev, bool enable, sel = enable ? MT8186_AFE_GPIO_PCM_ON : MT8186_AFE_GPIO_PCM_OFF; break; default: - dev_err(dev, "%s(), invalid dai %d\n", __func__, dai); + dev_dbg(dev, "%s(), invalid dai %d\n", __func__, dai); goto unlock; } diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c index 094402470dc2..247ab8df941f 100644 --- a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c +++ b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c @@ -110,7 +110,7 @@ static unsigned int adda_dl_rate_transform(struct mtk_base_afe *afe, case 192000: return MTK_AFE_ADDA_DL_RATE_192K; default: - dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", + dev_dbg(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", __func__, rate); } @@ -134,7 +134,7 @@ static unsigned int adda_ul_rate_transform(struct mtk_base_afe *afe, case 192000: return MTK_AFE_ADDA_UL_RATE_192K; default: - dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", + dev_dbg(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", __func__, rate); } diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c index 970b980a81e6..cdf54d1eb50d 100644 --- a/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c @@ -1061,7 +1061,7 @@ static int mt8186_mt6366_da7219_max98357_dev_probe(struct platform_device *pdev) card->name = card->topology_shortname; sof_on = 1; } else { - dev_info(&pdev->dev, "Probe without adsp\n"); + dev_dbg(&pdev->dev, "Probe without adsp\n"); } if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) { diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c index b333950aa3c3..7538274641fd 100644 --- a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c @@ -95,7 +95,7 @@ static int dmic_set(struct snd_kcontrol *kcontrol, priv->dmic_switch = ucontrol->value.integer.value[0]; if (priv->dmic_sel) { gpiod_set_value(priv->dmic_sel, priv->dmic_switch); - dev_info(dapm->card->dev, "dmic_set_value %d\n", + dev_dbg(dapm->card->dev, "dmic_set_value %d\n", priv->dmic_switch); } return 0; @@ -139,7 +139,7 @@ static int primary_codec_init(struct snd_soc_pcm_runtime *rtd) } if (!priv->dmic_sel) { - dev_info(card->dev, "dmic_sel is null\n"); + dev_dbg(card->dev, "dmic_sel is null\n"); return 0; } @@ -1152,7 +1152,7 @@ static int mt8186_mt6366_rt1019_rt5682s_dev_probe(struct platform_device *pdev) card->name = card->topology_shortname; sof_on = 1; } else { - dev_info(&pdev->dev, "Probe without adsp\n"); + dev_dbg(&pdev->dev, "Probe without adsp\n"); } if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) { -- cgit From 09255c7ed8ca1f1ed99357b845d2f63fe2ef3e1e Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:04 +0300 Subject: ASoC: SOF: Intel: hda-stream: Do not dereference hstream until it is safe Only access hext_stream->hstream after it has been checked for NULL pointer Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index c37ef581637f..50e92996f928 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -485,9 +485,8 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, { const struct sof_intel_dsp_desc *chip = get_chip_info(sdev->pdata); struct hdac_bus *bus = sof_to_bus(sdev); - struct hdac_stream *hstream = &hext_stream->hstream; - int sd_offset = SOF_STREAM_SD_OFFSET(hstream); - int ret; + struct hdac_stream *hstream; + int sd_offset, ret; u32 dma_start = SOF_HDA_SD_CTL_DMA_START; u32 mask; u32 run; @@ -502,6 +501,9 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, return -ENODEV; } + hstream = &hext_stream->hstream; + sd_offset = SOF_STREAM_SD_OFFSET(hstream); + /* decouple host and link DMA */ mask = 0x1 << hstream->index; snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, -- cgit From 59611370f92923089ceb284072d01445164a0191 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:05 +0300 Subject: ASoC: SOF: Add flag and state which will be used for DSP-less mode The DSPless mode of the ASoC/SOF driver can be used for hardware verification and debug on platforms with HDaudio codecs. The DSP mode is still needed on existing platforms for SSP, DMIC, SoundWire interfaces managed by the GP-DMA. This mode is also helpful to compare the legacy HDaudio driver with the ASoC/SOF driver wrt. codec management and handling. In theory we use the same code but differences are sometimes seen on jack detection and event handling. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 9 +++++++++ sound/soc/sof/sof-priv.h | 11 +++++++++++ 2 files changed, 20 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 7de8673a01ce..06bcae631612 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -365,6 +365,15 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) if (sof_core_debug) dev_info(dev, "sof_debug value: %#x\n", sof_core_debug); + if (sof_debug_check_flag(SOF_DBG_DSPLESS_MODE)) { + if (plat_data->desc->dspless_mode_supported) { + dev_info(dev, "Switching to DSPless mode\n"); + sdev->dspless_mode_selected = true; + } else { + dev_info(dev, "DSPless mode is not supported by the platform\n"); + } + } + /* check IPC support */ if (!(BIT(plat_data->ipc_type) & plat_data->desc->ipc_supported_mask)) { dev_err(dev, "ipc_type %d is not supported on this platform, mask is %#x\n", diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 5f919162a555..1170989bea57 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -48,6 +48,7 @@ struct snd_sof_pcm_stream; #define SOF_DBG_FORCE_NOCODEC BIT(10) /* ignore all codec-related * configurations */ +#define SOF_DBG_DSPLESS_MODE BIT(15) /* Do not initialize and use the DSP */ /* Flag definitions used for controlling the DSP dump behavior */ #define SOF_DBG_DUMP_REGS BIT(0) @@ -528,6 +529,16 @@ struct snd_sof_dev { spinlock_t ipc_lock; /* lock for IPC users */ spinlock_t hw_lock; /* lock for HW IO access */ + /* + * When true the DSP is not used. + * It is set under the following condition: + * User sets the SOF_DBG_DSPLESS_MODE flag in sof_debug module parameter + * and + * the platform advertises that it can support such mode + * pdata->desc->dspless_mode_supported is true. + */ + bool dspless_mode_selected; + /* Main, Base firmware image */ struct sof_firmware basefw; -- cgit From 28d40e7adfd4108c11c9397c6fe9d9f80fed31e9 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:06 +0300 Subject: ASoC: SOF: Add support for DSPless mode Via the SOF_DBG_DSPLESS_MODE sof_debug flag the SOF stack can be asked to not use the DSP for audio. The core's support for DSPless mode is only going to be enabled if the platform reports that it can be used without DSP. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 22 ++++++-- sound/soc/sof/debug.c | 1 + sound/soc/sof/pcm.c | 13 ++++- sound/soc/sof/pm.c | 5 ++ sound/soc/sof/sof-audio.c | 2 +- sound/soc/sof/sof-client.c | 3 ++ sound/soc/sof/topology.c | 130 ++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 168 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 06bcae631612..9a9d82220fd0 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -208,6 +208,11 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) /* set up platform component driver */ snd_sof_new_platform_drv(sdev); + if (sdev->dspless_mode_selected) { + sof_set_fw_state(sdev, SOF_DSPLESS_MODE); + goto skip_dsp_init; + } + /* register any debug/trace capabilities */ ret = snd_sof_dbg_init(sdev); if (ret < 0) { @@ -266,6 +271,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) dev_dbg(sdev->dev, "SOF firmware trace disabled\n"); } +skip_dsp_init: /* hereafter all FW boot flows are for PM reasons */ sdev->first_boot = false; @@ -387,12 +393,18 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) return ret; /* check all mandatory ops */ - if (!sof_ops(sdev) || !sof_ops(sdev)->probe || !sof_ops(sdev)->run || - !sof_ops(sdev)->block_read || !sof_ops(sdev)->block_write || - !sof_ops(sdev)->send_msg || !sof_ops(sdev)->load_firmware || - !sof_ops(sdev)->ipc_msg_data) { + if (!sof_ops(sdev) || !sof_ops(sdev)->probe) { + sof_ops_free(sdev); + dev_err(dev, "missing mandatory ops\n"); + return -EINVAL; + } + + if (!sdev->dspless_mode_selected && + (!sof_ops(sdev)->run || !sof_ops(sdev)->block_read || + !sof_ops(sdev)->block_write || !sof_ops(sdev)->send_msg || + !sof_ops(sdev)->load_firmware || !sof_ops(sdev)->ipc_msg_data)) { sof_ops_free(sdev); - dev_err(dev, "error: missing mandatory ops\n"); + dev_err(dev, "missing mandatory DSP ops\n"); return -EINVAL; } diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index ade0507328af..b42b5982cbbc 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -370,6 +370,7 @@ static const struct soc_fw_state_info { const char *name; } fw_state_dbg[] = { {SOF_FW_BOOT_NOT_STARTED, "SOF_FW_BOOT_NOT_STARTED"}, + {SOF_DSPLESS_MODE, "SOF_DSPLESS_MODE"}, {SOF_FW_BOOT_PREPARE, "SOF_FW_BOOT_PREPARE"}, {SOF_FW_BOOT_IN_PROGRESS, "SOF_FW_BOOT_IN_PROGRESS"}, {SOF_FW_BOOT_FAILED, "SOF_FW_BOOT_FAILED"}, diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index d9b4633bba7a..127b68caf9e1 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -330,6 +330,11 @@ static int sof_pcm_trigger(struct snd_soc_component *component, spcm->stream[substream->stream].suspend_ignored = true; return 0; } + + /* On suspend the DMA must be stopped in DSPless mode */ + if (sdev->dspless_mode_selected) + reset_hw_params = true; + fallthrough; case SNDRV_PCM_TRIGGER_STOP: ipc_first = true; @@ -705,7 +710,6 @@ void snd_sof_new_platform_drv(struct snd_sof_dev *sdev) pd->pcm_construct = sof_pcm_new; pd->ignore_machine = drv_name; - pd->be_hw_params_fixup = sof_pcm_dai_link_fixup; pd->be_pcm_base = SOF_BE_PCM_BASE; pd->use_dai_pcm_id = true; pd->topology_name_prefix = "sof"; @@ -714,4 +718,11 @@ void snd_sof_new_platform_drv(struct snd_sof_dev *sdev) pd->module_get_upon_open = 1; pd->legacy_dai_naming = 1; + + /* + * The fixup is only needed when the DSP is in use as with the DSPless + * mode we are directly using the audio interface + */ + if (!sdev->dspless_mode_selected) + pd->be_hw_params_fixup = sof_pcm_dai_link_fixup; } diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 8d3383085d12..c74ce8d414e7 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -103,6 +103,11 @@ static int sof_resume(struct device *dev, bool runtime_resume) return ret; } + if (sdev->dspless_mode_selected) { + sof_set_fw_state(sdev, SOF_DSPLESS_MODE); + return 0; + } + /* * Nothing further to be done for platforms that support the low power * D0 substate. Resume trace and return when resuming from diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 4f12e137ff63..7651644fcd62 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -688,7 +688,7 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, struct snd_sof_widget *pipe_widget; struct snd_sof_pipeline *spipe; - if (!swidget) + if (!swidget || sdev->dspless_mode_selected) continue; spipe = swidget->spipe; diff --git a/sound/soc/sof/sof-client.c b/sound/soc/sof/sof-client.c index 9017f0864cdd..d6b7caa0cf03 100644 --- a/sound/soc/sof/sof-client.c +++ b/sound/soc/sof/sof-client.c @@ -130,6 +130,9 @@ int sof_register_clients(struct snd_sof_dev *sdev) { int ret; + if (sdev->dspless_mode_selected) + return 0; + /* Register platform independent client devices */ ret = sof_register_ipc_flood_test(sdev); if (ret) { diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index bc8ca1e05b83..d3d536b0a8f5 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1144,8 +1144,12 @@ static void sof_disconnect_dai_widget(struct snd_soc_component *scomp, static int spcm_bind(struct snd_soc_component *scomp, struct snd_sof_pcm *spcm, int dir) { + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_sof_widget *host_widget; + if (sdev->dspless_mode_selected) + return 0; + host_widget = snd_sof_find_swidget_sname(scomp, spcm->pcm.caps[dir].name, dir); @@ -2270,6 +2274,126 @@ static struct snd_soc_tplg_ops sof_tplg_ops = { .bytes_ext_ops_count = ARRAY_SIZE(sof_bytes_ext_ops), }; +static int snd_sof_dspless_kcontrol(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static const struct snd_soc_tplg_kcontrol_ops sof_dspless_io_ops[] = { + {SOF_TPLG_KCTL_VOL_ID, snd_sof_dspless_kcontrol, snd_sof_dspless_kcontrol}, + {SOF_TPLG_KCTL_BYTES_ID, snd_sof_dspless_kcontrol, snd_sof_dspless_kcontrol}, + {SOF_TPLG_KCTL_ENUM_ID, snd_sof_dspless_kcontrol, snd_sof_dspless_kcontrol}, + {SOF_TPLG_KCTL_SWITCH_ID, snd_sof_dspless_kcontrol, snd_sof_dspless_kcontrol}, +}; + +static int snd_sof_dspless_bytes_ext_get(struct snd_kcontrol *kcontrol, + unsigned int __user *binary_data, + unsigned int size) +{ + return 0; +} + +static int snd_sof_dspless_bytes_ext_put(struct snd_kcontrol *kcontrol, + const unsigned int __user *binary_data, + unsigned int size) +{ + return 0; +} + +static const struct snd_soc_tplg_bytes_ext_ops sof_dspless_bytes_ext_ops[] = { + {SOF_TPLG_KCTL_BYTES_ID, snd_sof_dspless_bytes_ext_get, snd_sof_dspless_bytes_ext_put}, + {SOF_TPLG_KCTL_BYTES_VOLATILE_RO, snd_sof_dspless_bytes_ext_get}, +}; + +/* external widget init - used for any driver specific init */ +static int sof_dspless_widget_ready(struct snd_soc_component *scomp, int index, + struct snd_soc_dapm_widget *w, + struct snd_soc_tplg_dapm_widget *tw) +{ + if (WIDGET_IS_DAI(w->id)) { + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_sof_widget *swidget; + struct snd_sof_dai dai; + int ret; + + swidget = kzalloc(sizeof(*swidget), GFP_KERNEL); + if (!swidget) + return -ENOMEM; + + memset(&dai, 0, sizeof(dai)); + + ret = sof_connect_dai_widget(scomp, w, tw, &dai); + if (ret) { + kfree(swidget); + return ret; + } + + swidget->scomp = scomp; + swidget->widget = w; + mutex_init(&swidget->setup_mutex); + w->dobj.private = swidget; + list_add(&swidget->list, &sdev->widget_list); + } + + return 0; +} + +static int sof_dspless_widget_unload(struct snd_soc_component *scomp, + struct snd_soc_dobj *dobj) +{ + struct snd_soc_dapm_widget *w = container_of(dobj, struct snd_soc_dapm_widget, dobj); + + if (WIDGET_IS_DAI(w->id)) { + struct snd_sof_widget *swidget = dobj->private; + + sof_disconnect_dai_widget(scomp, w); + + if (!swidget) + return 0; + + /* remove and free swidget object */ + list_del(&swidget->list); + kfree(swidget); + } + + return 0; +} + +static int sof_dspless_link_load(struct snd_soc_component *scomp, int index, + struct snd_soc_dai_link *link, + struct snd_soc_tplg_link_config *cfg) +{ + link->platforms->name = dev_name(scomp->dev); + + /* Set nonatomic property for FE dai links for FE-BE compatibility */ + if (!link->no_pcm) + link->nonatomic = true; + + return 0; +} + +static struct snd_soc_tplg_ops sof_dspless_tplg_ops = { + /* external widget init - used for any driver specific init */ + .widget_ready = sof_dspless_widget_ready, + .widget_unload = sof_dspless_widget_unload, + + /* FE DAI - used for any driver specific init */ + .dai_load = sof_dai_load, + .dai_unload = sof_dai_unload, + + /* DAI link - used for any driver specific init */ + .link_load = sof_dspless_link_load, + + /* vendor specific kcontrol handlers available for binding */ + .io_ops = sof_dspless_io_ops, + .io_ops_count = ARRAY_SIZE(sof_dspless_io_ops), + + /* vendor specific bytes ext handlers available for binding */ + .bytes_ext_ops = sof_dspless_bytes_ext_ops, + .bytes_ext_ops_count = ARRAY_SIZE(sof_dspless_bytes_ext_ops), +}; + int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); @@ -2287,7 +2411,11 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) return ret; } - ret = snd_soc_tplg_component_load(scomp, &sof_tplg_ops, fw); + if (sdev->dspless_mode_selected) + ret = snd_soc_tplg_component_load(scomp, &sof_dspless_tplg_ops, fw); + else + ret = snd_soc_tplg_component_load(scomp, &sof_tplg_ops, fw); + if (ret < 0) { dev_err(scomp->dev, "error: tplg component load failed %d\n", ret); -- cgit From 4a3b1433a8d384ff8d668b4f8665d6c67dbb30d3 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:07 +0300 Subject: ASoC: SOF: Intel: hda: Skip interfaces not supported on a platform Not all interfaces (SSP/DMIC/HDA/SDW) are available on all platforms. If the interface is not even supported then there is no point in executing a probe or query for that interface. Introduce a simple function (hda_get_interface_mask) to query the interfaces supported on the platform. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 50 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 65389c7278e2..19aad4141a78 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -44,6 +44,37 @@ #define EXCEPT_MAX_HDR_SIZE 0x400 #define HDA_EXT_ROM_STATUS_SIZE 8 +static u32 hda_get_interface_mask(struct snd_sof_dev *sdev) +{ + const struct sof_intel_dsp_desc *chip; + u32 interface_mask = 0; + + chip = get_chip_info(sdev->pdata); + switch (chip->hw_ip_version) { + case SOF_INTEL_TANGIER: + case SOF_INTEL_BAYTRAIL: + case SOF_INTEL_BROADWELL: + interface_mask = BIT(SOF_DAI_INTEL_SSP); + break; + case SOF_INTEL_CAVS_1_5: + case SOF_INTEL_CAVS_1_5_PLUS: + interface_mask = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | + BIT(SOF_DAI_INTEL_HDA); + break; + case SOF_INTEL_CAVS_1_8: + case SOF_INTEL_CAVS_2_0: + case SOF_INTEL_CAVS_2_5: + case SOF_INTEL_ACE_1_0: + interface_mask = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | + BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); + break; + default: + break; + } + + return interface_mask; +} + #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) /* @@ -845,6 +876,7 @@ static int dmic_detect_topology_fixup(struct snd_sof_dev *sdev, static int hda_init_caps(struct snd_sof_dev *sdev) { + u32 interface_mask = hda_get_interface_mask(sdev); struct hdac_bus *bus = sof_to_bus(sdev); struct snd_sof_pdata *pdata = sdev->pdata; struct sof_intel_hda_dev *hdev = pdata->hw_pdata; @@ -865,6 +897,10 @@ static int hda_init_caps(struct snd_sof_dev *sdev) hda_bus_ml_get_capabilities(bus); + /* Skip SoundWire if it is not supported */ + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + goto skip_soundwire; + /* scan SoundWire capabilities exposed by DSDT */ ret = hda_sdw_acpi_scan(sdev); if (ret < 0) { @@ -1486,12 +1522,16 @@ void hda_set_mach_params(struct snd_soc_acpi_mach *mach, struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) { + u32 interface_mask = hda_get_interface_mask(sdev); struct snd_sof_pdata *sof_pdata = sdev->pdata; const struct sof_dev_desc *desc = sof_pdata->desc; - struct snd_soc_acpi_mach *mach; + struct snd_soc_acpi_mach *mach = NULL; const char *tplg_filename; - mach = snd_soc_acpi_find_machine(desc->machines); + /* Try I2S or DMIC if it is supported */ + if (interface_mask & (BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC))) + mach = snd_soc_acpi_find_machine(desc->machines); + if (mach) { bool add_extension = false; bool tplg_fixup = false; @@ -1598,10 +1638,8 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) } } - /* - * If I2S fails, try SoundWire - */ - if (!mach) + /* If I2S fails, try SoundWire if it is supported */ + if (!mach && (interface_mask & BIT(SOF_DAI_INTEL_ALH))) mach = hda_sdw_machine_select(sdev); /* -- cgit From 1f7b5d52be130e16fda60be446b30136698738c6 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:08 +0300 Subject: ASoC: SOF: Intel: hda: Add support for DSPless mode Via the SOF_DBG_DSPLESS_MODE sof_debug flag the SOF stack can be asked to not use the DSP for audio. The use of DSPless mode is governed by the sdev->dspless_mode_selected flag which is only going to be set if the user sets sof_debug=0x8000 and the platform advertises that the DSPless mode is supported on them. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 33 ++++++++++++++++++++++++++++++++- sound/soc/sof/intel/hda-dai.c | 25 ++++++++++++++++++++----- sound/soc/sof/intel/hda-pcm.c | 24 +++++++++++++++++------- sound/soc/sof/intel/hda-stream.c | 34 ++++++++++++++++++---------------- sound/soc/sof/intel/hda.c | 19 ++++++++++++------- 5 files changed, 99 insertions(+), 36 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index de48f13259f1..4b39cecacd68 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -319,13 +319,44 @@ static const struct hda_dai_widget_dma_ops hda_ipc3_dma_ops = { .post_trigger = hda_ipc3_post_trigger, }; +static struct hdac_ext_stream * +hda_dspless_get_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream) +{ + struct hdac_stream *hstream = substream->runtime->private_data; + + return stream_to_hdac_ext_stream(hstream); +} + +static void hda_dspless_setup_hext_stream(struct snd_sof_dev *sdev, + struct hdac_ext_stream *hext_stream, + unsigned int format_val) +{ + /* + * Save the format_val which was adjusted by the maxbps of the codec. + * This information is not available on the FE side since there we are + * using dummy_codec. + */ + hext_stream->hstream.format_val = format_val; +} + +static const struct hda_dai_widget_dma_ops hda_dspless_dma_ops = { + .get_hext_stream = hda_dspless_get_hext_stream, + .setup_hext_stream = hda_dspless_setup_hext_stream, +}; + #endif const struct hda_dai_widget_dma_ops * hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) - struct snd_sof_dai *sdai = swidget->private; + struct snd_sof_dai *sdai; + + if (sdev->dspless_mode_selected) + return &hda_dspless_dma_ops; + + sdai = swidget->private; switch (sdev->pdata->ipc_type) { case SOF_IPC: diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 46a17afdd1ea..0435b7f251aa 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -31,11 +31,18 @@ int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, struct snd_sof_dai_config_data *data) { struct snd_sof_widget *swidget = w->dobj.private; - struct snd_soc_component *component = swidget->scomp; - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); + const struct sof_ipc_tplg_ops *tplg_ops; + struct snd_soc_component *component; + struct snd_sof_dev *sdev; int ret; + if (!swidget) + return 0; + + component = swidget->scomp; + sdev = snd_soc_component_get_drvdata(component); + tplg_ops = sof_ipc_get_ops(sdev, tplg); + if (tplg_ops && tplg_ops->dai_config) { ret = tplg_ops->dai_config(sdev, swidget, flags, data); if (ret < 0) { @@ -56,13 +63,21 @@ hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); struct snd_sof_widget *swidget = w->dobj.private; - struct snd_sof_dai *sdai = swidget->private; + struct snd_sof_dai *sdai; + + /* + * The swidget parameter of hda_select_dai_widget_ops() is ignored in + * case of DSPless mode + */ + if (sdev->dspless_mode_selected) + return hda_select_dai_widget_ops(sdev, NULL); + + sdai = swidget->private; /* select and set the DAI widget ops if not set already */ if (!sdai->platform_private) { const struct hda_dai_widget_dma_ops *ops = hda_select_dai_widget_ops(sdev, swidget); - if (!ops) return NULL; diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index dc0b359ed9b6..981e7b699bdb 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -101,18 +101,23 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev, struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct snd_dma_buffer *dmab; int ret; - u32 size, rate, bits; - - size = params_buffer_bytes(params); - rate = hda_dsp_get_mult_div(sdev, params_rate(params)); - bits = hda_dsp_get_bits(sdev, params_width(params)); hstream->substream = substream; dmab = substream->runtime->dma_buffer_p; - hstream->format_val = rate | bits | (params_channels(params) - 1); - hstream->bufsize = size; + /* + * Use the codec required format val (which is link_bps adjusted) when + * the DSP is not in use + */ + if (!sdev->dspless_mode_selected) { + u32 rate = hda_dsp_get_mult_div(sdev, params_rate(params)); + u32 bits = hda_dsp_get_bits(sdev, params_width(params)); + + hstream->format_val = rate | bits | (params_channels(params) - 1); + } + + hstream->bufsize = params_buffer_bytes(params); hstream->period_bytes = params_period_bytes(params); hstream->no_period_wakeup = (params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) && @@ -249,6 +254,11 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev, snd_pcm_hw_constraint_integer(substream->runtime, SNDRV_PCM_HW_PARAM_PERIODS); + /* Only S16 and S32 supported by HDA hardware when used without DSP */ + if (sdev->dspless_mode_selected) + snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_FORMAT, + SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_S32); + /* binding pcm substream to hda stream */ substream->runtime->private_data = &dsp_stream->hstream; return 0; diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 50e92996f928..87e31a65b314 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -503,11 +503,12 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, hstream = &hext_stream->hstream; sd_offset = SOF_STREAM_SD_OFFSET(hstream); + mask = BIT(hstream->index); - /* decouple host and link DMA */ - mask = 0x1 << hstream->index; - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, - mask, mask); + /* decouple host and link DMA if the DSP is used */ + if (!sdev->dspless_mode_selected) + snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, + mask, mask); /* clear stream status */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, @@ -608,11 +609,10 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, * enable decoupled mode */ - if (chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK) { + if (!sdev->dspless_mode_selected && (chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) /* couple host and link DMA, disable DSP features */ snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, mask, 0); - } /* program stream format */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, @@ -620,11 +620,10 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, SOF_HDA_ADSP_REG_SD_FORMAT, 0xffff, hstream->format_val); - if (chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK) { + if (!sdev->dspless_mode_selected && (chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) /* decouple host and link DMA, enable DSP features */ snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, mask, mask); - } /* program last valid index */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, @@ -677,20 +676,23 @@ int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream = container_of(hstream, struct hdac_ext_stream, hstream); - struct hdac_bus *bus = sof_to_bus(sdev); - u32 mask = 0x1 << hstream->index; int ret; ret = hda_dsp_stream_reset(sdev, hstream); if (ret < 0) return ret; - spin_lock_irq(&bus->reg_lock); - /* couple host and link DMA if link DMA channel is idle */ - if (!hext_stream->link_locked) - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, - SOF_HDA_REG_PP_PPCTL, mask, 0); - spin_unlock_irq(&bus->reg_lock); + if (!sdev->dspless_mode_selected) { + struct hdac_bus *bus = sof_to_bus(sdev); + u32 mask = BIT(hstream->index); + + spin_lock_irq(&bus->reg_lock); + /* couple host and link DMA if link DMA channel is idle */ + if (!hext_stream->link_locked) + snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, + SOF_HDA_REG_PP_PPCTL, mask, 0); + spin_unlock_irq(&bus->reg_lock); + } hda_dsp_stream_spib_config(sdev, hext_stream, HDA_DSP_SPIB_DISABLE, 0); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 19aad4141a78..a14733aa7a60 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -47,32 +47,34 @@ static u32 hda_get_interface_mask(struct snd_sof_dev *sdev) { const struct sof_intel_dsp_desc *chip; - u32 interface_mask = 0; + u32 interface_mask[2] = { 0 }; chip = get_chip_info(sdev->pdata); switch (chip->hw_ip_version) { case SOF_INTEL_TANGIER: case SOF_INTEL_BAYTRAIL: case SOF_INTEL_BROADWELL: - interface_mask = BIT(SOF_DAI_INTEL_SSP); + interface_mask[0] = BIT(SOF_DAI_INTEL_SSP); break; case SOF_INTEL_CAVS_1_5: case SOF_INTEL_CAVS_1_5_PLUS: - interface_mask = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | - BIT(SOF_DAI_INTEL_HDA); + interface_mask[0] = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | + BIT(SOF_DAI_INTEL_HDA); + interface_mask[1] = BIT(SOF_DAI_INTEL_HDA); break; case SOF_INTEL_CAVS_1_8: case SOF_INTEL_CAVS_2_0: case SOF_INTEL_CAVS_2_5: case SOF_INTEL_ACE_1_0: - interface_mask = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | - BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); + interface_mask[0] = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | + BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); + interface_mask[1] = BIT(SOF_DAI_INTEL_HDA); break; default: break; } - return interface_mask; + return interface_mask[sdev->dspless_mode_selected]; } #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) @@ -1058,6 +1060,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) hdev->no_ipc_position = sof_ops(sdev)->pcm_pointer ? 1 : 0; #endif + if (sdev->dspless_mode_selected) + hdev->no_ipc_position = 1; + /* set up HDA base */ bus = sof_to_bus(sdev); ret = hda_init(sdev); -- cgit From 9fc6786f549c4d71e55bd646ffb4814933286072 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 12:21:09 +0300 Subject: ASoC: SOF: Intel: hda: make DSPless mode work with DSP disabled in BIOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the DSP is disabled in the BIOS, the DSP_BAR and PP_BAR cannot be accessed. One possible objection noted in initial reviews is that this patch adds a number of branches. However the number of branches is actually limited in probe/suspend/resume routines mostly, so there isn't really a degradation in terms of readability and maintainability. Adding yet another level of abstraction/ops/callbacks would increase complexity and not really help in terms of code reuse or readability and maintainability. A split between controller and DSP driver would be even more invasive. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230404092115.27949-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 30 ++++++++++--- sound/soc/sof/intel/hda-ipc.c | 3 ++ sound/soc/sof/intel/hda-stream.c | 25 ++++++----- sound/soc/sof/intel/hda.c | 94 ++++++++++++++++++++++++++++------------ 4 files changed, 107 insertions(+), 45 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index c9231aeacc53..23c05e6f424a 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -321,6 +321,9 @@ void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_intel_dsp_desc *chip = hda->desc; + if (sdev->dspless_mode_selected) + return; + /* enable IPC DONE and BUSY interrupts */ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, HDA_DSP_REG_HIPCCTL_DONE | HDA_DSP_REG_HIPCCTL_BUSY, @@ -336,6 +339,9 @@ void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_intel_dsp_desc *chip = hda->desc; + if (sdev->dspless_mode_selected) + return; + /* disable IPC interrupt */ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, HDA_DSP_ADSPIC_IPC, 0); @@ -681,6 +687,9 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) /* power down all hda links */ hda_bus_ml_suspend(bus); + if (sdev->dspless_mode_selected) + goto skip_dsp; + ret = chip->power_down_dsp(sdev); if (ret < 0) { dev_err(sdev->dev, "failed to power down DSP during suspend\n"); @@ -694,6 +703,7 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) /* disable ppcap interrupt */ hda_dsp_ctrl_ppcap_enable(sdev, false); hda_dsp_ctrl_ppcap_int_enable(sdev, false); +skip_dsp: /* disable hda bus irq and streams */ hda_dsp_ctrl_stop_chip(sdev); @@ -744,9 +754,11 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) hda_codec_jack_check(sdev); } - /* enable ppcap interrupt */ - hda_dsp_ctrl_ppcap_enable(sdev, true); - hda_dsp_ctrl_ppcap_int_enable(sdev, true); + if (!sdev->dspless_mode_selected) { + /* enable ppcap interrupt */ + hda_dsp_ctrl_ppcap_enable(sdev, true); + hda_dsp_ctrl_ppcap_int_enable(sdev, true); + } cleanup: /* display codec can powered off after controller init */ @@ -843,8 +855,10 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev) }; int ret; - /* cancel any attempt for DSP D0I3 */ - cancel_delayed_work_sync(&hda->d0i3_work); + if (!sdev->dspless_mode_selected) { + /* cancel any attempt for DSP D0I3 */ + cancel_delayed_work_sync(&hda->d0i3_work); + } /* stop hda controller and power dsp off */ ret = hda_suspend(sdev, true); @@ -866,8 +880,10 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) }; int ret; - /* cancel any attempt for DSP D0I3 */ - cancel_delayed_work_sync(&hda->d0i3_work); + if (!sdev->dspless_mode_selected) { + /* cancel any attempt for DSP D0I3 */ + cancel_delayed_work_sync(&hda->d0i3_work); + } if (target_state == SOF_DSP_PM_D0) { /* Set DSP power state */ diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index df541b22b2d2..a838dddb1d32 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -355,6 +355,9 @@ bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev) bool ret = false; u32 irq_status; + if (sdev->dspless_mode_selected) + return false; + /* store status */ irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIS); trace_sof_intel_hda_irq_ipc_check(sdev, irq_status); diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 87e31a65b314..79d818e6a0fa 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -874,12 +874,14 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) hext_stream = &hda_stream->hext_stream; - hext_stream->pphc_addr = sdev->bar[HDA_DSP_PP_BAR] + - SOF_HDA_PPHC_BASE + SOF_HDA_PPHC_INTERVAL * i; + if (sdev->bar[HDA_DSP_PP_BAR]) { + hext_stream->pphc_addr = sdev->bar[HDA_DSP_PP_BAR] + + SOF_HDA_PPHC_BASE + SOF_HDA_PPHC_INTERVAL * i; - hext_stream->pplc_addr = sdev->bar[HDA_DSP_PP_BAR] + - SOF_HDA_PPLC_BASE + SOF_HDA_PPLC_MULTI * num_total + - SOF_HDA_PPLC_INTERVAL * i; + hext_stream->pplc_addr = sdev->bar[HDA_DSP_PP_BAR] + + SOF_HDA_PPLC_BASE + SOF_HDA_PPLC_MULTI * num_total + + SOF_HDA_PPLC_INTERVAL * i; + } hstream = &hext_stream->hstream; @@ -930,13 +932,14 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) hext_stream = &hda_stream->hext_stream; - /* we always have DSP support */ - hext_stream->pphc_addr = sdev->bar[HDA_DSP_PP_BAR] + - SOF_HDA_PPHC_BASE + SOF_HDA_PPHC_INTERVAL * i; + if (sdev->bar[HDA_DSP_PP_BAR]) { + hext_stream->pphc_addr = sdev->bar[HDA_DSP_PP_BAR] + + SOF_HDA_PPHC_BASE + SOF_HDA_PPHC_INTERVAL * i; - hext_stream->pplc_addr = sdev->bar[HDA_DSP_PP_BAR] + - SOF_HDA_PPLC_BASE + SOF_HDA_PPLC_MULTI * num_total + - SOF_HDA_PPLC_INTERVAL * i; + hext_stream->pplc_addr = sdev->bar[HDA_DSP_PP_BAR] + + SOF_HDA_PPLC_BASE + SOF_HDA_PPLC_MULTI * num_total + + SOF_HDA_PPLC_INTERVAL * i; + } hstream = &hext_stream->hstream; diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index a14733aa7a60..483ec80f3160 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -122,8 +122,12 @@ void hda_common_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable) void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable) { + u32 interface_mask = hda_get_interface_mask(sdev); const struct sof_intel_dsp_desc *chip; + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + return; + chip = get_chip_info(sdev->pdata); if (chip && chip->enable_sdw_irq) chip->enable_sdw_irq(sdev, enable); @@ -131,10 +135,14 @@ void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable) static int hda_sdw_acpi_scan(struct snd_sof_dev *sdev) { + u32 interface_mask = hda_get_interface_mask(sdev); struct sof_intel_hda_dev *hdev; acpi_handle handle; int ret; + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + return -EINVAL; + handle = ACPI_HANDLE(sdev->dev); /* save ACPI info for the probe step */ @@ -288,8 +296,12 @@ out: static bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev) { + u32 interface_mask = hda_get_interface_mask(sdev); const struct sof_intel_dsp_desc *chip; + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + return false; + chip = get_chip_info(sdev->pdata); if (chip && chip->check_sdw_irq) return chip->check_sdw_irq(sdev); @@ -304,8 +316,12 @@ static irqreturn_t hda_dsp_sdw_thread(int irq, void *context) static bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) { + u32 interface_mask = hda_get_interface_mask(sdev); struct sof_intel_hda_dev *hdev; + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + return false; + hdev = sdev->pdata->hw_pdata; if (hdev->sdw && snd_sof_dsp_read(sdev, HDA_DSP_BAR, @@ -317,8 +333,12 @@ static bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) void hda_sdw_process_wakeen(struct snd_sof_dev *sdev) { + u32 interface_mask = hda_get_interface_mask(sdev); struct sof_intel_hda_dev *hdev; + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + return; + hdev = sdev->pdata->hw_pdata; if (!hdev->sdw) return; @@ -1010,21 +1030,25 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) const struct sof_intel_dsp_desc *chip; int ret = 0; - /* - * detect DSP by checking class/subclass/prog-id information - * class=04 subclass 03 prog-if 00: no DSP, legacy driver is required - * class=04 subclass 01 prog-if 00: DSP is present - * (and may be required e.g. for DMIC or SSP support) - * class=04 subclass 03 prog-if 80: either of DSP or legacy mode works - */ - if (pci->class == 0x040300) { - dev_err(sdev->dev, "error: the DSP is not enabled on this platform, aborting probe\n"); - return -ENODEV; - } else if (pci->class != 0x040100 && pci->class != 0x040380) { - dev_err(sdev->dev, "error: unknown PCI class/subclass/prog-if 0x%06x found, aborting probe\n", pci->class); - return -ENODEV; + if (!sdev->dspless_mode_selected) { + /* + * detect DSP by checking class/subclass/prog-id information + * class=04 subclass 03 prog-if 00: no DSP, legacy driver is required + * class=04 subclass 01 prog-if 00: DSP is present + * (and may be required e.g. for DMIC or SSP support) + * class=04 subclass 03 prog-if 80: either of DSP or legacy mode works + */ + if (pci->class == 0x040300) { + dev_err(sdev->dev, "the DSP is not enabled on this platform, aborting probe\n"); + return -ENODEV; + } else if (pci->class != 0x040100 && pci->class != 0x040380) { + dev_err(sdev->dev, "unknown PCI class/subclass/prog-if 0x%06x found, aborting probe\n", + pci->class); + return -ENODEV; + } + dev_info(sdev->dev, "DSP detected with PCI class/subclass/prog-if 0x%06x\n", + pci->class); } - dev_info(sdev->dev, "DSP detected with PCI class/subclass/prog-if 0x%06x\n", pci->class); chip = get_chip_info(sdev->pdata); if (!chip) { @@ -1069,6 +1093,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) if (ret < 0) goto hdac_bus_unmap; + if (sdev->dspless_mode_selected) + goto skip_dsp_setup; + /* DSP base */ sdev->bar[HDA_DSP_BAR] = pci_ioremap_bar(pci, HDA_DSP_BAR); if (!sdev->bar[HDA_DSP_BAR]) { @@ -1079,6 +1106,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) sdev->mmio_bar = HDA_DSP_BAR; sdev->mailbox_bar = HDA_DSP_BAR; +skip_dsp_setup: /* allow 64bit DMA address if supported by H/W */ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(64))) { @@ -1144,14 +1172,16 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) if (ret < 0) goto free_ipc_irq; - /* enable ppcap interrupt */ - hda_dsp_ctrl_ppcap_enable(sdev, true); - hda_dsp_ctrl_ppcap_int_enable(sdev, true); + if (!sdev->dspless_mode_selected) { + /* enable ppcap interrupt */ + hda_dsp_ctrl_ppcap_enable(sdev, true); + hda_dsp_ctrl_ppcap_int_enable(sdev, true); - /* set default mailbox offset for FW ready message */ - sdev->dsp_box.offset = HDA_DSP_MBOX_UPLINK_OFFSET; + /* set default mailbox offset for FW ready message */ + sdev->dsp_box.offset = HDA_DSP_MBOX_UPLINK_OFFSET; - INIT_DELAYED_WORK(&hdev->d0i3_work, hda_dsp_d0i3_work); + INIT_DELAYED_WORK(&hdev->d0i3_work, hda_dsp_d0i3_work); + } init_waitqueue_head(&hdev->waitq); @@ -1167,7 +1197,8 @@ free_irq_vector: free_streams: hda_dsp_stream_free(sdev); /* dsp_unmap: not currently used */ - iounmap(sdev->bar[HDA_DSP_BAR]); + if (!sdev->dspless_mode_selected) + iounmap(sdev->bar[HDA_DSP_BAR]); hdac_bus_unmap: platform_device_unregister(hdev->dmic_dev); iounmap(bus->remap_addr); @@ -1187,8 +1218,9 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) if (nhlt) intel_nhlt_free(nhlt); - /* cancel any attempt for DSP D0I3 */ - cancel_delayed_work_sync(&hda->d0i3_work); + if (!sdev->dspless_mode_selected) + /* cancel any attempt for DSP D0I3 */ + cancel_delayed_work_sync(&hda->d0i3_work); hda_codec_device_remove(sdev); @@ -1197,14 +1229,19 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) if (!IS_ERR_OR_NULL(hda->dmic_dev)) platform_device_unregister(hda->dmic_dev); - /* disable DSP IRQ */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, - SOF_HDA_PPCTL_PIE, 0); + if (!sdev->dspless_mode_selected) { + /* disable DSP IRQ */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, + SOF_HDA_PPCTL_PIE, 0); + } /* disable CIE and GIE interrupts */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, 0); + if (sdev->dspless_mode_selected) + goto skip_disable_dsp; + /* no need to check for error as the DSP will be disabled anyway */ if (chip && chip->power_down_dsp) chip->power_down_dsp(sdev); @@ -1213,6 +1250,7 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, SOF_HDA_PPCTL_GPROCEN, 0); +skip_disable_dsp: free_irq(sdev->ipc_irq, sdev); if (sdev->msi_enabled) pci_free_irq_vectors(pci); @@ -1221,7 +1259,9 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) hda_bus_ml_free(sof_to_bus(sdev)); - iounmap(sdev->bar[HDA_DSP_BAR]); + if (!sdev->dspless_mode_selected) + iounmap(sdev->bar[HDA_DSP_BAR]); + iounmap(bus->remap_addr); sof_hda_bus_exit(sdev); -- cgit From 04957f87ae7e862216a3bc901710c82de55c4078 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:10 +0300 Subject: ASoC: SOF: Intel: pci-apl: Allow DSPless mode set the dspless_mode_supported flag to true for apl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-apl.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/pci-apl.c b/sound/soc/sof/intel/pci-apl.c index aff6cb573c27..69cad5a6bc72 100644 --- a/sound/soc/sof/intel/pci-apl.c +++ b/sound/soc/sof/intel/pci-apl.c @@ -29,6 +29,7 @@ static const struct sof_dev_desc bxt_desc = { .chip_info = &apl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/apl", @@ -60,6 +61,7 @@ static const struct sof_dev_desc glk_desc = { .chip_info = &apl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/glk", -- cgit From a417d71fd3f6a60d1cda0abf62e7961489908dca Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:11 +0300 Subject: ASoC: SOF: Intel: pci-cnl: Allow DSPless mode set the dspless_mode_supported flag to true for cnl/cfl/cml family to allow DSPless mode. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-9-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-cnl.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/pci-cnl.c b/sound/soc/sof/intel/pci-cnl.c index 4c0c1c369dcd..8895508a0be6 100644 --- a/sound/soc/sof/intel/pci-cnl.c +++ b/sound/soc/sof/intel/pci-cnl.c @@ -30,6 +30,7 @@ static const struct sof_dev_desc cnl_desc = { .chip_info = &cnl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/cnl", @@ -62,6 +63,7 @@ static const struct sof_dev_desc cfl_desc = { .chip_info = &cnl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/cnl", @@ -94,6 +96,7 @@ static const struct sof_dev_desc cml_desc = { .chip_info = &cnl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/cnl", -- cgit From 937a7fb441f5f1796398e171eef479de34a7c64f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:12 +0300 Subject: ASoC: SOF: Intel: pci-icl: Allow DSPless mode set the dspless_mode_supported flag to true for icl/jsl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-10-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-icl.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/pci-icl.c b/sound/soc/sof/intel/pci-icl.c index 6785669113b3..5fb5a820693e 100644 --- a/sound/soc/sof/intel/pci-icl.c +++ b/sound/soc/sof/intel/pci-icl.c @@ -30,6 +30,7 @@ static const struct sof_dev_desc icl_desc = { .chip_info = &icl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/icl", @@ -61,6 +62,7 @@ static const struct sof_dev_desc jsl_desc = { .chip_info = &jsl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/jsl", -- cgit From b58bbd067585af1f38cc24dbeccf98218c717281 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:13 +0300 Subject: ASoC: SOF: Intel: pci-mtl: Allow DSPless mode set the dspless_mode_supported flag to true for mtl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-11-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-mtl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/pci-mtl.c b/sound/soc/sof/intel/pci-mtl.c index b183dc0014b4..e276e1e37fed 100644 --- a/sound/soc/sof/intel/pci-mtl.c +++ b/sound/soc/sof/intel/pci-mtl.c @@ -31,6 +31,7 @@ static const struct sof_dev_desc mtl_desc = { .chip_info = &mtl_chip_info, .ipc_supported_mask = BIT(SOF_INTEL_IPC4), .ipc_default = SOF_INTEL_IPC4, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_INTEL_IPC4] = "intel/sof-ipc4/mtl", }, -- cgit From f45b1fd61e874cae0217c04406f8e99d57ddfacc Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:14 +0300 Subject: ASoC: SOF: Intel: pci-skl: Allow DSPless mode set the dspless_mode_supported flag to true for skl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-12-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-skl.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/pci-skl.c b/sound/soc/sof/intel/pci-skl.c index 5b4bccf81965..5e69af6eed34 100644 --- a/sound/soc/sof/intel/pci-skl.c +++ b/sound/soc/sof/intel/pci-skl.c @@ -26,6 +26,7 @@ static struct sof_dev_desc skl_desc = { .irqindex_host_ipc = -1, .ipc_supported_mask = BIT(SOF_INTEL_IPC4), .ipc_default = SOF_INTEL_IPC4, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_INTEL_IPC4] = "intel/avs/skl", }, @@ -50,6 +51,7 @@ static struct sof_dev_desc kbl_desc = { .irqindex_host_ipc = -1, .ipc_supported_mask = BIT(SOF_INTEL_IPC4), .ipc_default = SOF_INTEL_IPC4, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_INTEL_IPC4] = "intel/avs/kbl", }, -- cgit From 5962c2a527b52b95426167ba59a2ef01a522d077 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 4 Apr 2023 12:21:15 +0300 Subject: ASoC: SOF: Intel: pci-tgl: Allow DSPless mode set the dspless_mode_supported flag to true for tgl/adl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230404092115.27949-13-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-tgl.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c index 22e769e0831d..ca37ff1bbd2a 100644 --- a/sound/soc/sof/intel/pci-tgl.c +++ b/sound/soc/sof/intel/pci-tgl.c @@ -30,6 +30,7 @@ static const struct sof_dev_desc tgl_desc = { .chip_info = &tgl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/tgl", @@ -62,6 +63,7 @@ static const struct sof_dev_desc tglh_desc = { .chip_info = &tglh_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/tgl-h", @@ -93,6 +95,7 @@ static const struct sof_dev_desc ehl_desc = { .chip_info = &ehl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/ehl", @@ -125,6 +128,7 @@ static const struct sof_dev_desc adls_desc = { .chip_info = &adls_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/adl-s", @@ -157,6 +161,7 @@ static const struct sof_dev_desc adl_desc = { .chip_info = &tgl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/adl", @@ -189,6 +194,7 @@ static const struct sof_dev_desc adl_n_desc = { .chip_info = &tgl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/adl-n", @@ -221,6 +227,7 @@ static const struct sof_dev_desc rpls_desc = { .chip_info = &adls_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/rpl-s", @@ -253,6 +260,7 @@ static const struct sof_dev_desc rpl_desc = { .chip_info = &tgl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/rpl", -- cgit From 194f8692302cbf31d8072f3fc2710fb04720d8a0 Mon Sep 17 00:00:00 2001 From: Zihao Wang Date: Tue, 4 Apr 2023 16:46:22 +0800 Subject: ASoC: tegra20_ac97: Add missing unwind goto in tegra20_ac97_platform_probe() Smatch Warns: sound/soc/tegra/tegra20_ac97.c:321 tegra20_ac97_platform_probe() warn: missing unwind goto? The goto will set the "soc_ac97_ops" and "soc_ac97_bus" operations to NULL. But they are already NULL at this point so it is a no-op. However, just for consistency, change the direct return to a goto. No functional change. Signed-off-by: Zihao Wang Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20230404084622.1202-1-u202012060@hust.edu.cn Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_ac97.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index fea6955f7f43..c498145e76e0 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c @@ -318,7 +318,8 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) ac97->reset = devm_reset_control_get_exclusive(&pdev->dev, "ac97"); if (IS_ERR(ac97->reset)) { dev_err(&pdev->dev, "Can't retrieve ac97 reset\n"); - return PTR_ERR(ac97->reset); + ret = PTR_ERR(ac97->reset); + goto err; } ac97->clk_ac97 = devm_clk_get(&pdev->dev, NULL); -- cgit From 7ddc7f91beb285246e926e3adf0b292b071aea33 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Apr 2023 22:59:35 +0000 Subject: ASoC: soc.h: clarify Codec2Codec params snd_soc_dai_link has params/num_params, but it is unclear that params for what. This patch clarify it is params for Codec2Codec. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87o7o5c2lk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 11 +++++++++++ sound/soc/soc-dapm.c | 44 ++++++++++++++++++++++---------------------- sound/soc/soc-pcm.c | 10 +++++----- 3 files changed, 38 insertions(+), 27 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 9bbcff492c1e..04f1bc8a3128 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2294,6 +2294,9 @@ EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls); */ int snd_soc_register_card(struct snd_soc_card *card) { + struct snd_soc_dai_link *dai_link; + int i; + if (!card->name || !card->dev) return -EINVAL; @@ -2314,6 +2317,14 @@ int snd_soc_register_card(struct snd_soc_card *card) mutex_init(&card->dapm_mutex); mutex_init(&card->pcm_mutex); + /* REMOVE ME */ + for_each_card_prelinks(card, i, dai_link) { + if (!dai_link->c2c_params) { + dai_link->c2c_params = dai_link->params; + dai_link->num_c2c_params = dai_link->num_params; + } + } + return snd_soc_bind_card(card); } EXPORT_SYMBOL_GPL(snd_soc_register_card); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 34fdcb7ee079..e7a0c28e0cb1 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1075,7 +1075,7 @@ static int dapm_new_dai_link(struct snd_soc_dapm_widget *w) struct snd_soc_pcm_runtime *rtd = w->priv; /* create control for links with > 1 config */ - if (rtd->dai_link->num_params <= 1) + if (rtd->dai_link->num_c2c_params <= 1) return 0; /* add kcontrol */ @@ -3864,7 +3864,7 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, * either party on the link to alter the configuration if * necessary */ - config = rtd->dai_link->params + rtd->params_select; + config = rtd->dai_link->c2c_params + rtd->c2c_params_select; if (!config) { dev_err(w->dapm->dev, "ASoC: link config missing\n"); ret = -EINVAL; @@ -4010,7 +4010,7 @@ static int snd_soc_dapm_dai_link_get(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol); struct snd_soc_pcm_runtime *rtd = w->priv; - ucontrol->value.enumerated.item[0] = rtd->params_select; + ucontrol->value.enumerated.item[0] = rtd->c2c_params_select; return 0; } @@ -4025,13 +4025,13 @@ static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol, if (w->power) return -EBUSY; - if (ucontrol->value.enumerated.item[0] == rtd->params_select) + if (ucontrol->value.enumerated.item[0] == rtd->c2c_params_select) return 0; - if (ucontrol->value.enumerated.item[0] >= rtd->dai_link->num_params) + if (ucontrol->value.enumerated.item[0] >= rtd->dai_link->num_c2c_params) return -EINVAL; - rtd->params_select = ucontrol->value.enumerated.item[0]; + rtd->c2c_params_select = ucontrol->value.enumerated.item[0]; return 1; } @@ -4039,7 +4039,7 @@ static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol, static void snd_soc_dapm_free_kcontrol(struct snd_soc_card *card, unsigned long *private_value, - int num_params, + int num_c2c_params, const char **w_param_text) { int count; @@ -4049,7 +4049,7 @@ snd_soc_dapm_free_kcontrol(struct snd_soc_card *card, if (!w_param_text) return; - for (count = 0 ; count < num_params; count++) + for (count = 0 ; count < num_c2c_params; count++) devm_kfree(card->dev, (void *)w_param_text[count]); devm_kfree(card->dev, w_param_text); } @@ -4057,8 +4057,8 @@ snd_soc_dapm_free_kcontrol(struct snd_soc_card *card, static struct snd_kcontrol_new * snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card, char *link_name, - const struct snd_soc_pcm_stream *params, - int num_params, const char **w_param_text, + const struct snd_soc_pcm_stream *c2c_params, + int num_c2c_params, const char **w_param_text, unsigned long *private_value) { struct soc_enum w_param_enum[] = { @@ -4070,10 +4070,10 @@ snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card, snd_soc_dapm_dai_link_put), }; struct snd_kcontrol_new *kcontrol_news; - const struct snd_soc_pcm_stream *config = params; + const struct snd_soc_pcm_stream *config = c2c_params; int count; - for (count = 0 ; count < num_params; count++) { + for (count = 0 ; count < num_c2c_params; count++) { if (!config->stream_name) { dev_warn(card->dapm.dev, "ASoC: anonymous config %d for dai link %s\n", @@ -4093,7 +4093,7 @@ snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card, config++; } - w_param_enum[0].items = num_params; + w_param_enum[0].items = num_c2c_params; w_param_enum[0].texts = w_param_text; *private_value = @@ -4118,7 +4118,7 @@ snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card, return kcontrol_news; outfree_w_param: - snd_soc_dapm_free_kcontrol(card, private_value, num_params, w_param_text); + snd_soc_dapm_free_kcontrol(card, private_value, num_c2c_params, w_param_text); return NULL; } @@ -4146,17 +4146,17 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card, w_param_text = NULL; kcontrol_news = NULL; num_kcontrols = 0; - if (rtd->dai_link->num_params > 1) { + if (rtd->dai_link->num_c2c_params > 1) { w_param_text = devm_kcalloc(card->dev, - rtd->dai_link->num_params, + rtd->dai_link->num_c2c_params, sizeof(char *), GFP_KERNEL); if (!w_param_text) goto param_fail; num_kcontrols = 1; kcontrol_news = snd_soc_dapm_alloc_kcontrol(card, link_name, - rtd->dai_link->params, - rtd->dai_link->num_params, + rtd->dai_link->c2c_params, + rtd->dai_link->num_c2c_params, w_param_text, &private_value); if (!kcontrol_news) goto param_fail; @@ -4187,7 +4187,7 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card, outfree_kcontrol_news: devm_kfree(card->dev, (void *)template.kcontrol_news); snd_soc_dapm_free_kcontrol(card, &private_value, - rtd->dai_link->num_params, w_param_text); + rtd->dai_link->num_c2c_params, w_param_text); param_fail: devm_kfree(card->dev, link_name); name_fail: @@ -4336,7 +4336,7 @@ static void dapm_connect_dai_pair(struct snd_soc_card *card, struct snd_pcm_str *streams = rtd->pcm->streams; int stream; - if (dai_link->params) { + if (dai_link->c2c_params) { playback_cpu = snd_soc_dai_get_widget_capture(cpu_dai); capture_cpu = snd_soc_dai_get_widget_playback(cpu_dai); } else { @@ -4349,7 +4349,7 @@ static void dapm_connect_dai_pair(struct snd_soc_card *card, codec = snd_soc_dai_get_widget(codec_dai, stream); if (playback_cpu && codec) { - if (dai_link->params && !rtd->c2c_widget[stream]) { + if (dai_link->c2c_params && !rtd->c2c_widget[stream]) { substream = streams[stream].substream; dai = snd_soc_dapm_new_dai(card, substream, "playback"); if (IS_ERR(dai)) @@ -4368,7 +4368,7 @@ capture: codec = snd_soc_dai_get_widget(codec_dai, stream); if (codec && capture_cpu) { - if (dai_link->params && !rtd->c2c_widget[stream]) { + if (dai_link->c2c_params && !rtd->c2c_widget[stream]) { substream = streams[stream].substream; dai = snd_soc_dapm_new_dai(card, substream, "capture"); if (IS_ERR(dai)) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b830a53ceacb..913a7d98e742 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2793,9 +2793,9 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *codec_dai; /* Adapt stream for codec2codec links */ - int cpu_capture = rtd->dai_link->params ? + int cpu_capture = rtd->dai_link->c2c_params ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE; - int cpu_playback = rtd->dai_link->params ? + int cpu_playback = rtd->dai_link->c2c_params ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; for_each_rtd_codec_dais(rtd, i, codec_dai) { @@ -2839,7 +2839,7 @@ static int soc_create_pcm(struct snd_pcm **pcm, int ret; /* create the PCM */ - if (rtd->dai_link->params) { + if (rtd->dai_link->c2c_params) { snprintf(new_name, sizeof(new_name), "codec2codec(%s)", rtd->dai_link->stream_name); @@ -2896,7 +2896,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) * don't interface with the outside world or application layer * we don't have to do any special handling on close. */ - if (!rtd->dai_link->params) + if (!rtd->dai_link->c2c_params) rtd->close_delayed_work_func = snd_soc_close_delayed_work; rtd->pcm = pcm; @@ -2904,7 +2904,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) pcm->private_data = rtd; pcm->no_device_suspend = true; - if (rtd->dai_link->no_pcm || rtd->dai_link->params) { + if (rtd->dai_link->no_pcm || rtd->dai_link->c2c_params) { if (playback) pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; if (capture) -- cgit From a1cd7e8017aabe4dded887dcca30e126ec2753c3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Apr 2023 22:59:45 +0000 Subject: ASoC: audio-graph-card2: switch to use c2c_params instead of params ASoC is now using c2c_params instead of params. This patch replace it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87mt3pc2la.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card2.c | 4 ++-- sound/soc/generic/simple-card-utils.c | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'sound') diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index d145b74d41e4..25aa79dd55b3 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -920,8 +920,8 @@ int audio_graph2_link_c2c(struct asoc_simple_priv *priv, c2c_conf->channels_min = c2c_conf->channels_max = 2; /* update ME */ - dai_link->params = c2c_conf; - dai_link->num_params = 1; + dai_link->c2c_params = c2c_conf; + dai_link->num_c2c_params = 1; } ep0 = port_to_endpoint(port0); diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 34a9b91e676f..467edd96eae5 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -562,12 +562,12 @@ static int asoc_simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd, { struct snd_soc_dai_link *dai_link = rtd->dai_link; struct snd_soc_component *component; - struct snd_soc_pcm_stream *params; + struct snd_soc_pcm_stream *c2c_params; struct snd_pcm_hardware hw; int i, ret, stream; /* Do nothing if it already has Codec2Codec settings */ - if (dai_link->params) + if (dai_link->c2c_params) return 0; /* Do nothing if it was DPCM :: BE */ @@ -592,19 +592,19 @@ static int asoc_simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd, return ret; } - params = devm_kzalloc(rtd->dev, sizeof(*params), GFP_KERNEL); - if (!params) + c2c_params = devm_kzalloc(rtd->dev, sizeof(*c2c_params), GFP_KERNEL); + if (!c2c_params) return -ENOMEM; - params->formats = hw.formats; - params->rates = hw.rates; - params->rate_min = hw.rate_min; - params->rate_max = hw.rate_max; - params->channels_min = hw.channels_min; - params->channels_max = hw.channels_max; + c2c_params->formats = hw.formats; + c2c_params->rates = hw.rates; + c2c_params->rate_min = hw.rate_min; + c2c_params->rate_max = hw.rate_max; + c2c_params->channels_min = hw.channels_min; + c2c_params->channels_max = hw.channels_max; - dai_link->params = params; - dai_link->num_params = 1; + dai_link->c2c_params = c2c_params; + dai_link->num_c2c_params = 1; return 0; } -- cgit From 433f4a1697fae78c34377de1ef3abd26aec8214e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Apr 2023 22:59:57 +0000 Subject: ASoC: meson: switch to use c2c_params instead of params ASoC is now using c2c_params instead of params. This patch replace it. num_c2c_params (was num_params) was not mandatory before, but let's set it by this patch. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87lej9c2ky.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-card.c | 3 ++- sound/soc/meson/gx-card.c | 3 ++- sound/soc/meson/meson-codec-glue.c | 5 +++-- 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 2b77010c2c5c..a25c397c66c5 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -337,7 +337,8 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, return ret; if (axg_card_cpu_is_codec(dai_link->cpus->of_node)) { - dai_link->params = &codec_params; + dai_link->c2c_params = &codec_params; + dai_link->num_c2c_params = 1; } else { dai_link->no_pcm = 1; snd_soc_dai_link_set_capabilities(dai_link); diff --git a/sound/soc/meson/gx-card.c b/sound/soc/meson/gx-card.c index 5119434a81c4..58c411d3c489 100644 --- a/sound/soc/meson/gx-card.c +++ b/sound/soc/meson/gx-card.c @@ -104,7 +104,8 @@ static int gx_card_add_link(struct snd_soc_card *card, struct device_node *np, /* Or apply codec to codec params if necessary */ if (gx_card_cpu_identify(dai_link->cpus, "CODEC CTRL")) { - dai_link->params = &codec_params; + dai_link->c2c_params = &codec_params; + dai_link->num_c2c_params = 1; } else { dai_link->no_pcm = 1; snd_soc_dai_link_set_capabilities(dai_link); diff --git a/sound/soc/meson/meson-codec-glue.c b/sound/soc/meson/meson-codec-glue.c index 5913486c43ab..e702d408ee96 100644 --- a/sound/soc/meson/meson-codec-glue.c +++ b/sound/soc/meson/meson-codec-glue.c @@ -105,13 +105,14 @@ int meson_codec_glue_output_startup(struct snd_pcm_substream *substream, if (!in_data) return -ENODEV; - if (WARN_ON(!rtd->dai_link->params)) { + if (WARN_ON(!rtd->dai_link->c2c_params)) { dev_warn(dai->dev, "codec2codec link expected\n"); return -EINVAL; } /* Replace link params with the input params */ - rtd->dai_link->params = &in_data->params; + rtd->dai_link->c2c_params = &in_data->params; + rtd->dai_link->num_c2c_params = 1; return snd_soc_runtime_set_dai_fmt(rtd, in_data->fmt); } -- cgit From e7a73b05542d82e209af450dd90b730255f6e775 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Apr 2023 23:00:07 +0000 Subject: ASoC: samsung: switch to use c2c_params instead of params ASoC is now using c2c_params instead of params. This patch replace it. num_c2c_params (was num_params) was not mandatory before, but let's set it by this patch. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87jzytc2kp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/aries_wm8994.c | 6 ++++-- sound/soc/samsung/bells.c | 21 ++++++++++++++------- sound/soc/samsung/littlemill.c | 3 ++- sound/soc/samsung/lowland.c | 3 ++- sound/soc/samsung/speyside.c | 3 ++- 5 files changed, 24 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/soc/samsung/aries_wm8994.c b/sound/soc/samsung/aries_wm8994.c index 0fbbf3b02c09..7492bb41456c 100644 --- a/sound/soc/samsung/aries_wm8994.c +++ b/sound/soc/samsung/aries_wm8994.c @@ -483,14 +483,16 @@ static struct snd_soc_dai_link aries_dai[] = { .name = "WM8994 AIF2", .stream_name = "Baseband", .init = &aries_baseband_init, - .params = &baseband_params, + .c2c_params = &baseband_params, + .num_c2c_params = 1, .ignore_suspend = 1, SND_SOC_DAILINK_REG(baseband), }, { .name = "WM8994 AIF3", .stream_name = "Bluetooth", - .params = &bluetooth_params, + .c2c_params = &bluetooth_params, + .num_c2c_params = 1, .ignore_suspend = 1, SND_SOC_DAILINK_REG(bluetooth), }, diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c index 76998a4a4cad..70b63d4faa99 100644 --- a/sound/soc/samsung/bells.c +++ b/sound/soc/samsung/bells.c @@ -264,7 +264,8 @@ static struct snd_soc_dai_link bells_dai_wm2200[] = { .stream_name = "DSP-CODEC", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, - .params = &sub_params, + .c2c_params = &sub_params, + .num_c2c_params = 1, .ignore_suspend = 1, SND_SOC_DAILINK_REG(wm2200_dsp_codec), }, @@ -300,7 +301,8 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = { .stream_name = "DSP-CODEC", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, - .params = &sub_params, + .c2c_params = &sub_params, + .num_c2c_params = 1, .ignore_suspend = 1, SND_SOC_DAILINK_REG(wm5102_dsp_codec), }, @@ -310,7 +312,8 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, - .params = &baseband_params, + .c2c_params = &baseband_params, + .num_c2c_params = 1, SND_SOC_DAILINK_REG(wm5102_baseband), }, { @@ -319,7 +322,8 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ignore_suspend = 1, - .params = &sub_params, + .c2c_params = &sub_params, + .num_c2c_params = 1, SND_SOC_DAILINK_REG(wm5102_sub), }, }; @@ -355,7 +359,8 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = { .stream_name = "DSP-CODEC", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, - .params = &sub_params, + .c2c_params = &sub_params, + .num_c2c_params = 1, .ignore_suspend = 1, SND_SOC_DAILINK_REG(wm5110_dsp_codec), }, @@ -365,7 +370,8 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, - .params = &baseband_params, + .c2c_params = &baseband_params, + .num_c2c_params = 1, SND_SOC_DAILINK_REG(wm5110_baseband), }, { @@ -374,7 +380,8 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ignore_suspend = 1, - .params = &sub_params, + .c2c_params = &sub_params, + .num_c2c_params = 1, SND_SOC_DAILINK_REG(wm5110_sub), }, }; diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c index 411e25cec591..5d8118e69359 100644 --- a/sound/soc/samsung/littlemill.c +++ b/sound/soc/samsung/littlemill.c @@ -167,7 +167,8 @@ static struct snd_soc_dai_link littlemill_dai[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, - .params = &baseband_params, + .c2c_params = &baseband_params, + .num_c2c_params = 1, SND_SOC_DAILINK_REG(baseband), }, }; diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c index b44f5e92224f..106770be6fc5 100644 --- a/sound/soc/samsung/lowland.c +++ b/sound/soc/samsung/lowland.c @@ -119,7 +119,8 @@ static struct snd_soc_dai_link lowland_dai[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ignore_suspend = 1, - .params = &sub_params, + .c2c_params = &sub_params, + .num_c2c_params = 1, .init = lowland_wm9081_init, SND_SOC_DAILINK_REG(speaker), }, diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 69d7b0115b38..22e2ad63d64d 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -219,7 +219,8 @@ static struct snd_soc_dai_link speyside_dai[] = { .init = speyside_wm8996_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, - .params = &dsp_codec_params, + .c2c_params = &dsp_codec_params, + .num_c2c_params = 1, .ignore_suspend = 1, SND_SOC_DAILINK_REG(dsp_codec), }, -- cgit From 1ea63f29c27712d6b9c45af67cd71299d849c5e3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Apr 2023 23:00:17 +0000 Subject: ASoC: soc.h: remove unused params/num_params No drivers are using params/num_params any more. Let's remove these. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87iledc2ke.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 04f1bc8a3128..9bbcff492c1e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2294,9 +2294,6 @@ EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls); */ int snd_soc_register_card(struct snd_soc_card *card) { - struct snd_soc_dai_link *dai_link; - int i; - if (!card->name || !card->dev) return -EINVAL; @@ -2317,14 +2314,6 @@ int snd_soc_register_card(struct snd_soc_card *card) mutex_init(&card->dapm_mutex); mutex_init(&card->pcm_mutex); - /* REMOVE ME */ - for_each_card_prelinks(card, i, dai_link) { - if (!dai_link->c2c_params) { - dai_link->c2c_params = dai_link->params; - dai_link->num_c2c_params = dai_link->num_params; - } - } - return snd_soc_bind_card(card); } EXPORT_SYMBOL_GPL(snd_soc_register_card); -- cgit From 3456aeb02a28e82235d45da434752e6f441427f0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Apr 2023 22:57:55 +0000 Subject: ASoC: soc-dapm.c: tidyup dapm_connect_dai_pair() dapm_connect_dai_pair() handles "Normal/Codec2Codec" x "CPU/Codec" x "Playback/Capture". (A) is "Codec2Codec" case of "CPU" widget x "Playback/Capture", (B) is "Normal" case of "CPU" widget x "Playback/Capture", (C) is each case of "Codec" widget. (X) is handling "Playback" case DAI connecting, (Y) is handling "Capture" case DAI connecting. static void dapm_connect_dai_pair(...) { ... (A) if (dai_link->params) { playback_cpu = ... capture_cpu = ... (B) } else { playback_cpu = ... capture_cpu = ... } ^ /* connect BE DAI playback if widgets are valid */ | stream = SNDRV_PCM_STREAM_PLAYBACK; | (C) codec = codec_dai->playback_widget; | | if (playback_cpu && codec) { (X) if (dai_link->params && !rtd->c2c_widget[stream]) { | ... | } | | (z) dapm_connect_dai_routes(...); v } capture: ^ /* connect BE DAI capture if widgets are valid */ | stream = SNDRV_PCM_STREAM_CAPTURE; | (C) codec = codec_dai->capture_widget; | | if (codec && capture_cpu) { (Y) if (dai_link->params && !rtd->c2c_widget[stream]) { | ... | } | | (z) dapm_connect_dai_routes(...); v } } (X) part and (Y) part are almost same. Main purpose of these parts (and this function) is calling dapm_connect_dai_routes() (= z) on each cases. The difference is "parameter" (= Normal/Codec2Codec x CPU/Codec x Playback/Capture). This patch cleanup these, but nothing changed for meaning. Link: https://lore.kernel.org/r/87ilen6ni4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/877cuqvswc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 93 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 36 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index e7a0c28e0cb1..36e6f261bcf7 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4325,60 +4325,81 @@ static void dapm_connect_dai_routes(struct snd_soc_dapm_context *dapm, snd_soc_dapm_add_path(dapm, src, sink, NULL, NULL); } +static int get_stream_cpu(struct snd_soc_dai_link *dai_link, int stream) +{ + /* + * [Normal] + * + * Playback + * CPU : SNDRV_PCM_STREAM_PLAYBACK + * Codec: SNDRV_PCM_STREAM_PLAYBACK + * + * Playback + * CPU : SNDRV_PCM_STREAM_CAPTURE + * Codec: SNDRV_PCM_STREAM_CAPTURE + */ + if (!dai_link->c2c_params) + return stream; + + /* + * [Codec2Codec] + * + * Playback + * CPU : SNDRV_PCM_STREAM_CAPTURE + * Codec: SNDRV_PCM_STREAM_PLAYBACK + * + * Capture + * CPU : SNDRV_PCM_STREAM_PLAYBACK + * Codec: SNDRV_PCM_STREAM_CAPTURE + */ + if (stream == SNDRV_PCM_STREAM_CAPTURE) + return SNDRV_PCM_STREAM_PLAYBACK; + + return SNDRV_PCM_STREAM_CAPTURE; +} + static void dapm_connect_dai_pair(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *codec_dai, struct snd_soc_dai *cpu_dai) { struct snd_soc_dai_link *dai_link = rtd->dai_link; - struct snd_soc_dapm_widget *dai, *codec, *playback_cpu, *capture_cpu; - struct snd_pcm_substream *substream; - struct snd_pcm_str *streams = rtd->pcm->streams; + struct snd_soc_dapm_widget *codec, *cpu; + struct snd_soc_dai *src_dai[] = { cpu_dai, codec_dai }; + struct snd_soc_dai *sink_dai[] = { codec_dai, cpu_dai }; + struct snd_soc_dapm_widget **src[] = { &cpu, &codec }; + struct snd_soc_dapm_widget **sink[] = { &codec, &cpu }; + char *widget_name[] = { "playback", "capture" }; int stream; - if (dai_link->c2c_params) { - playback_cpu = snd_soc_dai_get_widget_capture(cpu_dai); - capture_cpu = snd_soc_dai_get_widget_playback(cpu_dai); - } else { - playback_cpu = snd_soc_dai_get_widget_playback(cpu_dai); - capture_cpu = snd_soc_dai_get_widget_capture(cpu_dai); - } + for_each_pcm_streams(stream) { + int stream_cpu, stream_codec; - /* connect BE DAI playback if widgets are valid */ - stream = SNDRV_PCM_STREAM_PLAYBACK; - codec = snd_soc_dai_get_widget(codec_dai, stream); + stream_cpu = get_stream_cpu(dai_link, stream); + stream_codec = stream; - if (playback_cpu && codec) { - if (dai_link->c2c_params && !rtd->c2c_widget[stream]) { - substream = streams[stream].substream; - dai = snd_soc_dapm_new_dai(card, substream, "playback"); - if (IS_ERR(dai)) - goto capture; - rtd->c2c_widget[stream] = dai; - } + /* connect BE DAI playback if widgets are valid */ + cpu = snd_soc_dai_get_widget(cpu_dai, stream_cpu); + codec = snd_soc_dai_get_widget(codec_dai, stream_codec); - dapm_connect_dai_routes(&card->dapm, cpu_dai, playback_cpu, - rtd->c2c_widget[stream], - codec_dai, codec); - } - -capture: - /* connect BE DAI capture if widgets are valid */ - stream = SNDRV_PCM_STREAM_CAPTURE; - codec = snd_soc_dai_get_widget(codec_dai, stream); + if (!cpu || !codec) + continue; - if (codec && capture_cpu) { + /* special handling for [Codec2Codec] */ if (dai_link->c2c_params && !rtd->c2c_widget[stream]) { - substream = streams[stream].substream; - dai = snd_soc_dapm_new_dai(card, substream, "capture"); + struct snd_pcm_substream *substream = rtd->pcm->streams[stream].substream; + struct snd_soc_dapm_widget *dai = snd_soc_dapm_new_dai(card, substream, + widget_name[stream]); + if (IS_ERR(dai)) - return; + continue; + rtd->c2c_widget[stream] = dai; } - dapm_connect_dai_routes(&card->dapm, codec_dai, codec, + dapm_connect_dai_routes(&card->dapm, src_dai[stream], *src[stream], rtd->c2c_widget[stream], - cpu_dai, capture_cpu); + sink_dai[stream], *sink[stream]); } } -- cgit From 63a511284c9ea72696a5dd0a2d2721bdef19f774 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Thu, 6 Apr 2023 16:55:35 +0800 Subject: ASoC: rt712-sdca: Add RT712 SDCA driver for Mic topology This is the initial codec driver for rt712 SDCA (Mic topology). The host should connect with rt712 SdW2 interface. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20230406085535.52002-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 7 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rt712-sdca-dmic.c | 983 +++++++++++++++++++++++++++++++++++++ sound/soc/codecs/rt712-sdca-dmic.h | 108 ++++ 4 files changed, 1100 insertions(+) create mode 100644 sound/soc/codecs/rt712-sdca-dmic.c create mode 100644 sound/soc/codecs/rt712-sdca-dmic.h (limited to 'sound') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 4062fe3fbb1c..79d2362ad055 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -204,6 +204,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_RT711_SDW imply SND_SOC_RT711_SDCA_SDW imply SND_SOC_RT712_SDCA_SDW + imply SND_SOC_RT712_SDCA_DMIC_SDW imply SND_SOC_RT715_SDW imply SND_SOC_RT715_SDCA_SDW imply SND_SOC_RT1308_SDW @@ -1532,6 +1533,12 @@ config SND_SOC_RT712_SDCA_SDW select REGMAP_SOUNDWIRE select REGMAP_SOUNDWIRE_MBQ +config SND_SOC_RT712_SDCA_DMIC_SDW + tristate "Realtek RT712 SDCA DMIC Codec - SDW" + depends on SOUNDWIRE + select REGMAP_SOUNDWIRE + select REGMAP_SOUNDWIRE_MBQ + config SND_SOC_RT715 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 44ea747579fd..5cdbae88e6e3 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -234,6 +234,7 @@ snd-soc-rt700-objs := rt700.o rt700-sdw.o snd-soc-rt711-objs := rt711.o rt711-sdw.o snd-soc-rt711-sdca-objs := rt711-sdca.o rt711-sdca-sdw.o snd-soc-rt712-sdca-objs := rt712-sdca.o rt712-sdca-sdw.o +snd-soc-rt712-sdca-dmic-objs := rt712-sdca-dmic.o snd-soc-rt715-objs := rt715.o rt715-sdw.o snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o snd-soc-rt9120-objs := rt9120.o @@ -603,6 +604,7 @@ obj-$(CONFIG_SND_SOC_RT700) += snd-soc-rt700.o obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o obj-$(CONFIG_SND_SOC_RT711_SDCA_SDW) += snd-soc-rt711-sdca.o obj-$(CONFIG_SND_SOC_RT712_SDCA_SDW) += snd-soc-rt712-sdca.o +obj-$(CONFIG_SND_SOC_RT712_SDCA_DMIC_SDW) += snd-soc-rt712-sdca-dmic.o obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o obj-$(CONFIG_SND_SOC_RT9120) += snd-soc-rt9120.o diff --git a/sound/soc/codecs/rt712-sdca-dmic.c b/sound/soc/codecs/rt712-sdca-dmic.c new file mode 100644 index 000000000000..09807b6d6353 --- /dev/null +++ b/sound/soc/codecs/rt712-sdca-dmic.c @@ -0,0 +1,983 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// rt712-sdca-dmic.c -- rt712 SDCA DMIC ALSA SoC audio driver +// +// Copyright(c) 2023 Realtek Semiconductor Corp. +// +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rt712-sdca.h" +#include "rt712-sdca-dmic.h" + +static bool rt712_sdca_dmic_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x201a ... 0x201f: + case 0x2029 ... 0x202a: + case 0x202d ... 0x2034: + case 0x2230 ... 0x2232: + case 0x2f01 ... 0x2f0a: + case 0x2f35 ... 0x2f36: + case 0x2f52: + case 0x2f58 ... 0x2f59: + case 0x3201: + case 0x320c: + return true; + default: + return false; + } +} + +static bool rt712_sdca_dmic_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x201b: + case 0x201c: + case 0x201d: + case 0x201f: + case 0x202d ... 0x202f: + case 0x2230: + case 0x2f01: + case 0x2f35: + case 0x320c: + return true; + default: + return false; + } +} + +static bool rt712_sdca_dmic_mbq_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x2000000 ... 0x200008e: + case 0x5300000 ... 0x530000e: + case 0x5400000 ... 0x540000e: + case 0x5600000 ... 0x5600008: + case 0x5700000 ... 0x570000d: + case 0x5800000 ... 0x5800021: + case 0x5900000 ... 0x5900028: + case 0x5a00000 ... 0x5a00009: + case 0x5b00000 ... 0x5b00051: + case 0x5c00000 ... 0x5c0009a: + case 0x5d00000 ... 0x5d00009: + case 0x5f00000 ... 0x5f00030: + case 0x6100000 ... 0x6100068: + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_01): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_02): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_03): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_04): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_01): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_02): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_03): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_04): + return true; + default: + return false; + } +} + +static bool rt712_sdca_dmic_mbq_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x2000000: + case 0x200001a: + case 0x2000024: + case 0x2000046: + case 0x200008a: + case 0x5800000: + case 0x5800001: + case 0x6100008: + return true; + default: + return false; + } +} + +static const struct regmap_config rt712_sdca_dmic_regmap = { + .reg_bits = 32, + .val_bits = 8, + .readable_reg = rt712_sdca_dmic_readable_register, + .volatile_reg = rt712_sdca_dmic_volatile_register, + .max_register = 0x40981300, + .reg_defaults = rt712_sdca_dmic_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(rt712_sdca_dmic_reg_defaults), + .cache_type = REGCACHE_RBTREE, + .use_single_read = true, + .use_single_write = true, +}; + +static const struct regmap_config rt712_sdca_dmic_mbq_regmap = { + .name = "sdw-mbq", + .reg_bits = 32, + .val_bits = 16, + .readable_reg = rt712_sdca_dmic_mbq_readable_register, + .volatile_reg = rt712_sdca_dmic_mbq_volatile_register, + .max_register = 0x40800f14, + .reg_defaults = rt712_sdca_dmic_mbq_defaults, + .num_reg_defaults = ARRAY_SIZE(rt712_sdca_dmic_mbq_defaults), + .cache_type = REGCACHE_RBTREE, + .use_single_read = true, + .use_single_write = true, +}; + +static int rt712_sdca_dmic_index_write(struct rt712_sdca_dmic_priv *rt712, + unsigned int nid, unsigned int reg, unsigned int value) +{ + int ret; + struct regmap *regmap = rt712->mbq_regmap; + unsigned int addr = (nid << 20) | reg; + + ret = regmap_write(regmap, addr, value); + if (ret < 0) + dev_err(&rt712->slave->dev, + "Failed to set private value: %06x <= %04x ret=%d\n", + addr, value, ret); + + return ret; +} + +static int rt712_sdca_dmic_index_read(struct rt712_sdca_dmic_priv *rt712, + unsigned int nid, unsigned int reg, unsigned int *value) +{ + int ret; + struct regmap *regmap = rt712->mbq_regmap; + unsigned int addr = (nid << 20) | reg; + + ret = regmap_read(regmap, addr, value); + if (ret < 0) + dev_err(&rt712->slave->dev, + "Failed to get private value: %06x => %04x ret=%d\n", + addr, *value, ret); + + return ret; +} + +static int rt712_sdca_dmic_index_update_bits(struct rt712_sdca_dmic_priv *rt712, + unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val) +{ + unsigned int tmp; + int ret; + + ret = rt712_sdca_dmic_index_read(rt712, nid, reg, &tmp); + if (ret < 0) + return ret; + + set_mask_bits(&tmp, mask, val); + return rt712_sdca_dmic_index_write(rt712, nid, reg, tmp); +} + +static int rt712_sdca_dmic_io_init(struct device *dev, struct sdw_slave *slave) +{ + struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(dev); + + if (rt712->hw_init) + return 0; + + if (rt712->first_hw_init) { + regcache_cache_only(rt712->regmap, false); + regcache_cache_bypass(rt712->regmap, true); + regcache_cache_only(rt712->mbq_regmap, false); + regcache_cache_bypass(rt712->mbq_regmap, true); + } else { + /* + * PM runtime is only enabled when a Slave reports as Attached + */ + + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(&slave->dev, 3000); + pm_runtime_use_autosuspend(&slave->dev); + + /* update count of parent 'active' children */ + pm_runtime_set_active(&slave->dev); + + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(&slave->dev); + + pm_runtime_enable(&slave->dev); + } + + pm_runtime_get_noresume(&slave->dev); + + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_ADC0A_08_PDE_FLOAT_CTL, 0x1112); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_ADC0B_11_PDE_FLOAT_CTL, 0x1111); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_DMIC1_2_PDE_FLOAT_CTL, 0x1111); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_I2S_IN_OUT_PDE_FLOAT_CTL, 0x1155); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_DMIC_ENT_FLOAT_CTL, 0x2626); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_ADC_ENT_FLOAT_CTL, 0x1e19); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_DMIC_GAIN_ENT_FLOAT_CTL0, 0x1515); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_ADC_VOL_CH_FLOAT_CTL2, 0x0304); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_DMIC_GAIN_ENT_FLOAT_CTL2, 0x0304); + rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, + RT712_HDA_LEGACY_CONFIG_CTL0, 0x0050); + regmap_write(rt712->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_IT26, RT712_SDCA_CTL_VENDOR_DEF, 0), 0x01); + rt712_sdca_dmic_index_write(rt712, RT712_ULTRA_SOUND_DET, + RT712_ULTRA_SOUND_DETECTOR6, 0x3200); + regmap_write(rt712->regmap, RT712_RC_CAL, 0x23); + regmap_write(rt712->regmap, 0x2f52, 0x00); + + if (rt712->first_hw_init) { + regcache_cache_bypass(rt712->regmap, false); + regcache_mark_dirty(rt712->regmap); + regcache_cache_bypass(rt712->mbq_regmap, false); + regcache_mark_dirty(rt712->mbq_regmap); + } else + rt712->first_hw_init = true; + + /* Mark Slave initialization complete */ + rt712->hw_init = true; + + pm_runtime_mark_last_busy(&slave->dev); + pm_runtime_put_autosuspend(&slave->dev); + + dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); + return 0; +} + +static int rt712_sdca_dmic_set_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); + struct rt712_sdca_dmic_kctrl_priv *p = + (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; + unsigned int regvalue, ctl, i; + unsigned int adc_vol_flag = 0; + const unsigned int interval_offset = 0xc0; + + if (strstr(ucontrol->id.name, "FU1E Capture Volume")) + adc_vol_flag = 1; + + /* check all channels */ + for (i = 0; i < p->count; i++) { + regmap_read(rt712->mbq_regmap, p->reg_base + i, ®value); + + if (!adc_vol_flag) /* boost gain */ + ctl = regvalue / 0x0a00; + else { /* ADC gain */ + if (adc_vol_flag) + ctl = p->max - (((0x1e00 - regvalue) & 0xffff) / interval_offset); + else + ctl = p->max - (((0 - regvalue) & 0xffff) / interval_offset); + } + + ucontrol->value.integer.value[i] = ctl; + } + + return 0; +} + +static int rt712_sdca_dmic_set_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt712_sdca_dmic_kctrl_priv *p = + (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); + unsigned int gain_val[4]; + unsigned int i, adc_vol_flag = 0, changed = 0; + unsigned int regvalue[4]; + const unsigned int interval_offset = 0xc0; + int err; + + if (strstr(ucontrol->id.name, "FU1E Capture Volume")) + adc_vol_flag = 1; + + /* check all channels */ + for (i = 0; i < p->count; i++) { + regmap_read(rt712->mbq_regmap, p->reg_base + i, ®value[i]); + + gain_val[i] = ucontrol->value.integer.value[i]; + if (gain_val[i] > p->max) + gain_val[i] = p->max; + + if (!adc_vol_flag) /* boost gain */ + gain_val[i] = gain_val[i] * 0x0a00; + else { /* ADC gain */ + gain_val[i] = 0x1e00 - ((p->max - gain_val[i]) * interval_offset); + gain_val[i] &= 0xffff; + } + + if (regvalue[i] != gain_val[i]) + changed = 1; + } + + if (!changed) + return 0; + + for (i = 0; i < p->count; i++) { + err = regmap_write(rt712->mbq_regmap, p->reg_base + i, gain_val[i]); + if (err < 0) + dev_err(&rt712->slave->dev, "0x%08x can't be set\n", p->reg_base + i); + } + + return changed; +} + +static int rt712_sdca_set_fu1e_capture_ctl(struct rt712_sdca_dmic_priv *rt712) +{ + int err, i; + unsigned int ch_mute; + + for (i = 0; i < ARRAY_SIZE(rt712->fu1e_mixer_mute); i++) { + ch_mute = (rt712->fu1e_dapm_mute || rt712->fu1e_mixer_mute[i]) ? 0x01 : 0x00; + err = regmap_write(rt712->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, + RT712_SDCA_CTL_FU_MUTE, CH_01) + i, ch_mute); + if (err < 0) + return err; + } + + return 0; +} + +static int rt712_sdca_dmic_fu1e_capture_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + struct rt712_sdca_dmic_kctrl_priv *p = + (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; + unsigned int i; + + for (i = 0; i < p->count; i++) + ucontrol->value.integer.value[i] = !rt712->fu1e_mixer_mute[i]; + + return 0; +} + +static int rt712_sdca_dmic_fu1e_capture_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + struct rt712_sdca_dmic_kctrl_priv *p = + (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; + int err, changed = 0, i; + + for (i = 0; i < p->count; i++) { + if (rt712->fu1e_mixer_mute[i] != !ucontrol->value.integer.value[i]) + changed = 1; + rt712->fu1e_mixer_mute[i] = !ucontrol->value.integer.value[i]; + } + + err = rt712_sdca_set_fu1e_capture_ctl(rt712); + if (err < 0) + return err; + + return changed; +} + +static int rt712_sdca_fu_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct rt712_sdca_dmic_kctrl_priv *p = + (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; + + if (p->max == 1) + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + else + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = p->count; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = p->max; + return 0; +} + +#define RT712_SDCA_PR_VALUE(xreg_base, xcount, xmax, xinvert) \ + ((unsigned long)&(struct rt712_sdca_dmic_kctrl_priv) \ + {.reg_base = xreg_base, .count = xcount, .max = xmax, \ + .invert = xinvert}) + +#define RT712_SDCA_FU_CTRL(xname, reg_base, xmax, xinvert, xcount) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .info = rt712_sdca_fu_info, \ + .get = rt712_sdca_dmic_fu1e_capture_get, \ + .put = rt712_sdca_dmic_fu1e_capture_put, \ + .private_value = RT712_SDCA_PR_VALUE(reg_base, xcount, xmax, xinvert)} + +#define RT712_SDCA_EXT_TLV(xname, reg_base, xhandler_get,\ + xhandler_put, xcount, xmax, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ + SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .tlv.p = (tlv_array), \ + .info = rt712_sdca_fu_info, \ + .get = xhandler_get, .put = xhandler_put, \ + .private_value = RT712_SDCA_PR_VALUE(reg_base, xcount, xmax, 0) } + +static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0); +static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); + +static const struct snd_kcontrol_new rt712_sdca_dmic_snd_controls[] = { + RT712_SDCA_FU_CTRL("FU1E Capture Switch", + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_01), + 1, 1, 4), + RT712_SDCA_EXT_TLV("FU1E Capture Volume", + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_01), + rt712_sdca_dmic_set_gain_get, rt712_sdca_dmic_set_gain_put, 4, 0x3f, in_vol_tlv), + RT712_SDCA_EXT_TLV("FU15 Boost Volume", + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_01), + rt712_sdca_dmic_set_gain_get, rt712_sdca_dmic_set_gain_put, 4, 3, mic_vol_tlv), +}; + +static int rt712_sdca_dmic_mux_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + unsigned int val = 0, mask_sft; + + if (strstr(ucontrol->id.name, "ADC 25 Mux")) + mask_sft = 8; + else if (strstr(ucontrol->id.name, "ADC 26 Mux")) + mask_sft = 4; + else + return -EINVAL; + + rt712_sdca_dmic_index_read(rt712, RT712_VENDOR_HDA_CTL, + RT712_HDA_LEGACY_MUX_CTL0, &val); + + ucontrol->value.enumerated.item[0] = (val >> mask_sft) & 0x7; + + return 0; +} + +static int rt712_sdca_dmic_mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int *item = ucontrol->value.enumerated.item; + unsigned int val, val2 = 0, change, mask_sft; + + if (item[0] >= e->items) + return -EINVAL; + + if (strstr(ucontrol->id.name, "ADC 25 Mux")) + mask_sft = 8; + else if (strstr(ucontrol->id.name, "ADC 26 Mux")) + mask_sft = 4; + else + return -EINVAL; + + val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; + + rt712_sdca_dmic_index_read(rt712, RT712_VENDOR_HDA_CTL, + RT712_HDA_LEGACY_MUX_CTL0, &val2); + val2 = (0x7 << mask_sft) & val2; + + if (val == val2) + change = 0; + else + change = 1; + + if (change) + rt712_sdca_dmic_index_update_bits(rt712, RT712_VENDOR_HDA_CTL, + RT712_HDA_LEGACY_MUX_CTL0, 0x7 << mask_sft, + val << mask_sft); + + snd_soc_dapm_mux_update_power(dapm, kcontrol, + item[0], e, NULL); + + return change; +} + +static const char * const adc_mux_text[] = { + "DMIC1", + "DMIC2", +}; + +static SOC_ENUM_SINGLE_DECL( + rt712_adc25_enum, SND_SOC_NOPM, 0, adc_mux_text); + +static SOC_ENUM_SINGLE_DECL( + rt712_adc26_enum, SND_SOC_NOPM, 0, adc_mux_text); + +static const struct snd_kcontrol_new rt712_sdca_dmic_adc25_mux = + SOC_DAPM_ENUM_EXT("ADC 25 Mux", rt712_adc25_enum, + rt712_sdca_dmic_mux_get, rt712_sdca_dmic_mux_put); + +static const struct snd_kcontrol_new rt712_sdca_dmic_adc26_mux = + SOC_DAPM_ENUM_EXT("ADC 26 Mux", rt712_adc26_enum, + rt712_sdca_dmic_mux_get, rt712_sdca_dmic_mux_put); + +static int rt712_sdca_dmic_fu1e_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + rt712->fu1e_dapm_mute = false; + rt712_sdca_set_fu1e_capture_ctl(rt712); + break; + case SND_SOC_DAPM_PRE_PMD: + rt712->fu1e_dapm_mute = true; + rt712_sdca_set_fu1e_capture_ctl(rt712); + break; + } + return 0; +} + +static int rt712_sdca_dmic_pde11_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + unsigned char ps0 = 0x0, ps3 = 0x3; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt712->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PDE11, + RT712_SDCA_CTL_REQ_POWER_STATE, 0), + ps0); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt712->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PDE11, + RT712_SDCA_CTL_REQ_POWER_STATE, 0), + ps3); + break; + } + return 0; +} + +static const struct snd_soc_dapm_widget rt712_sdca_dmic_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("DMIC1"), + SND_SOC_DAPM_INPUT("DMIC2"), + + SND_SOC_DAPM_SUPPLY("PDE 11", SND_SOC_NOPM, 0, 0, + rt712_sdca_dmic_pde11_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_ADC_E("FU 1E", NULL, SND_SOC_NOPM, 0, 0, + rt712_sdca_dmic_fu1e_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_MUX("ADC 25 Mux", SND_SOC_NOPM, 0, 0, + &rt712_sdca_dmic_adc25_mux), + SND_SOC_DAPM_MUX("ADC 26 Mux", SND_SOC_NOPM, 0, 0, + &rt712_sdca_dmic_adc26_mux), + + SND_SOC_DAPM_AIF_OUT("DP2TX", "DP2 Capture", 0, SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_dapm_route rt712_sdca_dmic_audio_map[] = { + {"DP2TX", NULL, "FU 1E"}, + + {"FU 1E", NULL, "PDE 11"}, + {"FU 1E", NULL, "ADC 25 Mux"}, + {"FU 1E", NULL, "ADC 26 Mux"}, + {"ADC 25 Mux", "DMIC1", "DMIC1"}, + {"ADC 25 Mux", "DMIC2", "DMIC2"}, + {"ADC 26 Mux", "DMIC1", "DMIC1"}, + {"ADC 26 Mux", "DMIC2", "DMIC2"}, +}; + +static int rt712_sdca_dmic_probe(struct snd_soc_component *component) +{ + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + int ret; + + rt712->component = component; + + ret = pm_runtime_resume(component->dev); + if (ret < 0 && ret != -EACCES) + return ret; + + return 0; +} + +static const struct snd_soc_component_driver soc_sdca_dev_rt712_dmic = { + .probe = rt712_sdca_dmic_probe, + .controls = rt712_sdca_dmic_snd_controls, + .num_controls = ARRAY_SIZE(rt712_sdca_dmic_snd_controls), + .dapm_widgets = rt712_sdca_dmic_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt712_sdca_dmic_dapm_widgets), + .dapm_routes = rt712_sdca_dmic_audio_map, + .num_dapm_routes = ARRAY_SIZE(rt712_sdca_dmic_audio_map), + .endianness = 1, +}; + +static int rt712_sdca_dmic_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, + int direction) +{ + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); + + return 0; +} + +static void rt712_sdca_dmic_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + snd_soc_dai_set_dma_data(dai, substream, NULL); +} + +static int rt712_sdca_dmic_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + struct sdw_stream_config stream_config; + struct sdw_port_config port_config; + struct sdw_stream_runtime *sdw_stream; + int retval, num_channels; + unsigned int sampling_rate; + + dev_dbg(dai->dev, "%s %s", __func__, dai->name); + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); + + if (!sdw_stream) + return -EINVAL; + + if (!rt712->slave) + return -EINVAL; + + stream_config.frame_rate = params_rate(params); + stream_config.ch_count = params_channels(params); + stream_config.bps = snd_pcm_format_width(params_format(params)); + stream_config.direction = SDW_DATA_DIR_TX; + + num_channels = params_channels(params); + port_config.ch_mask = GENMASK(num_channels - 1, 0); + port_config.num = 2; + + retval = sdw_stream_add_slave(rt712->slave, &stream_config, + &port_config, 1, sdw_stream); + if (retval) { + dev_err(dai->dev, "Unable to configure port\n"); + return retval; + } + + if (params_channels(params) > 4) { + dev_err(component->dev, "Unsupported channels %d\n", + params_channels(params)); + return -EINVAL; + } + + /* sampling rate configuration */ + switch (params_rate(params)) { + case 16000: + sampling_rate = RT712_SDCA_RATE_16000HZ; + break; + case 32000: + sampling_rate = RT712_SDCA_RATE_32000HZ; + break; + case 44100: + sampling_rate = RT712_SDCA_RATE_44100HZ; + break; + case 48000: + sampling_rate = RT712_SDCA_RATE_48000HZ; + break; + case 96000: + sampling_rate = RT712_SDCA_RATE_96000HZ; + break; + case 192000: + sampling_rate = RT712_SDCA_RATE_192000HZ; + break; + default: + dev_err(component->dev, "Rate %d is not supported\n", + params_rate(params)); + return -EINVAL; + } + + /* set sampling frequency */ + regmap_write(rt712->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_CS1F, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), + sampling_rate); + regmap_write(rt712->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_CS1C, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), + sampling_rate); + + return 0; +} + +static int rt712_sdca_dmic_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(component); + struct sdw_stream_runtime *sdw_stream = + snd_soc_dai_get_dma_data(dai, substream); + + if (!rt712->slave) + return -EINVAL; + + sdw_stream_remove_slave(rt712->slave, sdw_stream); + return 0; +} + +#define RT712_STEREO_RATES (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) +#define RT712_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE) + +static const struct snd_soc_dai_ops rt712_sdca_dmic_ops = { + .hw_params = rt712_sdca_dmic_hw_params, + .hw_free = rt712_sdca_dmic_hw_free, + .set_stream = rt712_sdca_dmic_set_sdw_stream, + .shutdown = rt712_sdca_dmic_shutdown, +}; + +static struct snd_soc_dai_driver rt712_sdca_dmic_dai[] = { + { + .name = "rt712-sdca-dmic-aif1", + .id = RT712_AIF1, + .capture = { + .stream_name = "DP2 Capture", + .channels_min = 1, + .channels_max = 4, + .rates = RT712_STEREO_RATES, + .formats = RT712_FORMATS, + }, + .ops = &rt712_sdca_dmic_ops, + }, +}; + +static int rt712_sdca_dmic_init(struct device *dev, struct regmap *regmap, + struct regmap *mbq_regmap, struct sdw_slave *slave) +{ + struct rt712_sdca_dmic_priv *rt712; + int ret; + + rt712 = devm_kzalloc(dev, sizeof(*rt712), GFP_KERNEL); + if (!rt712) + return -ENOMEM; + + dev_set_drvdata(dev, rt712); + rt712->slave = slave; + rt712->regmap = regmap; + rt712->mbq_regmap = mbq_regmap; + + /* + * Mark hw_init to false + * HW init will be performed when device reports present + */ + rt712->hw_init = false; + rt712->first_hw_init = false; + rt712->fu1e_dapm_mute = true; + rt712->fu1e_mixer_mute[0] = rt712->fu1e_mixer_mute[1] = + rt712->fu1e_mixer_mute[2] = rt712->fu1e_mixer_mute[3] = true; + + ret = devm_snd_soc_register_component(dev, + &soc_sdca_dev_rt712_dmic, + rt712_sdca_dmic_dai, + ARRAY_SIZE(rt712_sdca_dmic_dai)); + + dev_dbg(&slave->dev, "%s\n", __func__); + + return ret; +} + + +static int rt712_sdca_dmic_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(&slave->dev); + + /* Update the status */ + rt712->status = status; + + if (status == SDW_SLAVE_UNATTACHED) + rt712->hw_init = false; + + /* + * Perform initialization only if slave status is present and + * hw_init flag is false + */ + if (rt712->hw_init || rt712->status != SDW_SLAVE_ATTACHED) + return 0; + + /* perform I/O transfers required for Slave initialization */ + return rt712_sdca_dmic_io_init(&slave->dev, slave); +} + +static int rt712_sdca_dmic_read_prop(struct sdw_slave *slave) +{ + struct sdw_slave_prop *prop = &slave->prop; + int nval, i; + u32 bit; + unsigned long addr; + struct sdw_dpn_prop *dpn; + + prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; + + prop->paging_support = true; + + /* first we need to allocate memory for set bits in port lists */ + prop->source_ports = BIT(2); /* BITMAP: 00000100 */ + prop->sink_ports = 0; + + nval = hweight32(prop->source_ports); + prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->src_dpn_prop), GFP_KERNEL); + if (!prop->src_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->src_dpn_prop; + addr = prop->source_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + dpn[i].ch_prep_timeout = 10; + i++; + } + + /* set the timeout values */ + prop->clk_stop_timeout = 200; + + /* wake-up event */ + prop->wake_capable = 1; + + return 0; +} + +static const struct sdw_device_id rt712_sdca_dmic_id[] = { + SDW_SLAVE_ENTRY_EXT(0x025d, 0x1712, 0x3, 0x1, 0), + SDW_SLAVE_ENTRY_EXT(0x025d, 0x1713, 0x3, 0x1, 0), + SDW_SLAVE_ENTRY_EXT(0x025d, 0x1716, 0x3, 0x1, 0), + SDW_SLAVE_ENTRY_EXT(0x025d, 0x1717, 0x3, 0x1, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, rt712_sdca_dmic_id); + +static int __maybe_unused rt712_sdca_dmic_dev_suspend(struct device *dev) +{ + struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(dev); + + if (!rt712->hw_init) + return 0; + + regcache_cache_only(rt712->regmap, true); + regcache_cache_only(rt712->mbq_regmap, true); + + return 0; +} + +static int __maybe_unused rt712_sdca_dmic_dev_system_suspend(struct device *dev) +{ + struct rt712_sdca_dmic_priv *rt712_sdca = dev_get_drvdata(dev); + + if (!rt712_sdca->hw_init) + return 0; + + return rt712_sdca_dmic_dev_suspend(dev); +} + +#define RT712_PROBE_TIMEOUT 5000 + +static int __maybe_unused rt712_sdca_dmic_dev_resume(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(dev); + unsigned long time; + + if (!rt712->first_hw_init) + return 0; + + if (!slave->unattach_request) + goto regmap_sync; + + time = wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(RT712_PROBE_TIMEOUT)); + if (!time) { + dev_err(&slave->dev, "Initialization not complete, timed out\n"); + sdw_show_ping_status(slave->bus, true); + + return -ETIMEDOUT; + } + +regmap_sync: + slave->unattach_request = 0; + regcache_cache_only(rt712->regmap, false); + regcache_sync(rt712->regmap); + regcache_cache_only(rt712->mbq_regmap, false); + regcache_sync(rt712->mbq_regmap); + return 0; +} + +static const struct dev_pm_ops rt712_sdca_dmic_pm = { + SET_SYSTEM_SLEEP_PM_OPS(rt712_sdca_dmic_dev_system_suspend, rt712_sdca_dmic_dev_resume) + SET_RUNTIME_PM_OPS(rt712_sdca_dmic_dev_suspend, rt712_sdca_dmic_dev_resume, NULL) +}; + + +static struct sdw_slave_ops rt712_sdca_dmic_slave_ops = { + .read_prop = rt712_sdca_dmic_read_prop, + .update_status = rt712_sdca_dmic_update_status, +}; + +static int rt712_sdca_dmic_sdw_probe(struct sdw_slave *slave, + const struct sdw_device_id *id) +{ + struct regmap *regmap, *mbq_regmap; + + /* Regmap Initialization */ + mbq_regmap = devm_regmap_init_sdw_mbq(slave, &rt712_sdca_dmic_mbq_regmap); + if (IS_ERR(mbq_regmap)) + return PTR_ERR(mbq_regmap); + + regmap = devm_regmap_init_sdw(slave, &rt712_sdca_dmic_regmap); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return rt712_sdca_dmic_init(&slave->dev, regmap, mbq_regmap, slave); +} + +static int rt712_sdca_dmic_sdw_remove(struct sdw_slave *slave) +{ + struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(&slave->dev); + + if (rt712->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + +static struct sdw_driver rt712_sdca_dmic_sdw_driver = { + .driver = { + .name = "rt712-sdca-dmic", + .owner = THIS_MODULE, + .pm = &rt712_sdca_dmic_pm, + }, + .probe = rt712_sdca_dmic_sdw_probe, + .remove = rt712_sdca_dmic_sdw_remove, + .ops = &rt712_sdca_dmic_slave_ops, + .id_table = rt712_sdca_dmic_id, +}; +module_sdw_driver(rt712_sdca_dmic_sdw_driver); + +MODULE_DESCRIPTION("ASoC RT712 SDCA DMIC SDW driver"); +MODULE_AUTHOR("Shuming Fan "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rt712-sdca-dmic.h b/sound/soc/codecs/rt712-sdca-dmic.h new file mode 100644 index 000000000000..74c29677c251 --- /dev/null +++ b/sound/soc/codecs/rt712-sdca-dmic.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * rt712-sdca-dmic.h -- RT712 SDCA DMIC ALSA SoC audio driver header + * + * Copyright(c) 2023 Realtek Semiconductor Corp. + */ + +#ifndef __RT712_SDW_DMIC_H__ +#define __RT712_SDW_DMIC_H__ + +#include +#include + +struct rt712_sdca_dmic_priv { + struct regmap *regmap; + struct regmap *mbq_regmap; + struct snd_soc_component *component; + struct sdw_slave *slave; + enum sdw_slave_status status; + struct sdw_bus_params params; + bool hw_init; + bool first_hw_init; + bool fu1e_dapm_mute; + bool fu1e_mixer_mute[4]; +}; + +struct rt712_sdca_dmic_kctrl_priv { + unsigned int reg_base; + unsigned int count; + unsigned int max; + unsigned int invert; +}; + +/* SDCA (Channel) */ +#define CH_01 0x01 +#define CH_02 0x02 +#define CH_03 0x03 +#define CH_04 0x04 + +static const struct reg_default rt712_sdca_dmic_reg_defaults[] = { + { 0x201a, 0x00 }, + { 0x201b, 0x00 }, + { 0x201c, 0x00 }, + { 0x201d, 0x00 }, + { 0x201e, 0x00 }, + { 0x201f, 0x00 }, + { 0x2029, 0x00 }, + { 0x202a, 0x00 }, + { 0x202d, 0x00 }, + { 0x202e, 0x00 }, + { 0x202f, 0x00 }, + { 0x2030, 0x00 }, + { 0x2031, 0x00 }, + { 0x2032, 0x00 }, + { 0x2033, 0x00 }, + { 0x2034, 0x00 }, + { 0x2230, 0x00 }, + { 0x2231, 0x2f }, + { 0x2232, 0x80 }, + { 0x2f01, 0x00 }, + { 0x2f02, 0x09 }, + { 0x2f03, 0x00 }, + { 0x2f04, 0x00 }, + { 0x2f05, 0x0b }, + { 0x2f06, 0x01 }, + { 0x2f08, 0x00 }, + { 0x2f09, 0x00 }, + { 0x2f0a, 0x01 }, + { 0x2f35, 0x02 }, + { 0x2f36, 0xcf }, + { 0x2f52, 0x08 }, + { 0x2f58, 0x07 }, + { 0x2f59, 0x07 }, + { 0x3201, 0x01 }, + { 0x320c, 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_IT26, RT712_SDCA_CTL_VENDOR_DEF, 0), 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_03), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_04), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_CS1F, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_CS1C, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, +}; + +static const struct reg_default rt712_sdca_dmic_mbq_defaults[] = { + { 0x0590001e, 0x0020 }, + { 0x06100000, 0x0010 }, + { 0x06100006, 0x0055 }, + { 0x06100010, 0x2630 }, + { 0x06100011, 0x152f }, + { 0x06100013, 0x0102 }, + { 0x06100015, 0x2219 }, + { 0x06100018, 0x0102 }, + { 0x06100026, 0x2c29 }, + { 0x06100027, 0x2d2b }, + { 0x0610002b, 0x2a32 }, + { 0x0610002f, 0x3355 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_01), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_02), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_03), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_04), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_01), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_02), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_03), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_04), 0x0000 }, +}; + +#endif /* __RT712_SDW_DMIC_H__ */ -- cgit From c52615e494f17f44b076ac8ae5a53cfc0041a0dd Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 23 Mar 2023 16:44:00 +0000 Subject: ASoC: qcom: q6apm-lpass-dai: close graphs before opening a new one On multiple prepare calls, its possible that the playback graphs are not unloaded from the DSP, which can have some wierd side-effects, one of them is that the data not consumed without any errors. Fixes: c2ac3aec474d("ASoC: qcom: q6apm-lpass-dai: unprepare stream if its already prepared") Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230323164403.6654-2-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6apm-lpass-dais.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c index 23d23bc6fbaa..420e8aa11f42 100644 --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c @@ -130,6 +130,9 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s if (dai_data->is_port_started[dai->id]) { q6apm_graph_stop(dai_data->graph[dai->id]); dai_data->is_port_started[dai->id] = false; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + q6apm_graph_close(dai_data->graph[dai->id]); } /** -- cgit From e2e530886359246ae782c779be248c59bc2ed111 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 23 Mar 2023 16:44:01 +0000 Subject: ASoC: qcom: sdw: do not restart soundwire ports for every prepare unpreparing/disabling and preparing/reenabling soundwire ports is not required for every prepare call, this add lots of click and pop noise if we do this in middle of playback or capture. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230323164403.6654-3-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/sdw.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c index 10249519a39e..1a41419c7eb8 100644 --- a/sound/soc/qcom/sdw.c +++ b/sound/soc/qcom/sdw.c @@ -32,11 +32,8 @@ int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, return 0; } - if (*stream_prepared) { - sdw_disable_stream(sruntime); - sdw_deprepare_stream(sruntime); - *stream_prepared = false; - } + if (*stream_prepared) + return 0; ret = sdw_prepare_stream(sruntime); if (ret) -- cgit From 80a4623eb1910d099e3d3de1564a6dfe16750e60 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Thu, 6 Apr 2023 11:23:00 -0400 Subject: ASoC: max98363: Make soc_codec_dev_max98363 static smatch reports sound/soc/codecs/max98363.c:392:39: warning: symbol 'soc_codec_dev_max98363' was not declared. Should it be static? This variable is only used in one file so should be static. Signed-off-by: Tom Rix Link: https://lore.kernel.org/r/20230406152300.1954292-1-trix@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98363.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/max98363.c b/sound/soc/codecs/max98363.c index 4585ebb1e82c..dcce06bff756 100644 --- a/sound/soc/codecs/max98363.c +++ b/sound/soc/codecs/max98363.c @@ -389,7 +389,7 @@ static const struct snd_soc_dapm_route max98363_audio_map[] = { {"BE_OUT", NULL, "AIFIN"}, }; -const struct snd_soc_component_driver soc_codec_dev_max98363 = { +static const struct snd_soc_component_driver soc_codec_dev_max98363 = { .controls = max98363_snd_controls, .num_controls = ARRAY_SIZE(max98363_snd_controls), .dapm_widgets = max98363_dapm_widgets, -- cgit From e41e1f4ae47499061bec3446c927bdfd2210a329 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 6 Apr 2023 10:29:37 -0500 Subject: ASoC: SOF: Intel: hda: add __func__ in SoundWire lcount() error logs Make sure SoundWire lcount helpers have unique error logs, but a common pattern for reporting issues. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230406152937.15347-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 483ec80f3160..2f1f0756ed75 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -213,8 +213,8 @@ int hda_sdw_check_lcount_common(struct snd_sof_dev *sdev) /* Check HW supported vs property value */ if (caps < ctx->count) { dev_err(sdev->dev, - "BIOS master count %d is larger than hardware capabilities %d\n", - ctx->count, caps); + "%s: BIOS master count %d is larger than hardware capabilities %d\n", + __func__, ctx->count, caps); return -EINVAL; } -- cgit From 8a55786a1875bd0b9c22156e800557a931baacb8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:12 +0300 Subject: ASoC: SOF: Intel: hda-mlink: improve hda_bus_ml_free() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use list_for_each_entry_safe() instead of open-coding. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 76ab9a2e7bb3..ac9bf477f413 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -36,13 +36,12 @@ void hda_bus_ml_get_capabilities(struct hdac_bus *bus) void hda_bus_ml_free(struct hdac_bus *bus) { - struct hdac_ext_link *hlink; + struct hdac_ext_link *hlink, *_h; if (!bus->mlcap) return; - while (!list_empty(&bus->hlink_list)) { - hlink = list_first_entry(&bus->hlink_list, struct hdac_ext_link, list); + list_for_each_entry_safe(hlink, _h, &bus->hlink_list, list) { list_del(&hlink->list); kfree(hlink); } -- cgit From 68376a3ef41f0a2d6c1c603e7293ba0e00b293da Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:13 +0300 Subject: ASoC: SOF: Intel: hda-mlink: add return value for hda_bus_ml_get_capabilities() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add return value - this will need additional work in the caller. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 5 +++-- sound/soc/sof/intel/hda.h | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index ac9bf477f413..e426d5e41e52 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -28,10 +28,11 @@ #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) -void hda_bus_ml_get_capabilities(struct hdac_bus *bus) +int hda_bus_ml_get_capabilities(struct hdac_bus *bus) { if (bus->mlcap) - snd_hdac_ext_bus_get_ml_capabilities(bus); + return snd_hdac_ext_bus_get_ml_capabilities(bus); + return 0; } void hda_bus_ml_free(struct hdac_bus *bus) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 2a43bfc14583..259b34eea677 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -765,7 +765,7 @@ static inline int hda_codec_i915_exit(struct snd_sof_dev *sdev) { return 0; } #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) -void hda_bus_ml_get_capabilities(struct hdac_bus *bus); +int hda_bus_ml_get_capabilities(struct hdac_bus *bus); void hda_bus_ml_free(struct hdac_bus *bus); void hda_bus_ml_put_all(struct hdac_bus *bus); void hda_bus_ml_reset_losidv(struct hdac_bus *bus); @@ -774,7 +774,7 @@ int hda_bus_ml_suspend(struct hdac_bus *bus); #else -static inline void hda_bus_ml_get_capabilities(struct hdac_bus *bus) { } +static inline int hda_bus_ml_get_capabilities(struct hdac_bus *bus) { return 0; } static inline void hda_bus_ml_free(struct hdac_bus *bus) { } static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { } static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { } -- cgit From 18227585d8374ce16d3a2792deb125794710de43 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:14 +0300 Subject: ASoC: SOF: Intel: hda-mlink: move to a dedicated module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of the functions will be used for SoundWire enumeration and power management, to avoid cycles in module dependencies and simplify integration all the HDaudio multi-link needs to move to a dedicated module. Drop no longer needed headers at the same time. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/Kconfig | 7 +++++++ sound/soc/sof/intel/Makefile | 5 ++++- sound/soc/sof/intel/hda-ctrl.c | 1 + sound/soc/sof/intel/hda-dsp.c | 1 + sound/soc/sof/intel/hda-mlink.c | 24 +++++++++++------------- sound/soc/sof/intel/hda.c | 2 ++ sound/soc/sof/intel/hda.h | 20 -------------------- 7 files changed, 26 insertions(+), 34 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index 715ba8a7f2f8..f4eeacf1f281 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -269,6 +269,13 @@ config SND_SOC_SOF_HDA_COMMON select SND_INTEL_DSP_CONFIG select SND_SOC_SOF_HDA_LINK_BASELINE select SND_SOC_SOF_HDA_PROBES + select SND_SOC_SOF_HDA_MLINK if SND_SOC_SOF_HDA_LINK + help + This option is not user-selectable but automagically handled by + 'select' statements at a higher level. + +config SND_SOC_SOF_HDA_MLINK + tristate help This option is not user-selectable but automagically handled by 'select' statements at a higher level. diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index 38ab86b6a9fe..fdb463c12e91 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -5,10 +5,12 @@ snd-sof-acpi-intel-bdw-objs := bdw.o snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.o \ hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \ - hda-dai.o hda-dai-ops.o hda-bus.o hda-mlink.o \ + hda-dai.o hda-dai-ops.o hda-bus.o \ skl.o hda-loader-skl.o \ apl.o cnl.o tgl.o icl.o mtl.o hda-common-ops.o +snd-sof-intel-hda-mlink-objs := hda-mlink.o + snd-sof-intel-hda-common-$(CONFIG_SND_SOC_SOF_HDA_PROBES) += hda-probes.o snd-sof-intel-hda-objs := hda-codec.o @@ -19,6 +21,7 @@ obj-$(CONFIG_SND_SOC_SOF_INTEL_ATOM_HIFI_EP) += snd-sof-intel-atom.o obj-$(CONFIG_SND_SOC_SOF_BAYTRAIL) += snd-sof-acpi-intel-byt.o obj-$(CONFIG_SND_SOC_SOF_BROADWELL) += snd-sof-acpi-intel-bdw.o obj-$(CONFIG_SND_SOC_SOF_HDA_COMMON) += snd-sof-intel-hda-common.o +obj-$(CONFIG_SND_SOC_SOF_HDA_MLINK) += snd-sof-intel-hda-mlink.o obj-$(CONFIG_SND_SOC_SOF_HDA) += snd-sof-intel-hda.o snd-sof-pci-intel-tng-objs := pci-tng.o diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index e1dba6b79065..84bf01bd360a 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "../ops.h" #include "hda.h" diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 23c05e6f424a..77df536cf901 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "../sof-audio.h" #include "../ops.h" diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index e426d5e41e52..fbf86f2350fb 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -12,21 +12,11 @@ #include #include +#include -#include #include -#include -#include -#include -#include -#include -#include -#include "../sof-audio.h" -#include "../sof-pci-dev.h" -#include "../ops.h" -#include "hda.h" - -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK) int hda_bus_ml_get_capabilities(struct hdac_bus *bus) { @@ -34,6 +24,7 @@ int hda_bus_ml_get_capabilities(struct hdac_bus *bus) return snd_hdac_ext_bus_get_ml_capabilities(bus); return 0; } +EXPORT_SYMBOL_NS(hda_bus_ml_get_capabilities, SND_SOC_SOF_HDA_MLINK); void hda_bus_ml_free(struct hdac_bus *bus) { @@ -47,6 +38,7 @@ void hda_bus_ml_free(struct hdac_bus *bus) kfree(hlink); } } +EXPORT_SYMBOL_NS(hda_bus_ml_free, SND_SOC_SOF_HDA_MLINK); void hda_bus_ml_put_all(struct hdac_bus *bus) { @@ -55,6 +47,7 @@ void hda_bus_ml_put_all(struct hdac_bus *bus) list_for_each_entry(hlink, &bus->hlink_list, list) snd_hdac_ext_bus_link_put(bus, hlink); } +EXPORT_SYMBOL_NS(hda_bus_ml_put_all, SND_SOC_SOF_HDA_MLINK); void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { @@ -64,6 +57,7 @@ void hda_bus_ml_reset_losidv(struct hdac_bus *bus) list_for_each_entry(hlink, &bus->hlink_list, list) writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); } +EXPORT_SYMBOL_NS(hda_bus_ml_reset_losidv, SND_SOC_SOF_HDA_MLINK); int hda_bus_ml_resume(struct hdac_bus *bus) { @@ -80,10 +74,14 @@ int hda_bus_ml_resume(struct hdac_bus *bus) } return 0; } +EXPORT_SYMBOL_NS(hda_bus_ml_resume, SND_SOC_SOF_HDA_MLINK); int hda_bus_ml_suspend(struct hdac_bus *bus) { return snd_hdac_ext_bus_link_power_down_all(bus); } +EXPORT_SYMBOL_NS(hda_bus_ml_suspend, SND_SOC_SOF_HDA_MLINK); #endif + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 483ec80f3160..8845ae255f1e 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "../sof-audio.h" #include "../sof-pci-dev.h" #include "../ops.h" @@ -1730,3 +1731,4 @@ MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA); MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI); MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT); MODULE_IMPORT_NS(SOUNDWIRE_INTEL); +MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 259b34eea677..0e0cfa81a8f2 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -763,26 +763,6 @@ static inline int hda_codec_i915_exit(struct snd_sof_dev *sdev) { return 0; } #endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - -int hda_bus_ml_get_capabilities(struct hdac_bus *bus); -void hda_bus_ml_free(struct hdac_bus *bus); -void hda_bus_ml_put_all(struct hdac_bus *bus); -void hda_bus_ml_reset_losidv(struct hdac_bus *bus); -int hda_bus_ml_resume(struct hdac_bus *bus); -int hda_bus_ml_suspend(struct hdac_bus *bus); - -#else - -static inline int hda_bus_ml_get_capabilities(struct hdac_bus *bus) { return 0; } -static inline void hda_bus_ml_free(struct hdac_bus *bus) { } -static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { } -static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { } -static inline int hda_bus_ml_resume(struct hdac_bus *bus) { return 0; } -static inline int hda_bus_ml_suspend(struct hdac_bus *bus) { return 0; } - -#endif /* CONFIG_SND_SOC_SOF_HDA */ - /* * Trace Control. */ -- cgit From 17c9b6ec35c0d6228db4f94590702a0cb03cd96a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:15 +0300 Subject: ASoC: SOF: Intel: hda-mlink: add structures to parse ALT links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend hdac_ext_link to store information needed for ALT links. Follow-up patches will include more functional patches for power-up and down. Note that this patch suggests the use of an 'eml_lock' to serialize access to shared registers. SoundWire-specific sequence require the lock to be taken at a higher level, as a result the helpers added in follow-up patches will provide 'unlocked' versions when needed. Also note that the low-level sequences with the 'hdaml_' prefix are taken directly from the hardware specifications - naming conventions included. The code will be split in two, with locking and linked-list management handled separately to avoid mixing required hardware setup and Linux-based resource management. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 221 +++++++++++++++++++++++++++++++++++++++- sound/soc/sof/intel/hda.c | 2 +- 2 files changed, 217 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index fbf86f2350fb..e6b20182f099 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -14,28 +14,239 @@ #include #include +#include #include #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK) -int hda_bus_ml_get_capabilities(struct hdac_bus *bus) +/** + * struct hdac_ext2_link - HDAudio extended+alternate link + * + * @hext_link: hdac_ext_link + * @alt: flag set for alternate extended links + * @intc: boolean for interrupt capable + * @ofls: boolean for offload support + * @lss: boolean for link synchronization capabilities + * @slcount: sublink count + * @elid: extended link ID (AZX_REG_ML_LEPTR_ID_ defines) + * @elver: extended link version + * @leptr: extended link pointer + * @eml_lock: mutual exclusion to access shared registers e.g. CPA/SPA bits + * in LCTL register + * @base_ptr: pointer to shim/ip/shim_vs space + * @instance_offset: offset between each of @slcount instances managed by link + * @shim_offset: offset to SHIM register base + * @ip_offset: offset to IP register base + * @shim_vs_offset: offset to vendor-specific (VS) SHIM base + */ +struct hdac_ext2_link { + struct hdac_ext_link hext_link; + + /* read directly from LCAP register */ + bool alt; + bool intc; + bool ofls; + bool lss; + int slcount; + int elid; + int elver; + u32 leptr; + + struct mutex eml_lock; /* prevent concurrent access to e.g. CPA/SPA */ + + /* internal values computed from LCAP contents */ + void __iomem *base_ptr; + u32 instance_offset; + u32 shim_offset; + u32 ip_offset; + u32 shim_vs_offset; +}; + +#define hdac_ext_link_to_ext2(h) container_of(h, struct hdac_ext2_link, hext_link) + +#define AZX_REG_SDW_INSTANCE_OFFSET 0x8000 +#define AZX_REG_SDW_SHIM_OFFSET 0x0 +#define AZX_REG_SDW_IP_OFFSET 0x100 +#define AZX_REG_SDW_VS_SHIM_OFFSET 0x6000 + +/* only one instance supported */ +#define AZX_REG_INTEL_DMIC_SHIM_OFFSET 0x0 +#define AZX_REG_INTEL_DMIC_IP_OFFSET 0x100 +#define AZX_REG_INTEL_DMIC_VS_SHIM_OFFSET 0x6000 + +#define AZX_REG_INTEL_SSP_INSTANCE_OFFSET 0x1000 +#define AZX_REG_INTEL_SSP_SHIM_OFFSET 0x0 +#define AZX_REG_INTEL_SSP_IP_OFFSET 0x100 +#define AZX_REG_INTEL_SSP_VS_SHIM_OFFSET 0xC00 + +/* only one instance supported */ +#define AZX_REG_INTEL_UAOL_SHIM_OFFSET 0x0 +#define AZX_REG_INTEL_UAOL_IP_OFFSET 0x100 +#define AZX_REG_INTEL_UAOL_VS_SHIM_OFFSET 0xC00 + +/* HDAML section - this part follows sequences in the hardware specification, + * including naming conventions and the use of the hdaml_ prefix. + * The code is intentionally minimal with limited dependencies on frameworks or + * helpers. Locking and scanning lists is handled at a higher level + */ + +static int hdaml_lnk_enum(struct device *dev, struct hdac_ext2_link *h2link, + void __iomem *ml_addr, int link_idx) { - if (bus->mlcap) - return snd_hdac_ext_bus_get_ml_capabilities(bus); + struct hdac_ext_link *hlink = &h2link->hext_link; + u32 base_offset; + + hlink->lcaps = readl(ml_addr + AZX_REG_ML_LCAP); + + h2link->alt = FIELD_GET(AZX_ML_HDA_LCAP_ALT, hlink->lcaps); + + /* handle alternate extensions */ + if (!h2link->alt) { + h2link->slcount = 1; + + /* + * LSDIID is initialized by hardware for HDaudio link, + * it needs to be setup by software for alternate links + */ + hlink->lsdiid = readw(ml_addr + AZX_REG_ML_LSDIID); + + dev_dbg(dev, "Link %d: HDAudio - lsdiid=%d\n", + link_idx, hlink->lsdiid); + + return 0; + } + + h2link->intc = FIELD_GET(AZX_ML_HDA_LCAP_INTC, hlink->lcaps); + h2link->ofls = FIELD_GET(AZX_ML_HDA_LCAP_OFLS, hlink->lcaps); + h2link->lss = FIELD_GET(AZX_ML_HDA_LCAP_LSS, hlink->lcaps); + + /* read slcount (increment due to zero-based hardware representation */ + h2link->slcount = FIELD_GET(AZX_ML_HDA_LCAP_SLCOUNT, hlink->lcaps) + 1; + dev_dbg(dev, "Link %d: HDAudio extended - sublink count %d\n", + link_idx, h2link->slcount); + + /* find IP ID and offsets */ + h2link->leptr = readl(hlink->ml_addr + AZX_REG_ML_LEPTR); + + h2link->elid = FIELD_GET(AZX_REG_ML_LEPTR_ID, h2link->leptr); + + base_offset = FIELD_GET(AZX_REG_ML_LEPTR_PTR, h2link->leptr); + h2link->base_ptr = hlink->ml_addr + base_offset; + + switch (h2link->elid) { + case AZX_REG_ML_LEPTR_ID_SDW: + h2link->shim_offset = AZX_REG_SDW_SHIM_OFFSET; + h2link->ip_offset = AZX_REG_SDW_IP_OFFSET; + h2link->shim_vs_offset = AZX_REG_SDW_VS_SHIM_OFFSET; + dev_dbg(dev, "Link %d: HDAudio extended - SoundWire alternate link, leptr.ptr %#x\n", + link_idx, base_offset); + break; + case AZX_REG_ML_LEPTR_ID_INTEL_DMIC: + h2link->shim_offset = AZX_REG_INTEL_DMIC_SHIM_OFFSET; + h2link->ip_offset = AZX_REG_INTEL_DMIC_IP_OFFSET; + h2link->shim_vs_offset = AZX_REG_INTEL_DMIC_VS_SHIM_OFFSET; + dev_dbg(dev, "Link %d: HDAudio extended - INTEL DMIC alternate link, leptr.ptr %#x\n", + link_idx, base_offset); + break; + case AZX_REG_ML_LEPTR_ID_INTEL_SSP: + h2link->shim_offset = AZX_REG_INTEL_SSP_SHIM_OFFSET; + h2link->ip_offset = AZX_REG_INTEL_SSP_IP_OFFSET; + h2link->shim_vs_offset = AZX_REG_INTEL_SSP_VS_SHIM_OFFSET; + dev_dbg(dev, "Link %d: HDAudio extended - INTEL SSP alternate link, leptr.ptr %#x\n", + link_idx, base_offset); + break; + case AZX_REG_ML_LEPTR_ID_INTEL_UAOL: + h2link->shim_offset = AZX_REG_INTEL_UAOL_SHIM_OFFSET; + h2link->ip_offset = AZX_REG_INTEL_UAOL_IP_OFFSET; + h2link->shim_vs_offset = AZX_REG_INTEL_UAOL_VS_SHIM_OFFSET; + dev_dbg(dev, "Link %d: HDAudio extended - INTEL UAOL alternate link, leptr.ptr %#x\n", + link_idx, base_offset); + break; + default: + dev_err(dev, "Link %d: HDAudio extended - Unsupported alternate link, leptr.id=%#02x value\n", + link_idx, h2link->elid); + return -EINVAL; + } return 0; } -EXPORT_SYMBOL_NS(hda_bus_ml_get_capabilities, SND_SOC_SOF_HDA_MLINK); + +/* END HDAML section */ + +static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + int ret; + + h2link = kzalloc(sizeof(*h2link), GFP_KERNEL); + if (!h2link) + return -ENOMEM; + + /* basic initialization */ + hlink = &h2link->hext_link; + + hlink->index = index; + hlink->bus = bus; + hlink->ml_addr = bus->mlcap + AZX_ML_BASE + (AZX_ML_INTERVAL * index); + + ret = hdaml_lnk_enum(bus->dev, h2link, hlink->ml_addr, index); + if (ret < 0) { + kfree(h2link); + return ret; + } + + mutex_init(&h2link->eml_lock); + + list_add_tail(&hlink->list, &bus->hlink_list); + + /* + * HDaudio regular links are powered-on by default, the + * refcount needs to be initialized. + */ + if (!h2link->alt) + hlink->ref_count = 1; + + return 0; +} + +int hda_bus_ml_init(struct hdac_bus *bus) +{ + u32 link_count; + int ret; + int i; + + if (!bus->mlcap) + return 0; + + link_count = readl(bus->mlcap + AZX_REG_ML_MLCD) + 1; + + dev_dbg(bus->dev, "HDAudio Multi-Link count: %d\n", link_count); + + for (i = 0; i < link_count; i++) { + ret = hda_ml_alloc_h2link(bus, i); + if (ret < 0) { + hda_bus_ml_free(bus); + return ret; + } + } + return 0; +} +EXPORT_SYMBOL_NS(hda_bus_ml_init, SND_SOC_SOF_HDA_MLINK); void hda_bus_ml_free(struct hdac_bus *bus) { struct hdac_ext_link *hlink, *_h; + struct hdac_ext2_link *h2link; if (!bus->mlcap) return; list_for_each_entry_safe(hlink, _h, &bus->hlink_list, list) { list_del(&hlink->list); - kfree(hlink); + h2link = hdac_ext_link_to_ext2(hlink); + + mutex_destroy(&h2link->eml_lock); + kfree(h2link); } } EXPORT_SYMBOL_NS(hda_bus_ml_free, SND_SOC_SOF_HDA_MLINK); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 8845ae255f1e..5980cf1e27a3 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -918,7 +918,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev) return ret; } - hda_bus_ml_get_capabilities(bus); + hda_bus_ml_init(bus); /* Skip SoundWire if it is not supported */ if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) -- cgit From 4c2d4e446d5673db2c653a6e53ca9be908582c4e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:16 +0300 Subject: ASoC: SOF: Intel: hda-mlink: special-case HDaudio regular links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For backwards compatibility, HDaudio/iDISP links are powered-on when exiting reset, and the existing driver forces them to be powered-off when entering S0ix. In addition, the get/put helpers are invoked directly by the ASoC codec drivers, which a historical layering violation. Extended links are powered-on by software only, during the probe and DAI startup phases. This calls for a different handling of the 'regular' and 'extended' audio links. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index e6b20182f099..8a66c0a67589 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -255,8 +255,12 @@ void hda_bus_ml_put_all(struct hdac_bus *bus) { struct hdac_ext_link *hlink; - list_for_each_entry(hlink, &bus->hlink_list, list) - snd_hdac_ext_bus_link_put(bus, hlink); + list_for_each_entry(hlink, &bus->hlink_list, list) { + struct hdac_ext2_link *h2link = hdac_ext_link_to_ext2(hlink); + + if (!h2link->alt) + snd_hdac_ext_bus_link_put(bus, hlink); + } } EXPORT_SYMBOL_NS(hda_bus_ml_put_all, SND_SOC_SOF_HDA_MLINK); @@ -277,7 +281,9 @@ int hda_bus_ml_resume(struct hdac_bus *bus) /* power up links that were active before suspend */ list_for_each_entry(hlink, &bus->hlink_list, list) { - if (hlink->ref_count) { + struct hdac_ext2_link *h2link = hdac_ext_link_to_ext2(hlink); + + if (!h2link->alt && hlink->ref_count) { ret = snd_hdac_ext_bus_link_power_up(hlink); if (ret < 0) return ret; @@ -289,7 +295,19 @@ EXPORT_SYMBOL_NS(hda_bus_ml_resume, SND_SOC_SOF_HDA_MLINK); int hda_bus_ml_suspend(struct hdac_bus *bus) { - return snd_hdac_ext_bus_link_power_down_all(bus); + struct hdac_ext_link *hlink; + int ret; + + list_for_each_entry(hlink, &bus->hlink_list, list) { + struct hdac_ext2_link *h2link = hdac_ext_link_to_ext2(hlink); + + if (!h2link->alt) { + ret = snd_hdac_ext_bus_link_power_down(hlink); + if (ret < 0) + return ret; + } + } + return 0; } EXPORT_SYMBOL_NS(hda_bus_ml_suspend, SND_SOC_SOF_HDA_MLINK); -- cgit From fc7dab8ec0b4a451dd5737aa4f06a0e8bd6efa32 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:17 +0300 Subject: ASoC: SOF: Intel: hda-mlink: introduce helpers for 'extended links' PM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add helpers to program SPA/CPA bits, using a mutex to access the shared LCTL register if required. All links are managed with the same LCTLx.SPA bits. However there are quite a few implementation details to be aware of: Legacy HDaudio multi-links are powered-up when exiting reset, which requires the ref_count to be manually set to one when initializing the link. Alternate links for SoundWire/DMIC/SSP need to be explicitly powered-up before accessing the SHIM/IP/Vendor-Specific SHIM space for each sublink. DMIC/SSP/SoundWire are all different cases with a different device/dai/hlink relationship. SoundWire will handle power management with the auxiliary device resume/suspend routine. The ref_count is not necessary in this case. The DMIC/SSP will by contrast handle the power management from DAI .startup and .shutdown callbacks. The SSP has a 1:1 mapping between sublink and DAI, but it's bidirectional so the ref_count will help avoid turning off the sublink when one of the two directions is still in use. The DMIC has a single link but two DAIs for data generated at different sampling frequencies, again the ref_count will make sure the two DAIs can be used concurrently. And last the SoundWire Intel require power-up/down and bank switch to be handled with a lock already taken, so the 'eml_lock' is made optional with the _unlocked versions of the helpers. Note that the _check_power_active() implementation is similar to previous helpers in sound/hda/ext, with sleep duration and timeout aligned with hardware recommendations. If desired, this helper could be modified in a second step with .e.g. readl_poll_timeout() Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-9-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 163 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 8a66c0a67589..4d016f6ab773 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -170,6 +170,68 @@ static int hdaml_lnk_enum(struct device *dev, struct hdac_ext2_link *h2link, return 0; } +/* + * Hardware recommendations are to wait ~10us before checking any hardware transition + * reported by bits changing status. + * This value does not need to be super-precise, a slack of 5us is perfectly acceptable. + * The worst-case is about 1ms before reporting an issue + */ +#define HDAML_POLL_DELAY_MIN_US 10 +#define HDAML_POLL_DELAY_SLACK_US 5 +#define HDAML_POLL_DELAY_RETRY 100 + +static int check_sublink_power(u32 __iomem *lctl, int sublink, bool enabled) +{ + int mask = BIT(sublink) << AZX_ML_LCTL_CPA_SHIFT; + int retry = HDAML_POLL_DELAY_RETRY; + u32 val; + + usleep_range(HDAML_POLL_DELAY_MIN_US, + HDAML_POLL_DELAY_MIN_US + HDAML_POLL_DELAY_SLACK_US); + do { + val = readl(lctl); + if (enabled) { + if (val & mask) + return 0; + } else { + if (!(val & mask)) + return 0; + } + usleep_range(HDAML_POLL_DELAY_MIN_US, + HDAML_POLL_DELAY_MIN_US + HDAML_POLL_DELAY_SLACK_US); + + } while (--retry); + + return -EIO; +} + +static int hdaml_link_init(u32 __iomem *lctl, int sublink) +{ + u32 val; + u32 mask = BIT(sublink) << AZX_ML_LCTL_SPA_SHIFT; + + val = readl(lctl); + val |= mask; + + writel(val, lctl); + + return check_sublink_power(lctl, sublink, true); +} + +static int hdaml_link_shutdown(u32 __iomem *lctl, int sublink) +{ + u32 val; + u32 mask; + + val = readl(lctl); + mask = BIT(sublink) << AZX_ML_LCTL_SPA_SHIFT; + val &= ~mask; + + writel(val, lctl); + + return check_sublink_power(lctl, sublink, false); +} + /* END HDAML section */ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) @@ -251,6 +313,107 @@ void hda_bus_ml_free(struct hdac_bus *bus) } EXPORT_SYMBOL_NS(hda_bus_ml_free, SND_SOC_SOF_HDA_MLINK); +static struct hdac_ext2_link * +find_ext2_link(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext_link *hlink; + + list_for_each_entry(hlink, &bus->hlink_list, list) { + struct hdac_ext2_link *h2link = hdac_ext_link_to_ext2(hlink); + + if (h2link->alt == alt && h2link->elid == elid) + return h2link; + } + + return NULL; +} + +static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid, int sublink, + bool eml_lock) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + int ret = 0; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return -ENODEV; + + if (sublink >= h2link->slcount) + return -EINVAL; + + hlink = &h2link->hext_link; + + if (eml_lock) + mutex_lock(&h2link->eml_lock); + + if (++hlink->ref_count > 1) + goto skip_init; + + ret = hdaml_link_init(hlink->ml_addr + AZX_REG_ML_LCTL, sublink); + +skip_init: + if (eml_lock) + mutex_unlock(&h2link->eml_lock); + + return ret; +} + +int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink) +{ + return hdac_bus_eml_power_up_base(bus, alt, elid, sublink, true); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_power_up, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink) +{ + return hdac_bus_eml_power_up_base(bus, alt, elid, sublink, false); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_power_up_unlocked, SND_SOC_SOF_HDA_MLINK); + +static int hdac_bus_eml_power_down_base(struct hdac_bus *bus, bool alt, int elid, int sublink, + bool eml_lock) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + int ret = 0; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return -ENODEV; + + if (sublink >= h2link->slcount) + return -EINVAL; + + hlink = &h2link->hext_link; + + if (eml_lock) + mutex_lock(&h2link->eml_lock); + + if (--hlink->ref_count > 0) + goto skip_shutdown; + + ret = hdaml_link_shutdown(hlink->ml_addr + AZX_REG_ML_LCTL, sublink); + +skip_shutdown: + if (eml_lock) + mutex_unlock(&h2link->eml_lock); + + return ret; +} + +int hdac_bus_eml_power_down(struct hdac_bus *bus, bool alt, int elid, int sublink) +{ + return hdac_bus_eml_power_down_base(bus, alt, elid, sublink, true); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_power_down, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink) +{ + return hdac_bus_eml_power_down_base(bus, alt, elid, sublink, false); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_power_down_unlocked, SND_SOC_SOF_HDA_MLINK); + void hda_bus_ml_put_all(struct hdac_bus *bus) { struct hdac_ext_link *hlink; -- cgit From 725218f1d8210ee6eba2c2e923ea26a312fb3f46 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:18 +0300 Subject: ASoC: SOF: Intel: hda-mlink: add convenience helpers for SoundWire PM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The updated SoundWire Intel driver will need to rely on Extended HDaudio links for power management, but it doesn't need to be aware of all the HDaudio structures. Add convenience helpers to avoid polluting SoundWire drivers too much with HDaudio information. Since the SoundWire/Intel solution already takes the lock at a higher level, the _unlocked PM helpers are used. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-10-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 4d016f6ab773..5045c10bed76 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -414,6 +414,18 @@ int hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, i } EXPORT_SYMBOL_NS(hdac_bus_eml_power_down_unlocked, SND_SOC_SOF_HDA_MLINK); +int hdac_bus_eml_sdw_power_up_unlocked(struct hdac_bus *bus, int sublink) +{ + return hdac_bus_eml_power_up_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW, sublink); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_power_up_unlocked, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink) +{ + return hdac_bus_eml_power_down_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW, sublink); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_power_down_unlocked, SND_SOC_SOF_HDA_MLINK); + void hda_bus_ml_put_all(struct hdac_bus *bus) { struct hdac_ext_link *hlink; -- cgit From 6857c7ee202cf4b8224882bcee8e3b97c26b6484 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:19 +0300 Subject: ASoC: SOF: Intel: hda-mlink: add helper to return sublink count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is needed for SoundWire integration. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-11-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 5045c10bed76..02743c342f28 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -328,6 +328,18 @@ find_ext2_link(struct hdac_bus *bus, bool alt, int elid) return NULL; } +int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext2_link *h2link; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return 0; + + return h2link->slcount; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_get_count, SND_SOC_SOF_HDA_MLINK); + static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid, int sublink, bool eml_lock) { -- cgit From 2e4288319ad3e18a266461d3e63c86eb36f7a152 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:20 +0300 Subject: ASoC: SOF: Intel: hda-mlink: add helpers to enable/check interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When INTC is set, LCTL exposes INTEN and INTSTS fields. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-12-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 02743c342f28..026642659037 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -232,6 +232,28 @@ static int hdaml_link_shutdown(u32 __iomem *lctl, int sublink) return check_sublink_power(lctl, sublink, false); } +static void hdaml_link_enable_interrupt(u32 __iomem *lctl, bool enable) +{ + u32 val; + + val = readl(lctl); + if (enable) + val |= AZX_ML_LCTL_INTEN; + else + val &= ~AZX_ML_LCTL_INTEN; + + writel(val, lctl); +} + +static bool hdaml_link_check_interrupt(u32 __iomem *lctl) +{ + u32 val; + + val = readl(lctl); + + return val & AZX_ML_LCTL_INTSTS; +} + /* END HDAML section */ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) @@ -340,6 +362,46 @@ int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid) } EXPORT_SYMBOL_NS(hdac_bus_eml_get_count, SND_SOC_SOF_HDA_MLINK); +void hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return; + + if (!h2link->intc) + return; + + hlink = &h2link->hext_link; + + mutex_lock(&h2link->eml_lock); + + hdaml_link_enable_interrupt(hlink->ml_addr + AZX_REG_ML_LCTL, enable); + + mutex_unlock(&h2link->eml_lock); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_enable_interrupt, SND_SOC_SOF_HDA_MLINK); + +bool hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return false; + + if (!h2link->intc) + return false; + + hlink = &h2link->hext_link; + + return hdaml_link_check_interrupt(hlink->ml_addr + AZX_REG_ML_LCTL); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_check_interrupt, SND_SOC_SOF_HDA_MLINK); + static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid, int sublink, bool eml_lock) { -- cgit From 02ba1b021c28670011b361be3be4bda49f348c43 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:21 +0300 Subject: ASoC: SOF: Intel: hda-mlink: add helpers to set link SYNC frequency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These helpers configure the ratio between the base clock and the hardware signal used for link synchronization. The SYNCPRD is written before the first sublink is powered-up. The SYNCPU bit is set, but it will only be cleared after the link is powered-up, hence the implementation with a set/wait pattern. These helpers are currently only needed by SoundWire support, where the lock is taken at a higher level, so only the _unlocked versions are exposed for now. Note that the _wait_bit() implementation is similar to previous helpers in drivers/soundwire, but with sleep duration and timeout aligned with hardware recommendations. If desired, this helper could be modified in a second step with e.g. readl_poll_timeout(). Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-13-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 90 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 026642659037..a364d6b5935d 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -254,6 +254,46 @@ static bool hdaml_link_check_interrupt(u32 __iomem *lctl) return val & AZX_ML_LCTL_INTSTS; } +static int hdaml_wait_bit(void __iomem *base, int offset, u32 mask, u32 target) +{ + int timeout = HDAML_POLL_DELAY_RETRY; + u32 reg_read; + + do { + reg_read = readl(base + offset); + if ((reg_read & mask) == target) + return 0; + + timeout--; + usleep_range(HDAML_POLL_DELAY_MIN_US, + HDAML_POLL_DELAY_MIN_US + HDAML_POLL_DELAY_SLACK_US); + } while (timeout != 0); + + return -EAGAIN; +} + +static void hdaml_link_set_syncprd(u32 __iomem *lsync, u32 syncprd) +{ + u32 val; + + val = readl(lsync); + val &= ~AZX_REG_ML_LSYNC_SYNCPRD; + val |= (syncprd & AZX_REG_ML_LSYNC_SYNCPRD); + + /* + * set SYNCPU but do not wait. The bit is cleared by hardware when + * the link becomes active. + */ + val |= AZX_REG_ML_LSYNC_SYNCPU; + + writel(val, lsync); +} + +static int hdaml_link_wait_syncpu(u32 __iomem *lsync) +{ + return hdaml_wait_bit(lsync, 0, AZX_REG_ML_LSYNC_SYNCPU, 0); +} + /* END HDAML section */ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) @@ -402,6 +442,56 @@ bool hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid) } EXPORT_SYMBOL_NS(hdac_bus_eml_check_interrupt, SND_SOC_SOF_HDA_MLINK); +int hdac_bus_eml_set_syncprd_unlocked(struct hdac_bus *bus, bool alt, int elid, u32 syncprd) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return 0; + + if (!h2link->lss) + return 0; + + hlink = &h2link->hext_link; + + hdaml_link_set_syncprd(hlink->ml_addr + AZX_REG_ML_LSYNC, syncprd); + + return 0; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_set_syncprd_unlocked, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_sdw_set_syncprd_unlocked(struct hdac_bus *bus, u32 syncprd) +{ + return hdac_bus_eml_set_syncprd_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW, syncprd); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_set_syncprd_unlocked, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_wait_syncpu_unlocked(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return 0; + + if (!h2link->lss) + return 0; + + hlink = &h2link->hext_link; + + return hdaml_link_wait_syncpu(hlink->ml_addr + AZX_REG_ML_LSYNC); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_wait_syncpu_unlocked, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_sdw_wait_syncpu_unlocked(struct hdac_bus *bus) +{ + return hdac_bus_eml_wait_syncpu_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_wait_syncpu_unlocked, SND_SOC_SOF_HDA_MLINK); + static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid, int sublink, bool eml_lock) { -- cgit From 1f5a6e8b5147b7bc49c0e091f8b458e45d8ee56c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:22 +0300 Subject: ASoC: SOF: Intel: hda-mlink: add helpers for sync_arm/sync_go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The multi-link synchronization uses the same concept and registers, but moved to the HDAudio extended links. Add helpers for sync_arm and sync_go which are the basic for the bus reset, bank switch and clock stop. Since SoundWire is the only user of those helpers, only expose the _unlocked versions for now. Note that SYNCGO is a write-only bit, so no error can be reported. We still return 0 for compatibility with the SoundWire stream management headers. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-14-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 70 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index a364d6b5935d..c8371ab03c0a 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -294,6 +294,26 @@ static int hdaml_link_wait_syncpu(u32 __iomem *lsync) return hdaml_wait_bit(lsync, 0, AZX_REG_ML_LSYNC_SYNCPU, 0); } +static void hdaml_link_sync_arm(u32 __iomem *lsync, int sublink) +{ + u32 val; + + val = readl(lsync); + val |= (AZX_REG_ML_LSYNC_CMDSYNC << sublink); + + writel(val, lsync); +} + +static void hdaml_link_sync_go(u32 __iomem *lsync) +{ + u32 val; + + val = readl(lsync); + val |= AZX_REG_ML_LSYNC_SYNCGO; + + writel(val, lsync); +} + /* END HDAML section */ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) @@ -492,6 +512,56 @@ int hdac_bus_eml_sdw_wait_syncpu_unlocked(struct hdac_bus *bus) } EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_wait_syncpu_unlocked, SND_SOC_SOF_HDA_MLINK); +void hdac_bus_eml_sync_arm_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return; + + if (!h2link->lss) + return; + + hlink = &h2link->hext_link; + + hdaml_link_sync_arm(hlink->ml_addr + AZX_REG_ML_LSYNC, sublink); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sync_arm_unlocked, SND_SOC_SOF_HDA_MLINK); + +void hdac_bus_eml_sdw_sync_arm_unlocked(struct hdac_bus *bus, int sublink) +{ + hdac_bus_eml_sync_arm_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW, sublink); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_sync_arm_unlocked, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_sync_go_unlocked(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return 0; + + if (!h2link->lss) + return 0; + + hlink = &h2link->hext_link; + + hdaml_link_sync_go(hlink->ml_addr + AZX_REG_ML_LSYNC); + + return 0; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sync_go_unlocked, SND_SOC_SOF_HDA_MLINK); + +int hdac_bus_eml_sdw_sync_go_unlocked(struct hdac_bus *bus) +{ + return hdac_bus_eml_sync_go_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_sync_go_unlocked, SND_SOC_SOF_HDA_MLINK); + static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid, int sublink, bool eml_lock) { -- cgit From d56d205857a2f6e10a1047532134321072f758b7 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:23 +0300 Subject: ASoC: SOF: Intel: hda-mlink: add helper to check cmdsync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helper is an optimization where sync_go is only called when the cmdsync field is actually set to a non-zero value. Since this is also only used by SoundWire for now, only expose the _unlocked version. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-15-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index c8371ab03c0a..cbbc8639691c 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -314,6 +314,15 @@ static void hdaml_link_sync_go(u32 __iomem *lsync) writel(val, lsync); } +static bool hdaml_link_check_cmdsync(u32 __iomem *lsync, u32 cmdsync_mask) +{ + u32 val; + + val = readl(lsync); + + return !!(val & cmdsync_mask); +} + /* END HDAML section */ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) @@ -562,6 +571,35 @@ int hdac_bus_eml_sdw_sync_go_unlocked(struct hdac_bus *bus) } EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_sync_go_unlocked, SND_SOC_SOF_HDA_MLINK); +bool hdac_bus_eml_check_cmdsync_unlocked(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + u32 cmdsync_mask; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return 0; + + if (!h2link->lss) + return 0; + + hlink = &h2link->hext_link; + + cmdsync_mask = GENMASK(AZX_REG_ML_LSYNC_CMDSYNC_SHIFT + h2link->slcount - 1, + AZX_REG_ML_LSYNC_CMDSYNC_SHIFT); + + return hdaml_link_check_cmdsync(hlink->ml_addr + AZX_REG_ML_LSYNC, + cmdsync_mask); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_check_cmdsync_unlocked, SND_SOC_SOF_HDA_MLINK); + +bool hdac_bus_eml_sdw_check_cmdsync_unlocked(struct hdac_bus *bus) +{ + return hdac_bus_eml_check_cmdsync_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW); +} +EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_check_cmdsync_unlocked, SND_SOC_SOF_HDA_MLINK); + static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid, int sublink, bool eml_lock) { -- cgit From 87a6ddc0cf1c62dbc7c2cc4b5f764a2e992c5ba6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:24 +0300 Subject: ASoC: SOF: Intel: hda-mlink: program SoundWire LSDIID registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each SoundWire peripheral can be programmed from the manager side either with a regular command FIFO, or with the HDaudio CORB/RIRB DMA-based mechanism. The mapping between SoundWire peripheral and SDI address is handled with the LSDIID register. This mapping only works of course if each peripheral has a unique address across all links. This has already been enforced in previous Intel contributions allowing for an IDA-based solution for the device number allocation. The checks on the dev_num are handled at the SoundWire level, but the locking is handled at the hda-mlink level. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-16-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index cbbc8639691c..5810d6f8719c 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -323,6 +323,16 @@ static bool hdaml_link_check_cmdsync(u32 __iomem *lsync, u32 cmdsync_mask) return !!(val & cmdsync_mask); } +static void hdaml_link_set_lsdiid(u32 __iomem *lsdiid, int dev_num) +{ + u32 val; + + val = readl(lsdiid); + val |= BIT(dev_num); + + writel(val, lsdiid); +} + /* END HDAML section */ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) @@ -698,6 +708,26 @@ int hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink) } EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_power_down_unlocked, SND_SOC_SOF_HDA_MLINK); +int hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, true, AZX_REG_ML_LEPTR_ID_SDW); + if (!h2link) + return -ENODEV; + + hlink = &h2link->hext_link; + + mutex_lock(&h2link->eml_lock); + + hdaml_link_set_lsdiid(hlink->ml_addr + AZX_REG_ML_LSDIID_OFFSET(sublink), dev_num); + + mutex_unlock(&h2link->eml_lock); + + return 0; +} EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_set_lsdiid, SND_SOC_SOF_HDA_MLINK); + void hda_bus_ml_put_all(struct hdac_bus *bus) { struct hdac_ext_link *hlink; -- cgit From 2b864e969be29958eb810fb611d1eac50eb7104b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:25 +0300 Subject: ASoC: SOF: Intel: hda-mlink: add helpers to retrieve DMIC/SSP hlink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Small helpers to make DAI ops simpler. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-17-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 5810d6f8719c..06613c081410 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -788,6 +788,30 @@ int hda_bus_ml_suspend(struct hdac_bus *bus) } EXPORT_SYMBOL_NS(hda_bus_ml_suspend, SND_SOC_SOF_HDA_MLINK); +struct hdac_ext_link *hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus) +{ + struct hdac_ext2_link *h2link; + + h2link = find_ext2_link(bus, true, AZX_REG_ML_LEPTR_ID_INTEL_SSP); + if (!h2link) + return NULL; + + return &h2link->hext_link; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_ssp_get_hlink, SND_SOC_SOF_HDA_MLINK); + +struct hdac_ext_link *hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus) +{ + struct hdac_ext2_link *h2link; + + h2link = find_ext2_link(bus, true, AZX_REG_ML_LEPTR_ID_INTEL_DMIC); + if (!h2link) + return NULL; + + return &h2link->hext_link; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_dmic_get_hlink, SND_SOC_SOF_HDA_MLINK); + #endif MODULE_LICENSE("Dual BSD/GPL"); -- cgit From 82958c406da4fec8f818826624c33cf2e62f4147 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:26 +0300 Subject: ASoC: SOF: Intel: hda-mlink: add helper to offload link ownership MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For DMIC and SSP, the DSP will be responsible for programming the blobs and link registers. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-18-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index 06613c081410..b9ce07c38bb5 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -333,6 +333,18 @@ static void hdaml_link_set_lsdiid(u32 __iomem *lsdiid, int dev_num) writel(val, lsdiid); } +static void hdaml_lctl_offload_enable(u32 __iomem *lctl, bool enable) +{ + u32 val = readl(lctl); + + if (enable) + val |= AZX_ML_LCTL_OFLEN; + else + val &= ~AZX_ML_LCTL_OFLEN; + + writel(val, lctl); +} + /* END HDAML section */ static int hda_ml_alloc_h2link(struct hdac_bus *bus, int index) @@ -812,6 +824,30 @@ struct hdac_ext_link *hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus) } EXPORT_SYMBOL_NS(hdac_bus_eml_dmic_get_hlink, SND_SOC_SOF_HDA_MLINK); +int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable) +{ + struct hdac_ext2_link *h2link; + struct hdac_ext_link *hlink; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return -ENODEV; + + if (!h2link->ofls) + return 0; + + hlink = &h2link->hext_link; + + mutex_lock(&h2link->eml_lock); + + hdaml_lctl_offload_enable(hlink->ml_addr + AZX_REG_ML_LCTL, enable); + + mutex_unlock(&h2link->eml_lock); + + return 0; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_enable_offload, SND_SOC_SOF_HDA_MLINK); + #endif MODULE_LICENSE("Dual BSD/GPL"); -- cgit From 681f27f302ff85ddf3f6e7fd0231059f99c0f26e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 4 Apr 2023 13:41:27 +0300 Subject: ASoC: SOF: Intel: hda-mlink: add helper to retrieve eml_lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For SoundWire usages, we need to use the global eml_lock to serialize/protect all accesses to shared registers. Due to the split implementation across two subsystems, we need to pass a pointer around. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20230404104127.5629-19-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-mlink.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index b9ce07c38bb5..775582ab7494 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -800,6 +800,18 @@ int hda_bus_ml_suspend(struct hdac_bus *bus) } EXPORT_SYMBOL_NS(hda_bus_ml_suspend, SND_SOC_SOF_HDA_MLINK); +struct mutex *hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext2_link *h2link; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return NULL; + + return &h2link->eml_lock; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_get_mutex, SND_SOC_SOF_HDA_MLINK); + struct hdac_ext_link *hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus) { struct hdac_ext2_link *h2link; -- cgit From a7fe7e24b2cddbe995b5b49e274d3a69dde7c7d9 Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Thu, 6 Apr 2023 10:37:02 -0500 Subject: ASoC: Intel: Add rpl_mx98360_rt5682 driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Boards were using this in older kernels before adl and rpl ids were split. Add this back to maintain support. Signed-off-by: Curtis Malainey Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20230406153703.17194-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 11 +++++++++++ sound/soc/intel/common/soc-acpi-intel-rpl-match.c | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 8735519cf4ed..791a59c5f00d 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -1116,6 +1116,17 @@ static const struct platform_device_id board_ids[] = { SOF_BT_OFFLOAD_SSP(2) | SOF_SSP_BT_OFFLOAD_PRESENT), }, + { + .name = "rpl_mx98360_rt5682", + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | + SOF_RT5682_SSP_CODEC(0) | + SOF_SPEAKER_AMP_PRESENT | + SOF_MAX98360A_SPEAKER_AMP_PRESENT | + SOF_RT5682_SSP_AMP(1) | + SOF_RT5682_NUM_HDMIDEV(4) | + SOF_BT_OFFLOAD_SSP(2) | + SOF_SSP_BT_OFFLOAD_PRESENT), + }, { .name = "mtl_mx98357_rt5682", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c index 07f96a11ea2f..13cbd8e9d41f 100644 --- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c @@ -284,7 +284,24 @@ static const struct snd_soc_acpi_link_adr rpl_sdw_rt1316_link12_rt714_link0[] = {} }; +static const struct snd_soc_acpi_codecs rpl_rt5682_hp = { + .num_codecs = 2, + .codecs = {"10EC5682", "RTL5682"}, +}; + +static const struct snd_soc_acpi_codecs rpl_max98360a_amp = { + .num_codecs = 1, + .codecs = {"MX98360A"}, +}; + struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = { + { + .comp_ids = &rpl_rt5682_hp, + .drv_name = "rpl_mx98360_rt5682", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &rpl_max98360a_amp, + .sof_tplg_filename = "sof-rpl-max98360a-rt5682.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_rpl_machines); -- cgit From f747eb86e4a82d0823328f642a667bffce703028 Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Thu, 6 Apr 2023 10:44:54 -0500 Subject: ASoC: SOF: Intel: MTL: conditionally wake WPIO1PG domain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wake IO1 from power gating if there is SoundWire enabled link discovered by ACPI scan. Signed-off-by: Yong Zhi Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20230406154454.18163-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 58959c24cb71..882ce5536ab6 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -217,6 +217,7 @@ static int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable) /* pre fw run operations */ static int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) { + struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; u32 dsphfpwrsts; u32 dsphfdsscs; u32 cpa; @@ -255,9 +256,11 @@ static int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) if (ret < 0) dev_err(sdev->dev, "failed to power up gated DSP domain\n"); - /* make sure SoundWire is not power-gated */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFPWRCTL, - MTL_HfPWRCTL_WPIOXPG(1), MTL_HfPWRCTL_WPIOXPG(1)); + /* if SoundWire is used, make sure it is not power-gated */ + if (hdev->info.handle && hdev->info.link_mask > 0) + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFPWRCTL, + MTL_HfPWRCTL_WPIOXPG(1), MTL_HfPWRCTL_WPIOXPG(1)); + return ret; } -- cgit From ef736f30548951870e2a5bfc41b6b0bb1d455641 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 6 Apr 2023 10:52:19 -0500 Subject: ASoC: SOF: Intel: hda-dai: Print the format_val as hexadecimal number The format_val is a set of bitfileds, printing it as a decimal just makes interpreting it complicated. In other HDA core code the format_val is printed as hexadecimal also. Signed-off-by: Peter Ujfalusi Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Jaska Uimonen Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230406155219.18997-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 0435b7f251aa..44a5d94c5050 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -177,8 +177,8 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params), params_format(params), link_bps, 0); - dev_dbg(bus->dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", - format_val, params_rate(params), params_channels(params), params_format(params)); + dev_dbg(bus->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val, + params_rate(params), params_channels(params), params_format(params)); if (ops->setup_hext_stream) ops->setup_hext_stream(sdev, hext_stream, format_val); -- cgit From 672029caa5708934817a331f3323bbe48d456c5c Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Fri, 7 Apr 2023 07:55:53 -0400 Subject: ASoC: mediatek: mt8186: set variable aud_pinctrl to static smatch reports sound/soc/mediatek/mt8186/mt8186-afe-gpio.c:14:16: warning: symbol 'aud_pinctrl' was not declared. Should it be static? This variable is only used in one file so should be static. Signed-off-by: Tom Rix Link: https://lore.kernel.org/r/20230407115553.1968111-1-trix@redhat.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-afe-gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c index 20b9f5d810ec..f12e91cc4fcf 100644 --- a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c +++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c @@ -11,7 +11,7 @@ #include "mt8186-afe-common.h" #include "mt8186-afe-gpio.h" -struct pinctrl *aud_pinctrl; +static struct pinctrl *aud_pinctrl; enum mt8186_afe_gpio { MT8186_AFE_GPIO_CLK_MOSI_OFF, -- cgit From 80f47122538d40b1a6a2c1a3c2d37b6e51b74224 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Tue, 11 Apr 2023 00:39:00 +0200 Subject: ASoC: ep93xx: i2s: move enable call to startup callback Make startup/shutdown callbacks symmetric to avoid clock subsystem warnings (reproduced with "aplay --dump-hw-params" + ctrl-c): WARNING: CPU: 0 PID: 102 at drivers/clk/clk.c:1048 clk_core_disable lrclk already disabled CPU: 0 PID: 102 Comm: aplay Not tainted 6.2.0-rc4 #1 Hardware name: Generic DT based system ... clk_core_disable from clk_core_disable_lock clk_core_disable_lock from ep93xx_i2s_shutdown ep93xx_i2s_shutdown from snd_soc_dai_shutdown snd_soc_dai_shutdown from soc_pcm_clean soc_pcm_clean from soc_pcm_close soc_pcm_close from snd_pcm_release_substream.part.0 snd_pcm_release_substream.part.0 from snd_pcm_release snd_pcm_release from __fput __fput from task_work_run ... WARNING: CPU: 0 PID: 102 at drivers/clk/clk.c:907 clk_core_unprepare lrclk already unprepared CPU: 0 PID: 102 Comm: aplay Tainted: G W 6.2.0-rc4 #1 Hardware name: Generic DT based system ... clk_core_unprepare from clk_unprepare clk_unprepare from ep93xx_i2s_shutdown ep93xx_i2s_shutdown from snd_soc_dai_shutdown snd_soc_dai_shutdown from soc_pcm_clean soc_pcm_clean from soc_pcm_close soc_pcm_close from snd_pcm_release_substream.part.0 snd_pcm_release_substream.part.0 from snd_pcm_release snd_pcm_release from __fput __fput from task_work_run ... Signed-off-by: Alexander Sverdlin Link: https://lore.kernel.org/r/20230410223902.2321834-2-alexander.sverdlin@gmail.com Signed-off-by: Mark Brown --- sound/soc/cirrus/ep93xx-i2s.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 9760453d9d79..2abd1bce2290 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -208,6 +208,16 @@ static int ep93xx_i2s_dai_probe(struct snd_soc_dai *dai) return 0; } +static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); + + ep93xx_i2s_enable(info, substream->stream); + + return 0; +} + static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -348,7 +358,6 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream, if (err) return err; - ep93xx_i2s_enable(info, substream->stream); return 0; } @@ -397,6 +406,7 @@ static int ep93xx_i2s_resume(struct snd_soc_component *component) #endif static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { + .startup = ep93xx_i2s_startup, .shutdown = ep93xx_i2s_shutdown, .hw_params = ep93xx_i2s_hw_params, .set_sysclk = ep93xx_i2s_set_sysclk, -- cgit From 2e9688c81cfc48b210af6f313cb04589b7943e86 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Tue, 11 Apr 2023 00:39:01 +0200 Subject: ASoC: cs4271: flat regcache, trivial simplifications - Switch to REGCACHE_FLAT, the whole overhead of RBTREE is not worth it with non sparse register set in the address range 1..7. - Move register width to central location Signed-off-by: Alexander Sverdlin Link: https://lore.kernel.org/r/20230410223902.2321834-3-alexander.sverdlin@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs4271-i2c.c | 1 - sound/soc/codecs/cs4271-spi.c | 1 - sound/soc/codecs/cs4271.c | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs4271-i2c.c b/sound/soc/codecs/cs4271-i2c.c index 0e8a7cf0da50..4033be1c3bc1 100644 --- a/sound/soc/codecs/cs4271-i2c.c +++ b/sound/soc/codecs/cs4271-i2c.c @@ -17,7 +17,6 @@ static int cs4271_i2c_probe(struct i2c_client *client) config = cs4271_regmap_config; config.reg_bits = 8; - config.val_bits = 8; return cs4271_probe(&client->dev, devm_regmap_init_i2c(client, &config)); diff --git a/sound/soc/codecs/cs4271-spi.c b/sound/soc/codecs/cs4271-spi.c index 7ef0a66b7778..4feb80436bd9 100644 --- a/sound/soc/codecs/cs4271-spi.c +++ b/sound/soc/codecs/cs4271-spi.c @@ -17,7 +17,6 @@ static int cs4271_spi_probe(struct spi_device *spi) config = cs4271_regmap_config; config.reg_bits = 16; - config.val_bits = 8; config.read_flag_mask = 0x21; config.write_flag_mask = 0x20; diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 2021cf442606..188b8b43c524 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -689,8 +689,8 @@ const struct regmap_config cs4271_regmap_config = { .reg_defaults = cs4271_reg_defaults, .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), - .cache_type = REGCACHE_RBTREE, - + .cache_type = REGCACHE_FLAT, + .val_bits = 8, .volatile_reg = cs4271_volatile_reg, }; EXPORT_SYMBOL_GPL(cs4271_regmap_config); -- cgit From 24f934becf60598fdec9c9f2e06437c831ffa374 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Tue, 11 Apr 2023 00:39:02 +0200 Subject: ASoC: ep93xx: i2s: Make it individually selectable This is necessary to replace EDB93XX specific SoC audio driver with generic "simple-audio-card". Signed-off-by: Alexander Sverdlin Link: https://lore.kernel.org/r/20230410223902.2321834-4-alexander.sverdlin@gmail.com Signed-off-by: Mark Brown --- sound/soc/cirrus/Kconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig index 34870c2d0cba..38a83c4dcc2d 100644 --- a/sound/soc/cirrus/Kconfig +++ b/sound/soc/cirrus/Kconfig @@ -8,7 +8,11 @@ config SND_EP93XX_SOC the EP93xx I2S or AC97 interfaces. config SND_EP93XX_SOC_I2S - tristate + tristate "I2S controller support for the Cirrus Logic EP93xx series" + depends on SND_EP93XX_SOC + help + Say Y or M if you want to add support for codecs attached to + the EP93xx I2S interface. if SND_EP93XX_SOC_I2S -- cgit From faf15233e59052f4d61cad2da6e56daf33124d96 Mon Sep 17 00:00:00 2001 From: Cem Kaya Date: Mon, 10 Apr 2023 20:38:15 +0200 Subject: ASoC: amd: Add Dell G15 5525 to quirks list Add Dell G15 5525 Ryzen Edition to quirks list for acp6x so that internal mic works. Link: https://bugzilla.kernel.org/show_bug.cgi?id=217155 Signed-off-by: Cem Kaya Link: https://lore.kernel.org/r/20230410183814.260518-1-cemkaya.boun@gmail.com Signed-off-by: Mark Brown --- sound/soc/amd/yc/acp6x-mach.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sound') diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index a428e17f0325..1d59163a882c 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -45,6 +45,13 @@ static struct snd_soc_card acp6x_card = { }; static const struct dmi_system_id yc_acp_quirk_table[] = { + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5525"), + } + }, { .driver_data = &acp6x_card, .matches = { -- cgit From beed115c2ce78f990222a29abed042582df4e87c Mon Sep 17 00:00:00 2001 From: Aashish Sharma Date: Tue, 11 Apr 2023 06:04:31 +0530 Subject: ASoC: mediatek: common: Fix refcount leak in parse_dai_link_info Add missing of_node_put()s before the returns to balance of_node_get()s and of_node_put()s, which may get unbalanced in case the for loop 'for_each_available_child_of_node' returns early. Fixes: 4302187d955f ("ASoC: mediatek: common: add soundcard driver common code") Reported-by: kernel test robot Reported-by: Julia Lawall Link: https://lore.kernel.org/r/202304090504.2K8L6soj-lkp@intel.com/ Signed-off-by: Aashish Sharma Reviewed-by: Guenter Roeck Reviewed-by: Trevor Wu Link: https://lore.kernel.org/r/20230411003431.4048700-1-shraash@google.com Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-soundcard-driver.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c index 7c55c2cb1f21..738093451ccb 100644 --- a/sound/soc/mediatek/common/mtk-soundcard-driver.c +++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c @@ -47,20 +47,26 @@ int parse_dai_link_info(struct snd_soc_card *card) /* Loop over all the dai link sub nodes */ for_each_available_child_of_node(dev->of_node, sub_node) { if (of_property_read_string(sub_node, "link-name", - &dai_link_name)) + &dai_link_name)) { + of_node_put(sub_node); return -EINVAL; + } for_each_card_prelinks(card, i, dai_link) { if (!strcmp(dai_link_name, dai_link->name)) break; } - if (i >= card->num_links) + if (i >= card->num_links) { + of_node_put(sub_node); return -EINVAL; + } ret = set_card_codec_info(card, sub_node, dai_link); - if (ret < 0) + if (ret < 0) { + of_node_put(sub_node); return ret; + } } return 0; -- cgit From a8f5da0bf4d85a6ad03810d902aba61c572102a6 Mon Sep 17 00:00:00 2001 From: Baishan Jiang Date: Wed, 12 Apr 2023 16:40:43 +0800 Subject: ASoC: amd: yc: Add ThinkBook 14 G5+ ARP to quirks list for acp6x ThinkBook 14 G5+ ARP uses Ryzen 7735H processor, and has the same microphone problem as ThinkBook 14 G4+ ARA. Adding 21HY to acp6x quirks table enables microphone for ThinkBook 14 G5+ ARP. Signed-off-by: Baishan Jiang Link: https://lore.kernel.org/r/OS3P286MB1711DD6556284B69C79C0C4FE19B9@OS3P286MB1711.JPNP286.PROD.OUTLOOK.COM Signed-off-by: Mark Brown --- sound/soc/amd/yc/acp6x-mach.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sound') diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index 1d59163a882c..b9958e555367 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -185,6 +185,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "21EN"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21HY"), + } + }, { .driver_data = &acp6x_card, .matches = { -- cgit From ef0128afa1655f8d024dc5058fbfa0c6deecf117 Mon Sep 17 00:00:00 2001 From: Fred Oh Date: Wed, 12 Apr 2023 09:14:57 +0300 Subject: ASoC: SOF: Intel: mtl: fix page fault in dspless mode when DSP is disabled The patch to make DSPless mode work even if the DSP is disabled in BIOS missed to touch the MTL code to add the needed checks. If the DSP is disabled this can lead to page fault due to not accesible registers. Fixes: 9fc6786f549c ("ASoC: SOF: Intel: hda: make DSPless mode work with DSP disabled in BIOS") Signed-off-by: Fred Oh Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230412061457.27937-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 882ce5536ab6..9f969e07fc27 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -60,6 +60,9 @@ static bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev) u32 irq_status; u32 hfintipptr; + if (sdev->dspless_mode_selected) + return false; + /* read Interrupt IP Pointer */ hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK; irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, hfintipptr + MTL_DSP_IRQSTS); @@ -120,6 +123,9 @@ static void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_intel_dsp_desc *chip = hda->desc; + if (sdev->dspless_mode_selected) + return; + /* enable IPC DONE and BUSY interrupts */ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE, @@ -131,6 +137,9 @@ static void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_intel_dsp_desc *chip = hda->desc; + if (sdev->dspless_mode_selected) + return; + /* disable IPC DONE and BUSY interrupts */ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE, 0); @@ -143,6 +152,9 @@ static void mtl_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable) u32 val; int ret; + if (sdev->dspless_mode_selected) + return; + /* Enable/Disable SoundWire interrupt */ mask = MTL_DSP_REG_HfSNDWIE_IE_MASK; if (enable) @@ -170,6 +182,9 @@ static int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable) u32 val; int ret; + if (sdev->dspless_mode_selected) + return 0; + /* read Interrupt IP Pointer */ hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK; -- cgit From d93ee84e3eb5d1afc081e57ca37f1411a01f2c94 Mon Sep 17 00:00:00 2001 From: Ying Liu Date: Wed, 12 Apr 2023 01:09:12 +0800 Subject: ASoC: tas5720: add missing unwind goto in tas5720_codec_probe Smatch complains that missing unwind goto in tas5720_codec_probe. When tas5720 has an invalid devtype, it is expected to invoke regulator_bulk_disable to handle the failure. But the default option return an error code directly. Fix it by reusing the probe_fail label. Signed-off-by: Ying Liu Link: https://lore.kernel.org/r/20230411170912.1939906-1-lyre@hust.edu.cn Signed-off-by: Mark Brown --- sound/soc/codecs/tas5720.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c index de6d01c8fdd3..4d27b60bd804 100644 --- a/sound/soc/codecs/tas5720.c +++ b/sound/soc/codecs/tas5720.c @@ -339,7 +339,8 @@ static int tas5720_codec_probe(struct snd_soc_component *component) break; default: dev_err(component->dev, "unexpected private driver data\n"); - return -EINVAL; + ret = -EINVAL; + goto probe_fail; } if (device_id != expected_device_id) -- cgit From bddcfb0802eb69b0f51293eab5db33d344c0262f Mon Sep 17 00:00:00 2001 From: Syed Saba Kareem Date: Wed, 12 Apr 2023 14:46:16 +0530 Subject: ASoC: amd: Add check for acp config flags We have SOF and generic ACP support enabled for Rembrandt and pheonix platforms on some machines. Since we have same PCI id used for probing, add check for machine configuration flag to avoid conflict with newer pci drivers. Such machine flag has been initialized via dmi match on few Chrome machines. If no flag is specified probe and register older platform device. Signed-off-by: Syed Saba Kareem Reviewed-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20230412091638.1158901-1-Syed.SabaKareem@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 2 ++ sound/soc/amd/ps/acp63.h | 2 ++ sound/soc/amd/ps/pci-ps.c | 8 +++++++- sound/soc/amd/yc/acp6x.h | 3 +++ sound/soc/amd/yc/pci-acp6x.c | 8 +++++++- 5 files changed, 21 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index c88ebd84bdd5..08e42082f5e9 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -90,6 +90,7 @@ config SND_SOC_AMD_VANGOGH_MACH config SND_SOC_AMD_ACP6x tristate "AMD Audio Coprocessor-v6.x Yellow Carp support" + select SND_AMD_ACP_CONFIG depends on X86 && PCI help This option enables Audio Coprocessor i.e ACP v6.x support on @@ -130,6 +131,7 @@ config SND_SOC_AMD_RPL_ACP6x config SND_SOC_AMD_PS tristate "AMD Audio Coprocessor-v6.3 Pink Sardine support" + select SND_AMD_ACP_CONFIG depends on X86 && PCI && ACPI help This option enables Audio Coprocessor i.e ACP v6.3 support on diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 6bf29b520511..dd36790b25ae 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -111,3 +111,5 @@ struct acp63_dev_data { u16 pdev_count; u16 pdm_dev_index; }; + +int snd_amd_acp_find_config(struct pci_dev *pci); diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 688a1d4643d9..afddb9a77ba4 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -247,11 +247,17 @@ static int snd_acp63_probe(struct pci_dev *pci, { struct acp63_dev_data *adata; u32 addr; - u32 irqflags; + u32 irqflags, flag; int val; int ret; irqflags = IRQF_SHARED; + + /* Return if acp config flag is defined */ + flag = snd_amd_acp_find_config(pci); + if (flag) + return -ENODEV; + /* Pink Sardine device check */ switch (pci->revision) { case 0x63: diff --git a/sound/soc/amd/yc/acp6x.h b/sound/soc/amd/yc/acp6x.h index 036207568c04..2de7d1edf00b 100644 --- a/sound/soc/amd/yc/acp6x.h +++ b/sound/soc/amd/yc/acp6x.h @@ -105,3 +105,6 @@ static inline void acp6x_writel(u32 val, void __iomem *base_addr) { writel(val, base_addr - ACP6x_PHY_BASE_ADDRESS); } + +int snd_amd_acp_find_config(struct pci_dev *pci); + diff --git a/sound/soc/amd/yc/pci-acp6x.c b/sound/soc/amd/yc/pci-acp6x.c index 77c5fa1f7af1..7af6a349b1d4 100644 --- a/sound/soc/amd/yc/pci-acp6x.c +++ b/sound/soc/amd/yc/pci-acp6x.c @@ -149,10 +149,16 @@ static int snd_acp6x_probe(struct pci_dev *pci, int index = 0; int val = 0x00; u32 addr; - unsigned int irqflags; + unsigned int irqflags, flag; int ret; irqflags = IRQF_SHARED; + + /* Return if acp config flag is defined */ + flag = snd_amd_acp_find_config(pci); + if (flag) + return -ENODEV; + /* Yellow Carp device check */ switch (pci->revision) { case 0x60: -- cgit From b599a4d7d905a8e8cf5c36ccae0b3dd97c956075 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Tue, 11 Apr 2023 18:59:51 +0200 Subject: ASoC: ep93xx: Add OF support Add the new cirrus,ep9301-ac97 and cirrus,ep9301-i2s compatibles. Signed-off-by: Alexander Sverdlin Link: https://lore.kernel.org/r/20230411165951.2335899-2-alexander.sverdlin@gmail.com Signed-off-by: Mark Brown --- sound/soc/cirrus/ep93xx-i2s.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sound') diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 2abd1bce2290..afc6b5b570ea 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -514,11 +515,18 @@ static void ep93xx_i2s_remove(struct platform_device *pdev) clk_put(info->mclk); } +static const struct of_device_id ep93xx_i2s_of_ids[] = { + { .compatible = "cirrus,ep9301-i2s" }, + {} +}; +MODULE_DEVICE_TABLE(of, ep93xx_i2s_of_ids); + static struct platform_driver ep93xx_i2s_driver = { .probe = ep93xx_i2s_probe, .remove_new = ep93xx_i2s_remove, .driver = { .name = "ep93xx-i2s", + .of_match_table = ep93xx_i2s_of_ids, }, }; -- cgit From 7b98a1efbabfd729441f46823b24432f2c32deeb Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 11 Apr 2023 16:25:24 +0100 Subject: ASoC: cs35l56: Use DAPM widget for firmware PLAY/PAUSE If we use a DAPM widget instead of mute_stream() to send the PLAY command we can issue the plays to multiple amps in parallel. With mute_stream each codec driver instance is called one at a time so we get N * PS0 delay time. DAPM does each stage on every widget in a card before moving to the next stage. So all amps will do the PRE_PMU then all will do the POST_PMU. The PLAY is sent in the PRE_PMU so that they all power-up in parallel. After the PS0 wait in the first POST_PMU all the other amps will also be ready so there won't be any extra delay, or it will be negligible. There's also no point waiting for the MBOX ack in the PRE_PMU. We won't see a PS0 state in POST_PMU if it didn't ack the PLAY command. So we can save a little extra time. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230411152528.329803-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 105 ++++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 50 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index d97b465f0d3c..71565e0fccd8 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -32,6 +32,23 @@ static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); +static int cs35l56_mbox_send(struct cs35l56_private *cs35l56, unsigned int command) +{ + unsigned int val; + int ret; + + regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command); + ret = regmap_read_poll_timeout(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, + val, (val == 0), + CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US); + if (ret) { + dev_warn(cs35l56->dev, "MBOX command %#x failed: %d\n", command, ret); + return ret; + } + + return 0; +} + static int cs35l56_wait_dsp_ready(struct cs35l56_private *cs35l56) { int ret; @@ -182,10 +199,45 @@ static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx6_enum, static const struct snd_kcontrol_new sdw1_tx6_mux = SOC_DAPM_ENUM("SDW1TX6 SRC", cs35l56_sdw1tx6_enum); +static int cs35l56_play_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); + unsigned int val; + int ret; + + dev_dbg(cs35l56->dev, "play: %d\n", event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Don't wait for ACK, we check in POST_PMU that it completed */ + return regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, + CS35L56_MBOX_CMD_AUDIO_PLAY); + case SND_SOC_DAPM_POST_PMU: + /* Wait for firmware to enter PS0 power state */ + ret = regmap_read_poll_timeout(cs35l56->regmap, + CS35L56_TRANSDUCER_ACTUAL_PS, + val, (val == CS35L56_PS0), + CS35L56_PS0_POLL_US, + CS35L56_PS0_TIMEOUT_US); + if (ret) + dev_err(cs35l56->dev, "PS0 wait failed: %d\n", ret); + return ret; + case SND_SOC_DAPM_POST_PMD: + return cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_PAUSE); + default: + return 0; + } +} + static const struct snd_soc_dapm_widget cs35l56_dapm_widgets[] = { SND_SOC_DAPM_REGULATOR_SUPPLY("VDD_B", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("VDD_AMP", 0, 0), + SND_SOC_DAPM_SUPPLY("PLAY", SND_SOC_NOPM, 0, 0, cs35l56_play_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_OUT_DRV("AMP", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_OUTPUT("SPK"), @@ -252,6 +304,9 @@ static const struct snd_soc_dapm_route cs35l56_audio_map[] = { { "AMP", NULL, "VDD_B" }, { "AMP", NULL, "VDD_AMP" }, + { "ASP1 Playback", NULL, "PLAY" }, + { "SDW1 Playback", NULL, "PLAY" }, + { "ASP1RX1", NULL, "ASP1 Playback" }, { "ASP1RX2", NULL, "ASP1 Playback" }, { "DSP1", NULL, "ASP1RX1" }, @@ -288,23 +343,6 @@ static const struct snd_soc_dapm_route cs35l56_audio_map[] = { { "SDW1 Capture", NULL, "SDW1 TX6 Source" }, }; -static int cs35l56_mbox_send(struct cs35l56_private *cs35l56, unsigned int command) -{ - unsigned int val; - int ret; - - regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command); - ret = regmap_read_poll_timeout(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, - val, (val == 0), - CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US); - if (ret) { - dev_warn(cs35l56->dev, "MBOX command %#x failed: %d\n", command, ret); - return ret; - } - - return 0; -} - static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -611,43 +649,11 @@ static int cs35l56_asp_dai_set_sysclk(struct snd_soc_dai *dai, return 0; } -static int cs35l56_mute_stream(struct snd_soc_dai *dai, int mute, int stream) -{ - struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); - unsigned int val; - int ret; - - dev_dbg(cs35l56->dev, "%s: %d %s\n", __func__, stream, mute ? "mute" : "unmute"); - - if (stream != SNDRV_PCM_STREAM_PLAYBACK) - return 0; - - if (mute) { - ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_PAUSE); - } else { - ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_PLAY); - if (ret == 0) { - /* Wait for firmware to enter PS0 power state */ - ret = regmap_read_poll_timeout(cs35l56->regmap, - CS35L56_TRANSDUCER_ACTUAL_PS, - val, (val == CS35L56_PS0), - CS35L56_PS0_POLL_US, - CS35L56_PS0_TIMEOUT_US); - if (ret) - dev_err(cs35l56->dev, "PS0 wait failed: %d\n", ret); - ret = 0; - } - } - - return ret; -} - static const struct snd_soc_dai_ops cs35l56_ops = { .set_fmt = cs35l56_asp_dai_set_fmt, .set_tdm_slot = cs35l56_asp_dai_set_tdm_slot, .hw_params = cs35l56_asp_dai_hw_params, .set_sysclk = cs35l56_asp_dai_set_sysclk, - .mute_stream = cs35l56_mute_stream, }; static void cs35l56_sdw_dai_shutdown(struct snd_pcm_substream *substream, @@ -749,7 +755,6 @@ static const struct snd_soc_dai_ops cs35l56_sdw_dai_ops = { .shutdown = cs35l56_sdw_dai_shutdown, .hw_params = cs35l56_sdw_dai_hw_params, .hw_free = cs35l56_sdw_dai_hw_free, - .mute_stream = cs35l56_mute_stream, .set_stream = cs35l56_sdw_dai_set_stream, }; -- cgit From 7816e3407110d887726687740aa18c9ce8eeb0d2 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 11 Apr 2023 16:25:25 +0100 Subject: ASoC: cs35l56: Skip first init_completion wait in dsp_work if init_done At the start of dsp_work() only wait for init_completion if !init_done. This allows system suspend to re-queue dsp_work() without having to do a dummy complete() of init_completion. A dummy completion in system suspend would have to be conditional on init_done. But that would create a possible race condition between our system resume and cs35l56_init() in the corner case that we suspend right after the SoundWire core has enumerated and reported ATTACHED. It is safer and simpler to have cs35l56_init() as the only place that init_completion is completed, and dsp_work() as the only place that it is consumed. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230411152528.329803-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 71565e0fccd8..14cdbf5fd523 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -866,7 +866,8 @@ static void cs35l56_dsp_work(struct work_struct *work) unsigned int val; int ret = 0; - if (!wait_for_completion_timeout(&cs35l56->init_completion, + if (!cs35l56->init_done && + !wait_for_completion_timeout(&cs35l56->init_completion, msecs_to_jiffies(5000))) { dev_err(cs35l56->dev, "%s: init_completion timed out\n", __func__); goto complete; -- cgit From f00abaddf0300bd9ca87918148a26bdb748129db Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 11 Apr 2023 16:25:26 +0100 Subject: ASoC: cs35l56: Always wait for firmware boot in runtime-resume When we are resuming from a system suspend the CS35L56 has probably been hard reset (usually a power-on reset). So we must wait for the firmware to boot. On SoundWire we also need it to re-initialize before we can read the registers to check the CS35L56 state. The simplest way to handle this is for runtime-resume to always wait for firmware boot. If the firmware is already booted the overhead is only one register read. The system-resume will have to runtime-resume the driver anyway before attempting any register access. So this will automatically include the wait for initialization on SoundWire. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230411152528.329803-5-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 14cdbf5fd523..372b07fef827 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -1108,10 +1108,8 @@ int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56) unsigned int val; int ret; - if (!cs35l56->can_hibernate) { - regcache_cache_only(cs35l56->regmap, false); + if (!cs35l56->can_hibernate) goto out_sync; - } if (!cs35l56->sdw_peripheral) { /* @@ -1126,6 +1124,7 @@ int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56) CS35L56_CONTROL_PORT_READY_US + 400); } +out_sync: regcache_cache_only(cs35l56->regmap, false); ret = cs35l56_wait_for_firmware_boot(cs35l56); @@ -1138,7 +1137,6 @@ int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56) if (ret) goto err; -out_sync: /* BOOT_DONE will be 1 if the amp reset */ regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_4, &val); if (val & CS35L56_OTP_BOOT_DONE_MASK) { -- cgit From f9dc6b875ec0a6a6d4091cd9603d193ec98c75a2 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 11 Apr 2023 16:25:27 +0100 Subject: ASoC: cs35l56: Add basic system suspend handling This adds the main handling for system suspend but does not handle re-patching the firmware after system resume. This is a multi-stage suspend and resume because if there is a RESET line it is almost certain that it will be shared by all the amps. So every amp must have done its suspend before we can assert RESET. Likewise we must de-assert RESET before the amps can resume. It's preferable to assert RESET before we turning off regulators, and while they power up. The actual suspend and resume is done by using the pair pm_runtime_force_suspend() and pm_runtime_force_resume() to re-use our runtime suspend/resume sequences. pm_runtime_force_suspend() will disable our pm_runtime. If we were runtime-resumed it calls our runtime_suspend(). pm_runtime_force_resume() re-enables pm_runtime and if we were originally runtime-resumed before the pm_runtime_force_suspend() it calls our runtime_resume(). Otherwise it leaves us runtime-suspended. The general process is therefore: suspend() -> finish dsp_work and then run our runtime_suspend suspend_late() -> assert RESET and turn off supplies resume_early() -> enable supplies and de-assert RESET resume() -> pm_runtime_force_resume() In addition, to prevent the IRQ handler running in the period between pm_runtime_force_suspend() and pm_runtime_force_resume() the parent IRQ is temporarily disabled: - from suspend until suspend_noirq - from resume_noirq until resume Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230411152528.329803-6-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-sdw.c | 26 +++++++++ sound/soc/codecs/cs35l56.c | 126 +++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/cs35l56.h | 6 ++ 3 files changed, 158 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index 448ef3609f4c..947d4e5f4dc9 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -450,6 +450,29 @@ static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev) return 0; } +static int __maybe_unused cs35l56_sdw_system_suspend(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + if (!cs35l56->init_done) + return 0; + + /* + * Disable SoundWire interrupts. + * Flush - don't cancel because that could leave an unbalanced pm_runtime_get. + */ + cs35l56->sdw_irq_no_unmask = true; + flush_work(&cs35l56->sdw_irq_work); + + /* Mask interrupts and flush in case sdw_irq_work was queued again */ + sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); + sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1); + sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); + flush_work(&cs35l56->sdw_irq_work); + + return cs35l56_system_suspend(dev); +} + static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_device_id *id) { struct device *dev = &peripheral->dev; @@ -499,6 +522,9 @@ static int cs35l56_sdw_remove(struct sdw_slave *peripheral) static const struct dev_pm_ops cs35l56_sdw_pm = { SET_RUNTIME_PM_OPS(cs35l56_sdw_runtime_suspend, cs35l56_sdw_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(cs35l56_sdw_system_suspend, cs35l56_system_resume) + LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_late, cs35l56_system_resume_early) + /* NOIRQ stage not needed, SoundWire doesn't use a hard IRQ */ }; static const struct sdw_device_id cs35l56_sdw_id[] = { diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 372b07fef827..74e8de2f81f5 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -11,8 +11,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -1160,6 +1162,127 @@ err: } EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_CORE); +int cs35l56_system_suspend(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + dev_dbg(dev, "system_suspend\n"); + + if (cs35l56->component) + flush_work(&cs35l56->dsp_work); + + /* + * The interrupt line is normally shared, but after we start suspending + * we can't check if our device is the source of an interrupt, and can't + * clear it. Prevent this race by temporarily disabling the parent irq + * until we reach _no_irq. + */ + if (cs35l56->irq) + disable_irq(cs35l56->irq); + + return pm_runtime_force_suspend(dev); +} +EXPORT_SYMBOL_GPL(cs35l56_system_suspend); + +int cs35l56_system_suspend_late(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + dev_dbg(dev, "system_suspend_late\n"); + + /* + * Assert RESET before removing supplies. + * RESET is usually shared by all amps so it must not be asserted until + * all driver instances have done their suspend() stage. + */ + if (cs35l56->reset_gpio) { + gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); + usleep_range(CS35L56_RESET_PULSE_MIN_US, CS35L56_RESET_PULSE_MIN_US + 400); + } + + regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); + + return 0; +} +EXPORT_SYMBOL_GPL(cs35l56_system_suspend_late); + +int cs35l56_system_suspend_no_irq(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + dev_dbg(dev, "system_suspend_no_irq\n"); + + /* Handlers are now disabled so the parent IRQ can safely be re-enabled. */ + if (cs35l56->irq) + enable_irq(cs35l56->irq); + + return 0; +} +EXPORT_SYMBOL_GPL(cs35l56_system_suspend_no_irq); + +int cs35l56_system_resume_no_irq(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + dev_dbg(dev, "system_resume_no_irq\n"); + + /* + * WAKE interrupts unmask if the CS35L56 hibernates, which can cause + * spurious interrupts, and the interrupt line is normally shared. + * We can't check if our device is the source of an interrupt, and can't + * clear it, until it has fully resumed. Prevent this race by temporarily + * disabling the parent irq until we complete resume(). + */ + if (cs35l56->irq) + disable_irq(cs35l56->irq); + + return 0; +} +EXPORT_SYMBOL_GPL(cs35l56_system_resume_no_irq); + +int cs35l56_system_resume_early(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + int ret; + + dev_dbg(dev, "system_resume_early\n"); + + /* Ensure a spec-compliant RESET pulse. */ + if (cs35l56->reset_gpio) { + gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); + usleep_range(CS35L56_RESET_PULSE_MIN_US, CS35L56_RESET_PULSE_MIN_US + 400); + } + + /* Enable supplies before releasing RESET. */ + ret = regulator_bulk_enable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); + if (ret) { + dev_err(dev, "system_resume_early failed to enable supplies: %d\n", ret); + return ret; + } + + /* Release shared RESET before drivers start resume(). */ + gpiod_set_value_cansleep(cs35l56->reset_gpio, 1); + + return 0; +} +EXPORT_SYMBOL_GPL(cs35l56_system_resume_early); + +int cs35l56_system_resume(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + int ret; + + dev_dbg(dev, "system_resume\n"); + + /* Undo pm_runtime_force_suspend() before re-enabling the irq */ + ret = pm_runtime_force_resume(dev); + if (cs35l56->irq) + enable_irq(cs35l56->irq); + + return ret; +} +EXPORT_SYMBOL_GPL(cs35l56_system_resume); + static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) { struct wm_adsp *dsp; @@ -1457,6 +1580,9 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_remove, SND_SOC_CS35L56_CORE); const struct dev_pm_ops cs35l56_pm_ops_i2c_spi = { SET_RUNTIME_PM_OPS(cs35l56_runtime_suspend, cs35l56_runtime_resume_i2c_spi, NULL) + SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend, cs35l56_system_resume) + LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_late, cs35l56_system_resume_early) + NOIRQ_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_no_irq, cs35l56_system_resume_no_irq) }; EXPORT_SYMBOL_NS_GPL(cs35l56_pm_ops_i2c_spi, SND_SOC_CS35L56_CORE); diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index efc4b99180f9..919ba0267ef9 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -68,6 +68,12 @@ extern const struct dev_pm_ops cs35l56_pm_ops_i2c_spi; int cs35l56_runtime_suspend(struct device *dev); int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56); +int cs35l56_system_suspend(struct device *dev); +int cs35l56_system_suspend_late(struct device *dev); +int cs35l56_system_suspend_no_irq(struct device *dev); +int cs35l56_system_resume_no_irq(struct device *dev); +int cs35l56_system_resume_early(struct device *dev); +int cs35l56_system_resume(struct device *dev); irqreturn_t cs35l56_irq(int irq, void *data); int cs35l56_irq_request(struct cs35l56_private *cs35l56); int cs35l56_common_probe(struct cs35l56_private *cs35l56); -- cgit From 39a594dc0b4ac949edf221db33c7061c45e2c90b Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 11 Apr 2023 16:25:23 +0100 Subject: ASoC: cs35l56: Remove quick-cancelling of dsp_work() Delete the 'removing' flag and don't kick init_completion to make a quick cancel of dsp_work(). Just let it timeout on the wait for the completion. Simplify the code to standard cancelling or flushing of the work. This avoids introducing corner cases from a layer of custom signalling. It also avoids potential race conditions when system-suspend handling is added. Unless the hardware is broken, the dsp_work() will already have started and passed the completion before the driver would want to cancel it. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/168122674746.26.16881587647873355224@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 8 +------- sound/soc/codecs/cs35l56.h | 1 - 2 files changed, 1 insertion(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 74e8de2f81f5..eb85c27ab087 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -875,7 +875,7 @@ static void cs35l56_dsp_work(struct work_struct *work) goto complete; } - if (!cs35l56->init_done || cs35l56->removing) + if (!cs35l56->init_done) goto complete; cs35l56->dsp.part = devm_kasprintf(cs35l56->dev, GFP_KERNEL, "cs35l56%s-%02x", @@ -925,9 +925,6 @@ static void cs35l56_dsp_work(struct work_struct *work) goto err; } - if (cs35l56->removing) - goto err; - mutex_lock(&cs35l56->irq_lock); init_completion(&cs35l56->init_completion); @@ -975,7 +972,6 @@ static int cs35l56_component_probe(struct snd_soc_component *component) BUILD_BUG_ON(ARRAY_SIZE(cs35l56_tx_input_texts) != ARRAY_SIZE(cs35l56_tx_input_values)); - cs35l56->removing = false; cs35l56->component = component; wm_adsp2_component_probe(&cs35l56->dsp, component); @@ -992,8 +988,6 @@ static void cs35l56_component_remove(struct snd_soc_component *component) { struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); - cs35l56->removing = true; - complete(&cs35l56->init_completion); cancel_work_sync(&cs35l56->dsp_work); } diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index 919ba0267ef9..50278dafc9ca 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -49,7 +49,6 @@ struct cs35l56_private { bool soft_resetting; bool init_done; bool sdw_attached; - bool removing; bool fw_patched; bool can_hibernate; struct completion init_completion; -- cgit From 59322d35179987e85b593e504fd334de8683c835 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 11 Apr 2023 16:25:28 +0100 Subject: ASoC: cs35l56: Re-patch firmware after system suspend Check during cs35l56_system_resume() whether the firmware patch must be applied again. The FIRMWARE_MISSING flag in the PROTECTION_STATUS register indicates whether the firmware has been patched. In non-secure mode the FIRMWARE_MISSING flag is cleared at the end of dsp_work(). If it is set after system-resume we know that dsp_work() must be run again. In secure mode the pre-OS loader will have done the secure patching and cleared the FIRMWARE_MISSING flag. So this flag does not tell us whether firmware memory was lost. But the driver could only be downloading non-secure tunings, which is always safe to do. If the driver has control of RESET we will have asserted it during suspend so the firmware patch will have been lost. The driver would only have control of RESET in non-secure mode. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/168122674550.26.8545058503709956172@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-sdw.c | 12 +++++++- sound/soc/codecs/cs35l56.c | 67 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index 947d4e5f4dc9..e759347423cf 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -473,6 +473,16 @@ static int __maybe_unused cs35l56_sdw_system_suspend(struct device *dev) return cs35l56_system_suspend(dev); } +static int __maybe_unused cs35l56_sdw_system_resume(struct device *dev) +{ + struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + + cs35l56->sdw_irq_no_unmask = false; + /* runtime_resume re-enables the interrupt */ + + return cs35l56_system_resume(dev); +} + static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_device_id *id) { struct device *dev = &peripheral->dev; @@ -522,7 +532,7 @@ static int cs35l56_sdw_remove(struct sdw_slave *peripheral) static const struct dev_pm_ops cs35l56_sdw_pm = { SET_RUNTIME_PM_OPS(cs35l56_sdw_runtime_suspend, cs35l56_sdw_runtime_resume, NULL) - SYSTEM_SLEEP_PM_OPS(cs35l56_sdw_system_suspend, cs35l56_system_resume) + SYSTEM_SLEEP_PM_OPS(cs35l56_sdw_system_suspend, cs35l56_sdw_system_resume) LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_late, cs35l56_system_resume_early) /* NOIRQ stage not needed, SoundWire doesn't use a hard IRQ */ }; diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index eb85c27ab087..18e341744839 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -946,6 +946,7 @@ static void cs35l56_dsp_work(struct work_struct *work) goto err_unlock; } + regmap_clear_bits(cs35l56->regmap, CS35L56_PROTECTION_STATUS, CS35L56_FIRMWARE_MISSING); cs35l56->fw_patched = true; err_unlock: @@ -1026,6 +1027,8 @@ static const struct snd_soc_component_driver soc_component_dev_cs35l56 = { .num_controls = ARRAY_SIZE(cs35l56_controls), .set_bias_level = cs35l56_set_bias_level, + + .suspend_bias_off = 1, /* see cs35l56_system_resume() */ }; static const struct reg_sequence cs35l56_hibernate_seq[] = { @@ -1156,6 +1159,47 @@ err: } EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_CORE); +static int cs35l56_is_fw_reload_needed(struct cs35l56_private *cs35l56) +{ + unsigned int val; + int ret; + + /* Nothing to re-patch if we haven't done any patching yet. */ + if (!cs35l56->fw_patched) + return false; + + /* + * If we have control of RESET we will have asserted it so the firmware + * will need re-patching. + */ + if (cs35l56->reset_gpio) + return true; + + /* + * In secure mode FIRMWARE_MISSING is cleared by the BIOS loader so + * can't be used here to test for memory retention. + * Assume that tuning must be re-loaded. + */ + if (cs35l56->secured) + return true; + + ret = pm_runtime_resume_and_get(cs35l56->dev); + if (ret) { + dev_err(cs35l56->dev, "Failed to runtime_get: %d\n", ret); + return ret; + } + + ret = regmap_read(cs35l56->regmap, CS35L56_PROTECTION_STATUS, &val); + if (ret) + dev_err(cs35l56->dev, "Failed to read PROTECTION_STATUS: %d\n", ret); + else + ret = !!(val & CS35L56_FIRMWARE_MISSING); + + pm_runtime_put_autosuspend(cs35l56->dev); + + return ret; +} + int cs35l56_system_suspend(struct device *dev) { struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); @@ -1273,7 +1317,28 @@ int cs35l56_system_resume(struct device *dev) if (cs35l56->irq) enable_irq(cs35l56->irq); - return ret; + if (ret) + return ret; + + /* Firmware won't have been loaded if the component hasn't probed */ + if (!cs35l56->component) + return 0; + + ret = cs35l56_is_fw_reload_needed(cs35l56); + dev_dbg(cs35l56->dev, "fw_reload_needed: %d\n", ret); + if (ret < 1) + return ret; + + cs35l56->fw_patched = false; + init_completion(&cs35l56->dsp_ready_completion); + queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work); + + /* + * suspend_bias_off ensures we are now in BIAS_OFF so there will be + * a BIAS_OFF->BIAS_STANDBY transition to complete dsp patching. + */ + + return 0; } EXPORT_SYMBOL_GPL(cs35l56_system_resume); -- cgit From 2c17277893747e30e41d1a7b57b80f2b298da278 Mon Sep 17 00:00:00 2001 From: David Rau Date: Thu, 13 Apr 2023 02:41:34 +0000 Subject: ASoC: da7219: Improve the relability of AAD IRQ process - Configure the default gound switch delay time before enabling IRQ to avoid the unexpected delay time is set up - Apply DA7219 AAD own work queue to handle AAD events - Replace msleep with queue_delayed_work to have better relability This commit improves the control of ground switches in AAD IRQ Signed-off-by: David Rau Link: https://lore.kernel.org/r/20230413024134.8612-1-David.Rau.opensource@dm.renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/da7219-aad.c | 60 +++++++++++++++++++++---------------------- sound/soc/codecs/da7219-aad.h | 5 ++-- 2 files changed, 31 insertions(+), 34 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index e3d398b8f54e..993a0d00bc48 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -342,36 +342,17 @@ static void da7219_aad_hptest_work(struct work_struct *work) static void da7219_aad_jack_det_work(struct work_struct *work) { struct da7219_aad_priv *da7219_aad = - container_of(work, struct da7219_aad_priv, jack_det_work); + container_of(work, struct da7219_aad_priv, jack_det_work.work); struct snd_soc_component *component = da7219_aad->component; - u8 srm_st; - mutex_lock(&da7219_aad->jack_det_mutex); - - srm_st = snd_soc_component_read(component, DA7219_PLL_SRM_STS) & DA7219_PLL_SRM_STS_MCLK; - msleep(da7219_aad->gnd_switch_delay * ((srm_st == 0x0) ? 2 : 1) - 4); /* Enable ground switch */ snd_soc_component_update_bits(component, 0xFB, 0x01, 0x01); - - mutex_unlock(&da7219_aad->jack_det_mutex); } - /* * IRQ */ -static irqreturn_t da7219_aad_pre_irq_thread(int irq, void *data) -{ - - struct da7219_aad_priv *da7219_aad = data; - - if (!da7219_aad->jack_inserted) - schedule_work(&da7219_aad->jack_det_work); - - return IRQ_WAKE_THREAD; -} - static irqreturn_t da7219_aad_irq_thread(int irq, void *data) { struct da7219_aad_priv *da7219_aad = data; @@ -392,6 +373,18 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) /* Read status register for jack insertion & type status */ statusa = snd_soc_component_read(component, DA7219_ACCDET_STATUS_A); + if (events[DA7219_AAD_IRQ_REG_A] & DA7219_E_JACK_INSERTED_MASK) { + u8 srm_st; + int delay = 0; + + srm_st = snd_soc_component_read(component, + DA7219_PLL_SRM_STS) & DA7219_PLL_SRM_STS_MCLK; + delay = (da7219_aad->gnd_switch_delay * ((srm_st == 0x0) ? 2 : 1) - 2); + queue_delayed_work(da7219_aad->aad_wq, + &da7219_aad->jack_det_work, + msecs_to_jiffies(delay)); + } + /* Clear events */ regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A, events, DA7219_AAD_IRQ_REG_MAX); @@ -400,9 +393,6 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) events[DA7219_AAD_IRQ_REG_A], events[DA7219_AAD_IRQ_REG_B], statusa); - if (!da7219_aad->jack_inserted) - cancel_work_sync(&da7219_aad->jack_det_work); - if (statusa & DA7219_JACK_INSERTION_STS_MASK) { /* Jack Insertion */ if (events[DA7219_AAD_IRQ_REG_A] & @@ -430,9 +420,9 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) if (statusa & DA7219_JACK_TYPE_STS_MASK) { report |= SND_JACK_HEADSET; mask |= SND_JACK_HEADSET | SND_JACK_LINEOUT; - schedule_work(&da7219_aad->btn_det_work); + queue_work(da7219_aad->aad_wq, &da7219_aad->btn_det_work); } else { - schedule_work(&da7219_aad->hptest_work); + queue_work(da7219_aad->aad_wq, &da7219_aad->hptest_work); } } @@ -465,6 +455,7 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) da7219_aad->jack_inserted = false; /* Cancel any pending work */ + cancel_delayed_work_sync(&da7219_aad->jack_det_work); cancel_work_sync(&da7219_aad->btn_det_work); cancel_work_sync(&da7219_aad->hptest_work); @@ -964,13 +955,19 @@ int da7219_aad_init(struct snd_soc_component *component) snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1, DA7219_BUTTON_CONFIG_MASK, 0); + da7219_aad_handle_gnd_switch_time(component); + + da7219_aad->aad_wq = create_singlethread_workqueue("da7219-aad"); + if (!da7219_aad->aad_wq) { + dev_err(component->dev, "Failed to create aad workqueue\n"); + return -ENOMEM; + } + + INIT_DELAYED_WORK(&da7219_aad->jack_det_work, da7219_aad_jack_det_work); INIT_WORK(&da7219_aad->btn_det_work, da7219_aad_btn_det_work); INIT_WORK(&da7219_aad->hptest_work, da7219_aad_hptest_work); - INIT_WORK(&da7219_aad->jack_det_work, da7219_aad_jack_det_work); - - mutex_init(&da7219_aad->jack_det_mutex); - ret = request_threaded_irq(da7219_aad->irq, da7219_aad_pre_irq_thread, + ret = request_threaded_irq(da7219_aad->irq, NULL, da7219_aad_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "da7219-aad", da7219_aad); @@ -984,8 +981,6 @@ int da7219_aad_init(struct snd_soc_component *component) regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A, &mask, DA7219_AAD_IRQ_REG_MAX); - da7219_aad_handle_gnd_switch_time(component); - return 0; } @@ -1002,8 +997,10 @@ void da7219_aad_exit(struct snd_soc_component *component) free_irq(da7219_aad->irq, da7219_aad); + cancel_delayed_work_sync(&da7219_aad->jack_det_work); cancel_work_sync(&da7219_aad->btn_det_work); cancel_work_sync(&da7219_aad->hptest_work); + destroy_workqueue(da7219_aad->aad_wq); } /* @@ -1031,4 +1028,5 @@ int da7219_aad_probe(struct i2c_client *i2c) MODULE_DESCRIPTION("ASoC DA7219 AAD Driver"); MODULE_AUTHOR("Adam Thomson "); +MODULE_AUTHOR("David Rau "); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/da7219-aad.h b/sound/soc/codecs/da7219-aad.h index be87ee47edde..fbfbf3e67918 100644 --- a/sound/soc/codecs/da7219-aad.h +++ b/sound/soc/codecs/da7219-aad.h @@ -197,9 +197,8 @@ struct da7219_aad_priv { struct work_struct btn_det_work; struct work_struct hptest_work; - struct work_struct jack_det_work; - - struct mutex jack_det_mutex; + struct delayed_work jack_det_work; + struct workqueue_struct *aad_wq; struct snd_soc_jack *jack; bool micbias_resume_enable; -- cgit From c6c3581a3e178882c8815462ca129e60be50fde8 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 13 Apr 2023 07:28:33 +0200 Subject: ASoC: da7218: Use devm_clk_get_optional() Use devm_clk_get_optional() instead of hand writing it. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/51976b2515d7007ba5c8aa7524892f147d7cdd51.1681363691.git.christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/codecs/da7218.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index 91372909d184..d9c28e701613 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -2893,14 +2893,10 @@ static int da7218_probe(struct snd_soc_component *component) da7218_handle_pdata(component); /* Check if MCLK provided, if not the clock is NULL */ - da7218->mclk = devm_clk_get(component->dev, "mclk"); + da7218->mclk = devm_clk_get_optional(component->dev, "mclk"); if (IS_ERR(da7218->mclk)) { - if (PTR_ERR(da7218->mclk) != -ENOENT) { - ret = PTR_ERR(da7218->mclk); - goto err_disable_reg; - } else { - da7218->mclk = NULL; - } + ret = PTR_ERR(da7218->mclk); + goto err_disable_reg; } /* Default PC to free-running */ -- cgit From fc0b096c92918c2ba4d76411ea763fdeb2ef6b0d Mon Sep 17 00:00:00 2001 From: David Lin Date: Fri, 14 Apr 2023 18:39:44 +0800 Subject: ASoC: nau8825: Add delay control for input path Change the original fixed delay to the assignment from property. It will make more flexible to different platforms for avoiding pop noise at the beginning of recording. Signed-off-by: David Lin Link: https://lore.kernel.org/r/20230414103941.39566-2-CTLIN0@nuvoton.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8825.c | 8 +++++++- sound/soc/codecs/nau8825.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 4bffa9c20f2b..c4389f5fe603 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -919,7 +919,7 @@ static int nau8825_adc_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: - msleep(125); + msleep(nau8825->adc_delay); regmap_update_bits(nau8825->regmap, NAU8825_REG_ENA_CTRL, NAU8825_ENABLE_ADC, NAU8825_ENABLE_ADC); break; @@ -2752,6 +2752,7 @@ static void nau8825_print_device_properties(struct nau8825 *nau8825) dev_dbg(dev, "crosstalk-enable: %d\n", nau8825->xtalk_enable); dev_dbg(dev, "adcout-drive-strong: %d\n", nau8825->adcout_ds); + dev_dbg(dev, "adc-delay-ms: %d\n", nau8825->adc_delay); } static int nau8825_read_device_properties(struct device *dev, @@ -2819,6 +2820,11 @@ static int nau8825_read_device_properties(struct device *dev, nau8825->xtalk_enable = device_property_read_bool(dev, "nuvoton,crosstalk-enable"); nau8825->adcout_ds = device_property_read_bool(dev, "nuvoton,adcout-drive-strong"); + ret = device_property_read_u32(dev, "nuvoton,adc-delay-ms", &nau8825->adc_delay); + if (ret) + nau8825->adc_delay = 125; + if (nau8825->adc_delay < 125 && nau8825->adc_delay > 500) + dev_warn(dev, "Please set the suitable delay time!\n"); nau8825->mclk = devm_clk_get(dev, "mclk"); if (PTR_ERR(nau8825->mclk) == -EPROBE_DEFER) { diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h index 0c3a446e0e1a..44b62bc3880f 100644 --- a/sound/soc/codecs/nau8825.h +++ b/sound/soc/codecs/nau8825.h @@ -517,6 +517,7 @@ struct nau8825 { int xtalk_enable; bool xtalk_baktab_initialized; /* True if initialized. */ bool adcout_ds; + int adc_delay; }; int nau8825_enable_jack_detect(struct snd_soc_component *component, -- cgit From 7d72351a4ef6e1e763bccc24d43c44ffbe1a1555 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Fri, 14 Apr 2023 14:37:49 +0100 Subject: ASoC: cs35l56: Rework IRQ allocation The irq member was being set before calling the init function and then cs35l56_irq_request() was called only when the init was successful. However cs35l56_release() calls devm_free_irq() when the irq member is set and therefore if init() fails then this will cause an attempted free of an unallocated IRQ. Instead pass the desired IRQ number to the cs35l56_irq_request() function and set cs35l56->irq only when it has been successfully allocated. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/168147949598.26.711670799488943454@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-i2c.c | 3 +-- sound/soc/codecs/cs35l56-spi.c | 3 +-- sound/soc/codecs/cs35l56.c | 11 ++++++----- sound/soc/codecs/cs35l56.h | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c index 4b7f034a7670..295caad26224 100644 --- a/sound/soc/codecs/cs35l56-i2c.c +++ b/sound/soc/codecs/cs35l56-i2c.c @@ -27,7 +27,6 @@ static int cs35l56_i2c_probe(struct i2c_client *client) return -ENOMEM; cs35l56->dev = dev; - cs35l56->irq = client->irq; cs35l56->can_hibernate = true; i2c_set_clientdata(client, cs35l56); @@ -43,7 +42,7 @@ static int cs35l56_i2c_probe(struct i2c_client *client) ret = cs35l56_init(cs35l56); if (ret == 0) - ret = cs35l56_irq_request(cs35l56); + ret = cs35l56_irq_request(cs35l56, client->irq); if (ret < 0) cs35l56_remove(cs35l56); diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c index 4b2084e85f29..996aab10500e 100644 --- a/sound/soc/codecs/cs35l56-spi.c +++ b/sound/soc/codecs/cs35l56-spi.c @@ -32,7 +32,6 @@ static int cs35l56_spi_probe(struct spi_device *spi) } cs35l56->dev = &spi->dev; - cs35l56->irq = spi->irq; ret = cs35l56_common_probe(cs35l56); if (ret != 0) @@ -40,7 +39,7 @@ static int cs35l56_spi_probe(struct spi_device *spi) ret = cs35l56_init(cs35l56); if (ret == 0) - ret = cs35l56_irq_request(cs35l56); + ret = cs35l56_irq_request(cs35l56, spi->irq); if (ret < 0) cs35l56_remove(cs35l56); diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 18e341744839..5ea7f419cda6 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -423,18 +423,19 @@ err_unlock: } EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_CORE); -int cs35l56_irq_request(struct cs35l56_private *cs35l56) +int cs35l56_irq_request(struct cs35l56_private *cs35l56, int irq) { int ret; - if (!cs35l56->irq) + if (!irq) return 0; - ret = devm_request_threaded_irq(cs35l56->dev, cs35l56->irq, NULL, - cs35l56_irq, + ret = devm_request_threaded_irq(cs35l56->dev, irq, NULL, cs35l56_irq, IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW, "cs35l56", cs35l56); - if (ret < 0) + if (!ret) + cs35l56->irq = irq; + else dev_err(cs35l56->dev, "Failed to get IRQ: %d\n", ret); return ret; diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index 50278dafc9ca..ac2e9237c27d 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -74,7 +74,7 @@ int cs35l56_system_resume_no_irq(struct device *dev); int cs35l56_system_resume_early(struct device *dev); int cs35l56_system_resume(struct device *dev); irqreturn_t cs35l56_irq(int irq, void *data); -int cs35l56_irq_request(struct cs35l56_private *cs35l56); +int cs35l56_irq_request(struct cs35l56_private *cs35l56, int irq); int cs35l56_common_probe(struct cs35l56_private *cs35l56); int cs35l56_init(struct cs35l56_private *cs35l56); int cs35l56_remove(struct cs35l56_private *cs35l56); -- cgit From b82396122b028a07ce2977e3f33123d7ab526d91 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Fri, 14 Apr 2023 14:37:50 +0100 Subject: ASoC: cs35l56: Allow a wider range for reset pulse width There is no reason to have such a tight usleep range of 400us and it is acceptable to allow MIN_US * 2. Also wrap the usleep in an inline function. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/168147949455.26.3401634900657387799@mailman-core.alsa-project.org Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 5ea7f419cda6..d60095162bfa 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -835,6 +835,12 @@ static int cs35l56_wait_for_firmware_boot(struct cs35l56_private *cs35l56) return 0; } +static inline void cs35l56_wait_min_reset_pulse(void) +{ + /* Satisfy minimum reset pulse width spec */ + usleep_range(CS35L56_RESET_PULSE_MIN_US, 2 * CS35L56_RESET_PULSE_MIN_US); +} + static const struct reg_sequence cs35l56_system_reset_seq[] = { REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), }; @@ -1236,7 +1242,7 @@ int cs35l56_system_suspend_late(struct device *dev) */ if (cs35l56->reset_gpio) { gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); - usleep_range(CS35L56_RESET_PULSE_MIN_US, CS35L56_RESET_PULSE_MIN_US + 400); + cs35l56_wait_min_reset_pulse(); } regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); @@ -1289,7 +1295,7 @@ int cs35l56_system_resume_early(struct device *dev) /* Ensure a spec-compliant RESET pulse. */ if (cs35l56->reset_gpio) { gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); - usleep_range(CS35L56_RESET_PULSE_MIN_US, CS35L56_RESET_PULSE_MIN_US + 400); + cs35l56_wait_min_reset_pulse(); } /* Enable supplies before releasing RESET. */ @@ -1440,9 +1446,7 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) return dev_err_probe(cs35l56->dev, ret, "Failed to enable supplies\n"); if (cs35l56->reset_gpio) { - /* satisfy minimum reset pulse width spec */ - usleep_range(CS35L56_RESET_PULSE_MIN_US, - CS35L56_RESET_PULSE_MIN_US + 400); + cs35l56_wait_min_reset_pulse(); gpiod_set_value_cansleep(cs35l56->reset_gpio, 1); } -- cgit From 440c2d38950f738d7a35d3d29533728e74586d54 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Fri, 14 Apr 2023 14:37:51 +0100 Subject: ASoC: cs35l56: Wait for init_complete in cs35l56_component_probe() Moving the wait from the beginning of the cs35l56_dsp_work() into cs35l56_component_probe() will prevent the limbo situation that is an artifact of the two stage SoundWire driver probe and initialisation where the card is all registered and shows in ALSA but doesn't actually work because the hardware didn't enumerate. The other bus drivers perform the probe and init sequentially and are not susceptible to this issue. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230414133753.653139-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index d60095162bfa..ab2e663af6c2 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -875,13 +875,6 @@ static void cs35l56_dsp_work(struct work_struct *work) unsigned int val; int ret = 0; - if (!cs35l56->init_done && - !wait_for_completion_timeout(&cs35l56->init_completion, - msecs_to_jiffies(5000))) { - dev_err(cs35l56->dev, "%s: init_completion timed out\n", __func__); - goto complete; - } - if (!cs35l56->init_done) goto complete; @@ -980,6 +973,12 @@ static int cs35l56_component_probe(struct snd_soc_component *component) BUILD_BUG_ON(ARRAY_SIZE(cs35l56_tx_input_texts) != ARRAY_SIZE(cs35l56_tx_input_values)); + if (!wait_for_completion_timeout(&cs35l56->init_completion, + msecs_to_jiffies(5000))) { + dev_err(cs35l56->dev, "%s: init_completion timed out\n", __func__); + return -ENODEV; + } + cs35l56->component = component; wm_adsp2_component_probe(&cs35l56->dsp, component); -- cgit From 4be476830bf96c0095e4e1acdfc12081aa0fb165 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Fri, 14 Apr 2023 14:37:52 +0100 Subject: ASoC: cs35l56: Remove redundant dsp_ready_completion dsp_ready_completion is redundant and can be replaced by a call flush_work() to wait for cs35l56_dsp_work() to complete. As the dsp_work is queued by component_probe() it must run before other ASoC component callbacks and therefore there is no risk of calling flush_work() before the dsp_work() has been queued. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230414133753.653139-5-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 41 +++++++++-------------------------------- sound/soc/codecs/cs35l56.h | 1 - 2 files changed, 9 insertions(+), 33 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index ab2e663af6c2..5f66a8e20b2d 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -51,21 +51,10 @@ static int cs35l56_mbox_send(struct cs35l56_private *cs35l56, unsigned int comma return 0; } -static int cs35l56_wait_dsp_ready(struct cs35l56_private *cs35l56) +static void cs35l56_wait_dsp_ready(struct cs35l56_private *cs35l56) { - int ret; - - if (!cs35l56->fw_patched) { - /* block until firmware download completes */ - ret = wait_for_completion_timeout(&cs35l56->dsp_ready_completion, - msecs_to_jiffies(25000)); - if (!ret) { - dev_err(cs35l56->dev, "dsp_ready_completion timeout\n"); - return -ETIMEDOUT; - } - } - - return 0; + /* Wait for patching to complete */ + flush_work(&cs35l56->dsp_work); } static int cs35l56_dspwait_get_volsw(struct snd_kcontrol *kcontrol, @@ -73,11 +62,8 @@ static int cs35l56_dspwait_get_volsw(struct snd_kcontrol *kcontrol, { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); - int ret = cs35l56_wait_dsp_ready(cs35l56); - - if (ret) - return ret; + cs35l56_wait_dsp_ready(cs35l56); return snd_soc_get_volsw(kcontrol, ucontrol); } @@ -86,11 +72,8 @@ static int cs35l56_dspwait_put_volsw(struct snd_kcontrol *kcontrol, { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); - int ret = cs35l56_wait_dsp_ready(cs35l56); - - if (ret) - return ret; + cs35l56_wait_dsp_ready(cs35l56); return snd_soc_put_volsw(kcontrol, ucontrol); } @@ -876,13 +859,13 @@ static void cs35l56_dsp_work(struct work_struct *work) int ret = 0; if (!cs35l56->init_done) - goto complete; + return; cs35l56->dsp.part = devm_kasprintf(cs35l56->dev, GFP_KERNEL, "cs35l56%s-%02x", cs35l56->secured ? "s" : "", cs35l56->rev); if (!cs35l56->dsp.part) - goto complete; + return; pm_runtime_get_sync(cs35l56->dev); @@ -961,9 +944,6 @@ err: sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, CS35L56_SDW_INT_MASK_CODEC_IRQ); } - -complete: - complete_all(&cs35l56->dsp_ready_completion); } static int cs35l56_component_probe(struct snd_soc_component *component) @@ -1002,7 +982,6 @@ static int cs35l56_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); - int ret = 0; switch (level) { case SND_SOC_BIAS_STANDBY: @@ -1011,14 +990,14 @@ static int cs35l56_set_bias_level(struct snd_soc_component *component, * BIAS_OFF to BIAS_STANDBY */ if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) - ret = cs35l56_wait_dsp_ready(cs35l56); + cs35l56_wait_dsp_ready(cs35l56); break; default: break; } - return ret; + return 0; } static const struct snd_soc_component_driver soc_component_dev_cs35l56 = { @@ -1336,7 +1315,6 @@ int cs35l56_system_resume(struct device *dev) return ret; cs35l56->fw_patched = false; - init_completion(&cs35l56->dsp_ready_completion); queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work); /* @@ -1358,7 +1336,6 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) return -ENOMEM; INIT_WORK(&cs35l56->dsp_work, cs35l56_dsp_work); - init_completion(&cs35l56->dsp_ready_completion); dsp = &cs35l56->dsp; dsp->part = "cs35l56"; diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index ac2e9237c27d..09762e70ce81 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -34,7 +34,6 @@ struct cs35l56_private { struct wm_adsp dsp; /* must be first member */ struct work_struct dsp_work; struct workqueue_struct *dsp_wq; - struct completion dsp_ready_completion; struct mutex irq_lock; struct snd_soc_component *component; struct device *dev; -- cgit From 9ed4c762e214a6592184d0dd65b6db86ad30e6d5 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Fri, 14 Apr 2023 14:37:53 +0100 Subject: ASoC: cs35l56: Don't return a value from cs35l56_remove() cs35l56_remove() always returns 0. Two of the functions that call it are void and the other one should only return 0. So there's no point returning anything from cs35l56_remove(). Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230414133753.653139-6-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-sdw.c | 4 +++- sound/soc/codecs/cs35l56.c | 4 +--- sound/soc/codecs/cs35l56.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index e759347423cf..2cde78605ba9 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -527,7 +527,9 @@ static int cs35l56_sdw_remove(struct sdw_slave *peripheral) sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); - return cs35l56_remove(cs35l56); + cs35l56_remove(cs35l56); + + return 0; } static const struct dev_pm_ops cs35l56_sdw_pm = { diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 5f66a8e20b2d..0f4a94b02ef8 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -1590,7 +1590,7 @@ post_soft_reset: } EXPORT_SYMBOL_NS_GPL(cs35l56_init, SND_SOC_CS35L56_CORE); -int cs35l56_remove(struct cs35l56_private *cs35l56) +void cs35l56_remove(struct cs35l56_private *cs35l56) { cs35l56->init_done = false; @@ -1613,8 +1613,6 @@ int cs35l56_remove(struct cs35l56_private *cs35l56) gpiod_set_value_cansleep(cs35l56->reset_gpio, 0); regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); - - return 0; } EXPORT_SYMBOL_NS_GPL(cs35l56_remove, SND_SOC_CS35L56_CORE); diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index 09762e70ce81..1f7894662fcb 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -76,6 +76,6 @@ irqreturn_t cs35l56_irq(int irq, void *data); int cs35l56_irq_request(struct cs35l56_private *cs35l56, int irq); int cs35l56_common_probe(struct cs35l56_private *cs35l56); int cs35l56_init(struct cs35l56_private *cs35l56); -int cs35l56_remove(struct cs35l56_private *cs35l56); +void cs35l56_remove(struct cs35l56_private *cs35l56); #endif /* ifndef CS35L56_H */ -- cgit From 8076c586bbc1c62e075e58f41dafdd8b5022b24d Mon Sep 17 00:00:00 2001 From: Paweł Anikiel Date: Fri, 14 Apr 2023 16:02:00 +0200 Subject: ASoC: ssm2602: Add support for CLKDIV2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SSM260x chips have an internal MCLK /2 divider (bit D7 in register R8). Add logic that allows for more MCLK values using this divider. Signed-off-by: Paweł Anikiel Link: https://lore.kernel.org/r/20230414140203.707729-7-pan@semihalf.com Signed-off-by: Mark Brown --- sound/soc/codecs/ssm2602.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index cbbe83b85ada..00b60369b029 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -280,9 +280,12 @@ static inline int ssm2602_get_coeff(int mclk, int rate) int i; for (i = 0; i < ARRAY_SIZE(ssm2602_coeff_table); i++) { - if (ssm2602_coeff_table[i].rate == rate && - ssm2602_coeff_table[i].mclk == mclk) - return ssm2602_coeff_table[i].srate; + if (ssm2602_coeff_table[i].rate == rate) { + if (ssm2602_coeff_table[i].mclk == mclk) + return ssm2602_coeff_table[i].srate; + if (ssm2602_coeff_table[i].mclk == mclk / 2) + return ssm2602_coeff_table[i].srate | SRATE_CORECLK_DIV2; + } } return -EINVAL; } @@ -365,18 +368,24 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai, switch (freq) { case 12288000: case 18432000: + case 24576000: + case 36864000: ssm2602->sysclk_constraints = &ssm2602_constraints_12288000; break; case 11289600: case 16934400: + case 22579200: + case 33868800: ssm2602->sysclk_constraints = &ssm2602_constraints_11289600; break; case 12000000: + case 24000000: ssm2602->sysclk_constraints = NULL; break; default: return -EINVAL; } + ssm2602->sysclk = freq; } else { unsigned int mask; -- cgit From 4a778bdc7afbc422bd513c4f1cd7a9faf4bebaab Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Apr 2023 00:15:48 +0000 Subject: ASoC: expand snd_soc_dapm_mutex_lock/unlock() soc.h has snd_soc_dapm_mutex_lock/unlock() definition and many drivers are using it, but soc-dapm.c is not. 1st reason is snd_soc_dapm_mutex_lock/unlock() requests snd_soc_dapm_context pointer as parameter (A), but sometimes soc-dapm.c needs to use snd_soc_card (B). (A) static inline void snd_soc_dapm_mutex_lock(struct snd_soc_dapm_context *dapm) { mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); } ^^^^^^^^^^ (B) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); ^^^^ 2nd reason is it want to use SND_SOC_DAPM_CLASS_INIT for mutex_lock_nested(), but helper is using _RUNTIME (A). The conclusion is we want to use "dapm vs card" and "_RUNTIME vs _INIT" for dapm lock/unlock. To enable this selfish request, this patch uses _Generic macro. We can use snd_soc_dapm_mutex_lock/unlock() for both dapm and card case. snd_soc_dapm_mutex_lock(dapm); snd_soc_dapm_mutex_unlock(dapm); snd_soc_dapm_mutex_lock(card); snd_soc_dapm_mutex_unlock(card); Current soc-dapm.c is using both mutex_lock() and mutex_lock_nested(). This patch handles mutex_lock() as mutex_lock_nested(..., 0), in other words, handles below as same. mutex_lock(&card->dapm_mutex); mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); Because people might misunderstand that _init() is mutex initialization, this patch renames _INIT to _ROOT and adds new snd_soc_dapm_mutex_lock_root() for it. This patch also moves snd_soc_dapm_subclass definition from soc-dapm.h to soc.h to keep related code together. Because very complex soc.h vs soc-dapm.h relationship, it is difficult/impossible to define these helper into soc-dapm.h. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87cz4hx3v0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 119 +++++++++++++++++++++++++-------------------------- 1 file changed, 58 insertions(+), 61 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 36e6f261bcf7..f2f04ce693a1 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -150,7 +150,7 @@ static int dapm_down_seq[] = { static void dapm_assert_locked(struct snd_soc_dapm_context *dapm) { if (snd_soc_card_is_instantiated(dapm->card)) - lockdep_assert_held(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_assert_held(dapm); } static void pop_wait(u32 pop_time) @@ -302,7 +302,7 @@ void dapm_mark_endpoints_dirty(struct snd_soc_card *card) { struct snd_soc_dapm_widget *w; - mutex_lock(&card->dapm_mutex); + snd_soc_dapm_mutex_lock_root(card); for_each_card_widgets(card, w) { if (w->is_ep) { @@ -314,7 +314,7 @@ void dapm_mark_endpoints_dirty(struct snd_soc_card *card) } } - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); } EXPORT_SYMBOL_GPL(dapm_mark_endpoints_dirty); @@ -604,7 +604,7 @@ static void dapm_reset(struct snd_soc_card *card) { struct snd_soc_dapm_widget *w; - lockdep_assert_held(&card->dapm_mutex); + snd_soc_dapm_mutex_assert_held(card); memset(&card->dapm_stats, 0, sizeof(card->dapm_stats)); @@ -1302,7 +1302,7 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, int paths; int ret; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); if (stream == SNDRV_PCM_STREAM_PLAYBACK) { invalidate_paths_ep(w, SND_SOC_DAPM_DIR_OUT); @@ -1322,7 +1322,7 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, paths = ret; trace_snd_soc_dapm_connected(paths, stream); - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); return paths; } @@ -1952,7 +1952,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) enum snd_soc_bias_level bias; int ret; - lockdep_assert_held(&card->dapm_mutex); + snd_soc_dapm_mutex_assert_held(card); trace_snd_soc_dapm_start(card); @@ -2090,7 +2090,6 @@ static ssize_t dapm_widget_power_read_file(struct file *file, size_t count, loff_t *ppos) { struct snd_soc_dapm_widget *w = file->private_data; - struct snd_soc_card *card = w->dapm->card; enum snd_soc_dapm_direction dir, rdir; char *buf; int in, out; @@ -2101,7 +2100,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file, if (!buf) return -ENOMEM; - mutex_lock(&card->dapm_mutex); + snd_soc_dapm_mutex_lock_root(w->dapm); /* Supply widgets are not handled by is_connected_{input,output}_ep() */ if (w->is_supply) { @@ -2145,7 +2144,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file, } } - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(w->dapm); ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); @@ -2266,7 +2265,7 @@ static int soc_dapm_mux_update_power(struct snd_soc_card *card, int found = 0; bool connect; - lockdep_assert_held(&card->dapm_mutex); + snd_soc_dapm_mutex_assert_held(card); /* find dapm widget path assoc with kcontrol */ dapm_kcontrol_for_each_path(path, kcontrol) { @@ -2293,11 +2292,11 @@ int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, struct snd_soc_card *card = dapm->card; int ret; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); card->update = update; ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); card->update = NULL; - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); if (ret > 0) snd_soc_dpcm_runtime_update(card); return ret; @@ -2312,7 +2311,7 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card, struct snd_soc_dapm_path *path; int found = 0; - lockdep_assert_held(&card->dapm_mutex); + snd_soc_dapm_mutex_assert_held(card); /* find dapm widget path assoc with kcontrol */ dapm_kcontrol_for_each_path(path, kcontrol) { @@ -2358,11 +2357,11 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, struct snd_soc_card *card = dapm->card; int ret; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); card->update = update; ret = soc_dapm_mixer_update_power(card, kcontrol, connect, -1); card->update = NULL; - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); if (ret > 0) snd_soc_dpcm_runtime_update(card); return ret; @@ -2441,7 +2440,7 @@ static ssize_t dapm_widget_show(struct device *dev, struct snd_soc_dai *codec_dai; int i, count = 0; - mutex_lock(&rtd->card->dapm_mutex); + snd_soc_dapm_mutex_lock_root(rtd->card); for_each_rtd_codec_dais(rtd, i, codec_dai) { struct snd_soc_component *cmpnt = codec_dai->component; @@ -2449,7 +2448,7 @@ static ssize_t dapm_widget_show(struct device *dev, count = dapm_widget_show_component(cmpnt, buf, count); } - mutex_unlock(&rtd->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(rtd->card); return count; } @@ -2632,9 +2631,9 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) { int ret; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); ret = snd_soc_dapm_sync_unlocked(dapm); - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); @@ -2703,9 +2702,9 @@ int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret; - mutex_lock_nested(&rtd->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(rtd->card); ret = dapm_update_dai_unlocked(substream, params, dai); - mutex_unlock(&rtd->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(rtd->card); return ret; } @@ -3090,14 +3089,14 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, { int i, ret = 0; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); for (i = 0; i < num; i++) { int r = snd_soc_dapm_add_route(dapm, route); if (r < 0) ret = r; route++; } - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } @@ -3116,12 +3115,12 @@ int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm, { int i; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); for (i = 0; i < num; i++) { snd_soc_dapm_del_route(dapm, route); route++; } - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return 0; } @@ -3194,14 +3193,14 @@ int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm, int i; int ret = 0; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); + snd_soc_dapm_mutex_lock_root(dapm); for (i = 0; i < num; i++) { int err = snd_soc_dapm_weak_route(dapm, route); if (err) ret = err; route++; } - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } @@ -3220,7 +3219,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) struct snd_soc_dapm_widget *w; unsigned int val; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); + snd_soc_dapm_mutex_lock_root(card); for_each_card_widgets(card, w) { @@ -3232,7 +3231,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) sizeof(struct snd_kcontrol *), GFP_KERNEL); if (!w->kcontrols) { - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); return -ENOMEM; } } @@ -3275,7 +3274,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) } dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP); - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); return 0; } EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); @@ -3293,7 +3292,6 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); - struct snd_soc_card *card = dapm->card; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; int reg = mc->reg; @@ -3304,7 +3302,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, unsigned int invert = mc->invert; unsigned int reg_val, val, rval = 0; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) { reg_val = soc_dapm_read(dapm, reg); val = (reg_val >> shift) & mask; @@ -3321,7 +3319,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, if (snd_soc_volsw_is_stereo(mc)) rval = (reg_val >> width) & mask; } - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); if (invert) ucontrol->value.integer.value[0] = max - val; @@ -3379,7 +3377,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, rval = max - rval; } - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); /* This assumes field width < (bits in unsigned int / 2) */ if (width > sizeof(unsigned int) * 8 / 2) @@ -3421,7 +3419,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, card->update = NULL; } - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); if (ret > 0) snd_soc_dpcm_runtime_update(card); @@ -3443,17 +3441,16 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); - struct snd_soc_card *card = dapm->card; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int reg_val, val; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); if (e->reg != SND_SOC_NOPM && dapm_kcontrol_is_powered(kcontrol)) { reg_val = soc_dapm_read(dapm, e->reg); } else { reg_val = dapm_kcontrol_get_value(kcontrol); } - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); val = (reg_val >> e->shift_l) & e->mask; ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); @@ -3500,7 +3497,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, mask |= e->mask << e->shift_r; } - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); change = dapm_kcontrol_set_value(kcontrol, val); @@ -3521,7 +3518,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, card->update = NULL; } - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); if (ret > 0) snd_soc_dpcm_runtime_update(card); @@ -3562,12 +3559,12 @@ int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); const char *pin = (const char *)kcontrol->private_value; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); ucontrol->value.integer.value[0] = snd_soc_dapm_get_pin_status(&card->dapm, pin); - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); return 0; } @@ -3586,10 +3583,10 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, const char *pin = (const char *)kcontrol->private_value; int ret; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); ret = __snd_soc_dapm_set_pin(&card->dapm, pin, !!ucontrol->value.integer.value[0]); - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); snd_soc_dapm_sync(&card->dapm); return ret; @@ -3762,9 +3759,9 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, { struct snd_soc_dapm_widget *w; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); w = snd_soc_dapm_new_control_unlocked(dapm, widget); - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return w; } @@ -3787,7 +3784,7 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, int i; int ret = 0; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); + snd_soc_dapm_mutex_lock_root(dapm); for (i = 0; i < num; i++) { struct snd_soc_dapm_widget *w = snd_soc_dapm_new_control_unlocked(dapm, widget); if (IS_ERR(w)) { @@ -3796,7 +3793,7 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, } widget++; } - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); @@ -4499,9 +4496,9 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, { struct snd_soc_card *card = rtd->card; - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(card); soc_dapm_stream_event(rtd, stream, event); - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); } void snd_soc_dapm_stream_stop(struct snd_soc_pcm_runtime *rtd, int stream) @@ -4562,11 +4559,11 @@ int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin) { int ret; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); ret = snd_soc_dapm_set_pin(dapm, pin, 1); - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } @@ -4630,11 +4627,11 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, { int ret; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, pin); - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } @@ -4674,11 +4671,11 @@ int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, { int ret; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); ret = snd_soc_dapm_set_pin(dapm, pin, 0); - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } @@ -4725,11 +4722,11 @@ int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin) { int ret; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + snd_soc_dapm_mutex_lock(dapm); ret = snd_soc_dapm_set_pin(dapm, pin, 0); - mutex_unlock(&dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(dapm); return ret; } @@ -4826,7 +4823,7 @@ static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) LIST_HEAD(down_list); int powerdown = 0; - mutex_lock(&card->dapm_mutex); + snd_soc_dapm_mutex_lock_root(card); for_each_card_widgets(dapm->card, w) { if (w->dapm != dapm) @@ -4851,7 +4848,7 @@ static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) SND_SOC_BIAS_STANDBY); } - mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_mutex_unlock(card); } /* -- cgit From 38e42f6d6c6702bbfc633fce9b579fb80cec2d59 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Apr 2023 00:16:10 +0000 Subject: ASoC: expand snd_soc_dpcm_mutex_lock/unlock() soc-pcm.c has snd_soc_dpcm_mutex_lock/unlock(), but other files can't use it because it is static function. It requests snd_soc_pcm_runtime as parameter (A), but sometimes we want to use it by snd_soc_card (B). (A) static inline void snd_soc_dpcm_mutex_lock(struct snd_soc_pcm_runtime *rtd) { mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); } ^^^^^^^^^ (B) mutex_lock_nested(&card->pcm_mutex, card->pcm_subclass); ^^^^ We want to use it with both "rtd" and "card" for dapm lock/unlock. To enable it, this patch uses _Generic macro. This patch makes snd_soc_dpcm_mutex_{un}lock() global function, and use it on each files. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87bkk1x3ud.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-component.c | 12 ++++++------ sound/soc/soc-compress.c | 42 +++++++++++++++++++++--------------------- sound/soc/soc-core.c | 4 ++-- sound/soc/soc-pcm.c | 17 ++--------------- 4 files changed, 31 insertions(+), 44 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 3cd6952212e1..ff25718ff2e8 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -550,7 +550,7 @@ int snd_soc_component_compr_get_caps(struct snd_compr_stream *cstream, struct snd_soc_component *component; int i, ret = 0; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); for_each_rtd_components(rtd, i, component) { if (component->driver->compress_ops && @@ -561,7 +561,7 @@ int snd_soc_component_compr_get_caps(struct snd_compr_stream *cstream, } } - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return soc_component_ret(component, ret); } @@ -574,7 +574,7 @@ int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream, struct snd_soc_component *component; int i, ret = 0; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); for_each_rtd_components(rtd, i, component) { if (component->driver->compress_ops && @@ -585,7 +585,7 @@ int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream, } } - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return soc_component_ret(component, ret); } @@ -638,7 +638,7 @@ int snd_soc_component_compr_copy(struct snd_compr_stream *cstream, struct snd_soc_component *component; int i, ret = 0; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); for_each_rtd_components(rtd, i, component) { if (component->driver->compress_ops && @@ -649,7 +649,7 @@ int snd_soc_component_compr_copy(struct snd_compr_stream *cstream, } } - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return soc_component_ret(component, ret); } diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 6e74a6c48986..661e9d70994f 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -62,7 +62,7 @@ static int soc_compr_clean(struct snd_compr_stream *cstream, int rollback) struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); if (!rollback) snd_soc_runtime_deactivate(rtd, stream); @@ -84,7 +84,7 @@ static int soc_compr_clean(struct snd_compr_stream *cstream, int rollback) if (!rollback) snd_soc_dapm_stream_stop(rtd, stream); - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); snd_soc_pcm_component_pm_runtime_put(rtd, cstream, rollback); @@ -107,7 +107,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) if (ret < 0) goto err_no_lock; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); ret = snd_soc_dai_compr_startup(cpu_dai, cstream); if (ret < 0) @@ -123,7 +123,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) snd_soc_runtime_activate(rtd, stream); err: - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); err_no_lock: if (ret < 0) soc_compr_clean(cstream, 1); @@ -146,7 +146,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) if (ret < 0) goto be_err; - mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(fe); /* calculate valid and active FE <-> BE dpcms */ dpcm_process_paths(fe, stream, &list, 1); @@ -182,7 +182,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; snd_soc_runtime_activate(fe, stream); - mutex_unlock(&fe->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(fe); mutex_unlock(&fe->card->mutex); @@ -209,7 +209,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); - mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(fe); snd_soc_runtime_deactivate(fe, stream); fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; @@ -229,7 +229,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) dpcm_be_disconnect(fe, stream); - mutex_unlock(&fe->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(fe); snd_soc_link_compr_shutdown(cstream, 0); @@ -249,7 +249,7 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ int ret; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); ret = snd_soc_component_compr_trigger(cstream, cmd); if (ret < 0) @@ -269,7 +269,7 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) } out: - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return ret; } @@ -327,7 +327,7 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ int ret; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); /* * First we call set_params for the CPU DAI, then the component @@ -352,14 +352,14 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, /* cancel any delayed stream shutdown that is pending */ rtd->pop_wait = 0; - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); cancel_delayed_work_sync(&rtd->delayed_work); return 0; err: - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return ret; } @@ -404,9 +404,9 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, ret = snd_soc_link_compr_set_params(cstream); if (ret < 0) goto out; - mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(fe); dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); - mutex_unlock(&fe->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(fe); fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; out: @@ -422,7 +422,7 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret = 0; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params); if (ret < 0) @@ -430,7 +430,7 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, ret = snd_soc_component_compr_get_params(cstream, params); err: - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return ret; } @@ -440,7 +440,7 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes); if (ret < 0) @@ -448,7 +448,7 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) ret = snd_soc_component_compr_ack(cstream, bytes); err: - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return ret; } @@ -459,7 +459,7 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, int ret; struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp); if (ret < 0) @@ -467,7 +467,7 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, ret = snd_soc_component_compr_pointer(cstream, tstamp); out: - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); return ret; } diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 9bbcff492c1e..4594505cdae2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -348,7 +348,7 @@ void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int playback = SNDRV_PCM_STREAM_PLAYBACK; - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + snd_soc_dpcm_mutex_lock(rtd); dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n", @@ -364,7 +364,7 @@ void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd) SND_SOC_DAPM_STREAM_STOP); } - mutex_unlock(&rtd->card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(rtd); } EXPORT_SYMBOL_GPL(snd_soc_close_delayed_work); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 913a7d98e742..adb69d7820a8 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -49,19 +49,6 @@ static inline int _soc_pcm_ret(struct snd_soc_pcm_runtime *rtd, return ret; } -static inline void snd_soc_dpcm_mutex_lock(struct snd_soc_pcm_runtime *rtd) -{ - mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); -} - -static inline void snd_soc_dpcm_mutex_unlock(struct snd_soc_pcm_runtime *rtd) -{ - mutex_unlock(&rtd->card->pcm_mutex); -} - -#define snd_soc_dpcm_mutex_assert_held(rtd) \ - lockdep_assert_held(&(rtd)->card->pcm_mutex) - static inline void snd_soc_dpcm_stream_lock_irq(struct snd_soc_pcm_runtime *rtd, int stream) { @@ -2664,7 +2651,7 @@ int snd_soc_dpcm_runtime_update(struct snd_soc_card *card) struct snd_soc_pcm_runtime *fe; int ret = 0; - mutex_lock_nested(&card->pcm_mutex, card->pcm_subclass); + snd_soc_dpcm_mutex_lock(card); /* shutdown all old paths first */ for_each_card_rtds(card, fe) { ret = soc_dpcm_fe_runtime_update(fe, 0); @@ -2680,7 +2667,7 @@ int snd_soc_dpcm_runtime_update(struct snd_soc_card *card) } out: - mutex_unlock(&card->pcm_mutex); + snd_soc_dpcm_mutex_unlock(card); return ret; } EXPORT_SYMBOL_GPL(snd_soc_dpcm_runtime_update); -- cgit From 0f3b818486796ec8895fa4ccdf15edb759bff40a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Apr 2023 00:16:27 +0000 Subject: ASoC: add snd_soc_card_mutex_lock/unlock() ASoC need to use card->mutex with _INIT or _RUNTIME, but there is no helper function for it. This patch adds its helper function and use it. Because people might misunderstand that _init() is mutex initialization, this patch renames _INIT to _ROOT and adds new snd_soc_card_mutex_lock_root() for it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87a5zlx3tw.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 18 +++++++++--------- sound/soc/soc-core.c | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 661e9d70994f..d8715db5e415 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -140,7 +140,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ int ret; - mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); + snd_soc_card_mutex_lock(fe->card); ret = dpcm_path_get(fe, stream, &list); if (ret < 0) @@ -184,7 +184,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) snd_soc_runtime_activate(fe, stream); snd_soc_dpcm_mutex_unlock(fe); - mutex_unlock(&fe->card->mutex); + snd_soc_card_mutex_unlock(fe->card); return 0; @@ -196,7 +196,7 @@ out: dpcm_path_put(&list); be_err: fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; - mutex_unlock(&fe->card->mutex); + snd_soc_card_mutex_unlock(fe->card); return ret; } @@ -207,7 +207,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) struct snd_soc_dpcm *dpcm; int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ - mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); + snd_soc_card_mutex_lock(fe->card); snd_soc_dpcm_mutex_lock(fe); snd_soc_runtime_deactivate(fe, stream); @@ -237,7 +237,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) snd_soc_dai_compr_shutdown(cpu_dai, cstream, 0); - mutex_unlock(&fe->card->mutex); + snd_soc_card_mutex_unlock(fe->card); return 0; } @@ -284,7 +284,7 @@ static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) cmd == SND_COMPR_TRIGGER_DRAIN) return snd_soc_component_compr_trigger(cstream, cmd); - mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); + snd_soc_card_mutex_lock(fe->card); ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd); if (ret < 0) @@ -315,7 +315,7 @@ static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) out: fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; - mutex_unlock(&fe->card->mutex); + snd_soc_card_mutex_unlock(fe->card); return ret; } @@ -373,7 +373,7 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ int ret; - mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); + snd_soc_card_mutex_lock(fe->card); /* * Create an empty hw_params for the BE as the machine driver must @@ -411,7 +411,7 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, out: fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; - mutex_unlock(&fe->card->mutex); + snd_soc_card_mutex_unlock(fe->card); return ret; } diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4594505cdae2..b48efc3a08d2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1938,7 +1938,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) int ret; mutex_lock(&client_mutex); - mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); + snd_soc_card_mutex_lock_root(card); snd_soc_dapm_init(&card->dapm, card, NULL); @@ -2093,7 +2093,7 @@ probe_end: if (ret < 0) soc_cleanup_card_resources(card); - mutex_unlock(&card->mutex); + snd_soc_card_mutex_unlock(card); mutex_unlock(&client_mutex); return ret; -- cgit From 1c34890273a020d61d6127ade3f68ed1cb21c16a Mon Sep 17 00:00:00 2001 From: Liliang Ye Date: Mon, 3 Apr 2023 23:26:47 +0800 Subject: ASoC: fsl_mqs: move of_node_put() to the correct location of_node_put() should have been done directly after mqs_priv->regmap = syscon_node_to_regmap(gpr_np); otherwise it creates a reference leak on the success path. To fix this, of_node_put() is moved to the correct location, and change all the gotos to direct returns. Fixes: a9d273671440 ("ASoC: fsl_mqs: Fix error handling in probe") Signed-off-by: Liliang Ye Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20230403152647.17638-1-yll@hust.edu.cn Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_mqs.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c index 3fb3d3e4d09a..49ae7f6267d3 100644 --- a/sound/soc/fsl/fsl_mqs.c +++ b/sound/soc/fsl/fsl_mqs.c @@ -210,10 +210,10 @@ static int fsl_mqs_probe(struct platform_device *pdev) } mqs_priv->regmap = syscon_node_to_regmap(gpr_np); + of_node_put(gpr_np); if (IS_ERR(mqs_priv->regmap)) { dev_err(&pdev->dev, "failed to get gpr regmap\n"); - ret = PTR_ERR(mqs_priv->regmap); - goto err_free_gpr_np; + return PTR_ERR(mqs_priv->regmap); } } else { regs = devm_platform_ioremap_resource(pdev, 0); @@ -242,8 +242,7 @@ static int fsl_mqs_probe(struct platform_device *pdev) if (IS_ERR(mqs_priv->mclk)) { dev_err(&pdev->dev, "failed to get the clock: %ld\n", PTR_ERR(mqs_priv->mclk)); - ret = PTR_ERR(mqs_priv->mclk); - goto err_free_gpr_np; + return PTR_ERR(mqs_priv->mclk); } dev_set_drvdata(&pdev->dev, mqs_priv); @@ -252,13 +251,9 @@ static int fsl_mqs_probe(struct platform_device *pdev) ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_fsl_mqs, &fsl_mqs_dai, 1); if (ret) - goto err_free_gpr_np; - return 0; - -err_free_gpr_np: - of_node_put(gpr_np); + return ret; - return ret; + return 0; } static void fsl_mqs_remove(struct platform_device *pdev) -- cgit From 67380533d450000699848e292d20ec18d0321f0e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 17 Apr 2023 16:14:50 +0200 Subject: ASoC: codecs: wcd9335: Simplify with dev_err_probe Code can be a bit simpler with dev_err_probe(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230417141453.919158-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd9335.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index d2548fdf9ae5..8bf3510a3ea3 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -5138,20 +5138,17 @@ static int wcd9335_irq_init(struct wcd9335_codec *wcd) * INTR2 is a subset of first interrupt sources MAD, VBAT, and SVA */ wcd->intr1 = of_irq_get_byname(wcd->dev->of_node, "intr1"); - if (wcd->intr1 < 0) { - if (wcd->intr1 != -EPROBE_DEFER) - dev_err(wcd->dev, "Unable to configure IRQ\n"); - - return wcd->intr1; - } + if (wcd->intr1 < 0) + return dev_err_probe(wcd->dev, wcd->intr1, + "Unable to configure IRQ\n"); ret = devm_regmap_add_irq_chip(wcd->dev, wcd->regmap, wcd->intr1, IRQF_TRIGGER_HIGH, 0, &wcd9335_regmap_irq1_chip, &wcd->irq_data); if (ret) - dev_err(wcd->dev, "Failed to register IRQ chip: %d\n", ret); + return dev_err_probe(wcd->dev, ret, "Failed to register IRQ chip\n"); - return ret; + return 0; } static int wcd9335_slim_probe(struct slim_device *slim) @@ -5207,17 +5204,15 @@ static int wcd9335_slim_status(struct slim_device *sdev, slim_get_logical_addr(wcd->slim_ifc_dev); wcd->regmap = regmap_init_slimbus(sdev, &wcd9335_regmap_config); - if (IS_ERR(wcd->regmap)) { - dev_err(dev, "Failed to allocate slim register map\n"); - return PTR_ERR(wcd->regmap); - } + if (IS_ERR(wcd->regmap)) + return dev_err_probe(dev, PTR_ERR(wcd->regmap), + "Failed to allocate slim register map\n"); wcd->if_regmap = regmap_init_slimbus(wcd->slim_ifc_dev, &wcd9335_ifc_regmap_config); - if (IS_ERR(wcd->if_regmap)) { - dev_err(dev, "Failed to allocate ifc register map\n"); - return PTR_ERR(wcd->if_regmap); - } + if (IS_ERR(wcd->if_regmap)) + return dev_err_probe(dev, PTR_ERR(wcd->if_regmap), + "Failed to allocate ifc register map\n"); ret = wcd9335_bring_up(wcd); if (ret) { -- cgit From 5f3d94eb7ae877430d9fe6a9aae7dcef6c3e5fea Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Tue, 18 Apr 2023 08:09:55 -0400 Subject: ASoC: nau8825: fix bounds check for adc_delay clang build reports sound/soc/codecs/nau8825.c:2826:31: error: overlapping comparisons always evaluate to false [-Werror,-Wtautological-overlap-compare] if (nau8825->adc_delay < 125 && nau8825->adc_delay > 500) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~ This is a bug, a logical-or should have been used. Fixes: fc0b096c9291 ("ASoC: nau8825: Add delay control for input path") Signed-off-by: Tom Rix Acked-by: David Lin Link: https://lore.kernel.org/r/20230418120955.3230705-1-trix@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8825.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index c4389f5fe603..f4eb999761a4 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -2823,7 +2823,7 @@ static int nau8825_read_device_properties(struct device *dev, ret = device_property_read_u32(dev, "nuvoton,adc-delay-ms", &nau8825->adc_delay); if (ret) nau8825->adc_delay = 125; - if (nau8825->adc_delay < 125 && nau8825->adc_delay > 500) + if (nau8825->adc_delay < 125 || nau8825->adc_delay > 500) dev_warn(dev, "Please set the suitable delay time!\n"); nau8825->mclk = devm_clk_get(dev, "mclk"); -- cgit From fa92f4294283cc7d1f29151420be9e9336182518 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 18 Apr 2023 09:46:28 +0200 Subject: ASoC: codecs: wcd934x: Simplify with dev_err_probe Replace dev_err() in probe() path with dev_err_probe() to: 1. Make code a bit simpler and easier to read, 2. Do not print messages on deferred probe. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230418074630.8681-2-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 783479a4d535..56487ad2f048 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -5868,10 +5868,9 @@ static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd) slim_get_logical_addr(wcd->sidev); wcd->if_regmap = regmap_init_slimbus(wcd->sidev, &wcd934x_ifc_regmap_config); - if (IS_ERR(wcd->if_regmap)) { - dev_err(dev, "Failed to allocate ifc register map\n"); - return PTR_ERR(wcd->if_regmap); - } + if (IS_ERR(wcd->if_regmap)) + return dev_err_probe(dev, PTR_ERR(wcd->if_regmap), + "Failed to allocate ifc register map\n"); of_property_read_u32(dev->parent->of_node, "qcom,dmic-sample-rate", &wcd->dmic_sample_rate); @@ -5923,19 +5922,15 @@ static int wcd934x_codec_probe(struct platform_device *pdev) memcpy(wcd->tx_chs, wcd934x_tx_chs, sizeof(wcd934x_tx_chs)); irq = regmap_irq_get_virq(data->irq_data, WCD934X_IRQ_SLIMBUS); - if (irq < 0) { - dev_err(wcd->dev, "Failed to get SLIM IRQ\n"); - return irq; - } + if (irq < 0) + return dev_err_probe(wcd->dev, irq, "Failed to get SLIM IRQ\n"); ret = devm_request_threaded_irq(dev, irq, NULL, wcd934x_slim_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT, "slim", wcd); - if (ret) { - dev_err(dev, "Failed to request slimbus irq\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to request slimbus irq\n"); wcd934x_register_mclk_output(wcd); platform_set_drvdata(pdev, wcd); -- cgit From 92864de45c3e445419d1e99e3a409469a5f3ef57 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 18 Apr 2023 09:46:29 +0200 Subject: ASoC: codecs: wcd934x: Simplify &pdev->dev in probe The probe already stores pointer to &pdev->dev, so use it to make the code a bit easier to read. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230418074630.8681-3-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 56487ad2f048..c0d1fa36d841 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -5892,12 +5892,12 @@ static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd) static int wcd934x_codec_probe(struct platform_device *pdev) { - struct wcd934x_ddata *data = dev_get_drvdata(pdev->dev.parent); - struct wcd934x_codec *wcd; struct device *dev = &pdev->dev; + struct wcd934x_ddata *data = dev_get_drvdata(dev->parent); + struct wcd934x_codec *wcd; int ret, irq; - wcd = devm_kzalloc(&pdev->dev, sizeof(*wcd), GFP_KERNEL); + wcd = devm_kzalloc(dev, sizeof(*wcd), GFP_KERNEL); if (!wcd) return -ENOMEM; -- cgit From 60ba2fda5280528e70fa26b44e36d1530f6d1d7e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 18 Apr 2023 09:46:30 +0200 Subject: ASoC: codecs: wcd938x: Simplify with dev_err_probe Replace dev_err() in probe() path with dev_err_probe() to: 1. Make code a bit simpler and easier to read, 2. Do not print messages on deferred probe. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230418074630.8681-4-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd938x.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index f033f79ed238..11b264a63b04 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -4235,18 +4235,15 @@ static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device int ret; wcd938x->reset_gpio = of_get_named_gpio(dev->of_node, "reset-gpios", 0); - if (wcd938x->reset_gpio < 0) { - dev_err(dev, "Failed to get reset gpio: err = %d\n", - wcd938x->reset_gpio); - return wcd938x->reset_gpio; - } + if (wcd938x->reset_gpio < 0) + return dev_err_probe(dev, wcd938x->reset_gpio, + "Failed to get reset gpio\n"); wcd938x->us_euro_gpio = devm_gpiod_get_optional(dev, "us-euro", GPIOD_OUT_LOW); - if (IS_ERR(wcd938x->us_euro_gpio)) { - dev_err(dev, "us-euro swap Control GPIO not found\n"); - return PTR_ERR(wcd938x->us_euro_gpio); - } + if (IS_ERR(wcd938x->us_euro_gpio)) + return dev_err_probe(dev, PTR_ERR(wcd938x->us_euro_gpio), + "us-euro swap Control GPIO not found\n"); cfg->swap_gnd_mic = wcd938x_swap_gnd_mic; @@ -4256,16 +4253,12 @@ static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device wcd938x->supplies[3].supply = "vdd-mic-bias"; ret = regulator_bulk_get(dev, WCD938X_MAX_SUPPLY, wcd938x->supplies); - if (ret) { - dev_err(dev, "Failed to get supplies: err = %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to get supplies\n"); ret = regulator_bulk_enable(WCD938X_MAX_SUPPLY, wcd938x->supplies); - if (ret) { - dev_err(dev, "Failed to enable supplies: err = %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to enable supplies\n"); wcd938x_dt_parse_micbias_info(dev, wcd938x); -- cgit From 16e5fc8ae793947d7dd0de63c7a613798f75c237 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 18 Apr 2023 15:43:06 +0100 Subject: ASoC: cs35l56: Update comment on masking of EINT20 interrupts EINT20 contains wake-source interrupts and also interface-blocked interrupts, which all default to unmasked after reset or wake. The comment in cs35l56_init() only mentioned the wake interrupts. Update the comment so it's clear that it's intentional to also mask the *_BLOCKED interrupts. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230418144309.1100721-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 0f4a94b02ef8..1b80cae5026e 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -1537,7 +1537,7 @@ int cs35l56_init(struct cs35l56_private *cs35l56) cs35l56_patch(cs35l56->dev, cs35l56->regmap, cs35l56->rev); - /* Wake source interrupts default to unmasked, so mask them */ + /* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */ regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); regmap_update_bits(cs35l56->regmap, CS35L56_IRQ1_MASK_1, CS35L56_AMP_SHORT_ERR_EINT1_MASK, -- cgit From 5ab28c78a125a724684958f4caf8210127d3f528 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 18 Apr 2023 15:43:07 +0100 Subject: ASoC: cs35l56: Remove SDW1 TX5 and TX6 Reduce SDW1 to 4 channels and remove the controls for SDW1 TX5 and TX6. The TX5 and TX6 channels have been removed from B0 silicon. There is no need to support them on A1 silicon. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230418144309.1100721-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-shared.c | 27 --------------------------- sound/soc/codecs/cs35l56.c | 28 +--------------------------- 2 files changed, 1 insertion(+), 54 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index d8bc06ad4888..f5fa6bb04d38 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -28,8 +28,6 @@ static const struct reg_default cs35l56_reg_defaults[] = { { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 }, { CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 }, { CS35L56_SWIRE_DP3_CH4_INPUT, 0x00000028 }, - { CS35L56_SWIRE_DP3_CH5_INPUT, 0x00000018 }, - { CS35L56_SWIRE_DP3_CH6_INPUT, 0x00000018 }, { CS35L56_IRQ1_CFG, 0x00000000 }, { CS35L56_IRQ1_MASK_1, 0x83ffffff }, { CS35L56_IRQ1_MASK_2, 0xffff7fff }, @@ -42,29 +40,6 @@ static const struct reg_default cs35l56_reg_defaults[] = { /* CS35L56_MAIN_POSTURE_NUMBER - soft register, no default */ }; -/* - * The Ax devices have different default register values to that of B0, - * establish a common set of register defaults. - */ -static const struct reg_sequence cs35l56_reva_patch[] = { - { CS35L56_SWIRE_DP3_CH5_INPUT, 0x00000018 }, - { CS35L56_SWIRE_DP3_CH6_INPUT, 0x00000018 }, -}; - -void cs35l56_patch(struct device *dev, struct regmap *regmap, u8 revid) -{ - int ret; - - if (revid >= CS35L56_REVID_B0) - return; - - ret = regmap_register_patch(regmap, cs35l56_reva_patch, - ARRAY_SIZE(cs35l56_reva_patch)); - if (ret) - dev_err(dev, "Failed to apply patch: %d\n", ret); -} -EXPORT_SYMBOL_NS_GPL(cs35l56_patch, SND_SOC_CS35L56_SHARED); - static bool cs35l56_is_dsp_memory(unsigned int reg) { switch (reg) { @@ -114,8 +89,6 @@ static bool cs35l56_readable_reg(struct device *dev, unsigned int reg) case CS35L56_SWIRE_DP3_CH2_INPUT: case CS35L56_SWIRE_DP3_CH3_INPUT: case CS35L56_SWIRE_DP3_CH4_INPUT: - case CS35L56_SWIRE_DP3_CH5_INPUT: - case CS35L56_SWIRE_DP3_CH6_INPUT: case CS35L56_IRQ1_CFG: case CS35L56_IRQ1_STATUS: case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8: diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 1b80cae5026e..c0a857cfb8cb 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -166,24 +166,6 @@ static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx4_enum, static const struct snd_kcontrol_new sdw1_tx4_mux = SOC_DAPM_ENUM("SDW1TX4 SRC", cs35l56_sdw1tx4_enum); -static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx5_enum, - CS35L56_SWIRE_DP3_CH5_INPUT, - 0, CS35L56_SWIRETXn_SRC_MASK, - cs35l56_tx_input_texts, - cs35l56_tx_input_values); - -static const struct snd_kcontrol_new sdw1_tx5_mux = - SOC_DAPM_ENUM("SDW1TX5 SRC", cs35l56_sdw1tx5_enum); - -static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx6_enum, - CS35L56_SWIRE_DP3_CH6_INPUT, - 0, CS35L56_SWIRETXn_SRC_MASK, - cs35l56_tx_input_texts, - cs35l56_tx_input_values); - -static const struct snd_kcontrol_new sdw1_tx6_mux = - SOC_DAPM_ENUM("SDW1TX6 SRC", cs35l56_sdw1tx6_enum); - static int cs35l56_play_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -251,8 +233,6 @@ static const struct snd_soc_dapm_widget cs35l56_dapm_widgets[] = { SND_SOC_DAPM_MUX("SDW1 TX2 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx2_mux), SND_SOC_DAPM_MUX("SDW1 TX3 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx3_mux), SND_SOC_DAPM_MUX("SDW1 TX4 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx4_mux), - SND_SOC_DAPM_MUX("SDW1 TX5 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx5_mux), - SND_SOC_DAPM_MUX("SDW1 TX6 Source", SND_SOC_NOPM, 0, 0, &sdw1_tx6_mux), SND_SOC_DAPM_SIGGEN("VMON ADC"), SND_SOC_DAPM_SIGGEN("IMON ADC"), @@ -318,14 +298,10 @@ static const struct snd_soc_dapm_route cs35l56_audio_map[] = { CS35L56_SRC_ROUTE("SDW1 TX2") CS35L56_SRC_ROUTE("SDW1 TX3") CS35L56_SRC_ROUTE("SDW1 TX4") - CS35L56_SRC_ROUTE("SDW1 TX5") - CS35L56_SRC_ROUTE("SDW1 TX6") { "SDW1 Capture", NULL, "SDW1 TX1 Source" }, { "SDW1 Capture", NULL, "SDW1 TX2 Source" }, { "SDW1 Capture", NULL, "SDW1 TX3 Source" }, { "SDW1 Capture", NULL, "SDW1 TX4 Source" }, - { "SDW1 Capture", NULL, "SDW1 TX5 Source" }, - { "SDW1 Capture", NULL, "SDW1 TX6 Source" }, }; static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, @@ -779,7 +755,7 @@ static struct snd_soc_dai_driver cs35l56_dai[] = { .capture = { .stream_name = "SDW1 Capture", .channels_min = 1, - .channels_max = 6, + .channels_max = 4, .rates = CS35L56_RATES, .formats = CS35L56_TX_FORMATS, }, @@ -1535,8 +1511,6 @@ int cs35l56_init(struct cs35l56_private *cs35l56) dev_info(cs35l56->dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d\n", cs35l56->secured ? "s" : "", cs35l56->rev, otpid); - cs35l56_patch(cs35l56->dev, cs35l56->regmap, cs35l56->rev); - /* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */ regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); regmap_update_bits(cs35l56->regmap, CS35L56_IRQ1_MASK_1, -- cgit From d3a4efb334e5f6cbb3f2741fa07a873a2a78b016 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 18 Apr 2023 15:43:08 +0100 Subject: ASoC: cs35l56: Remove SDW2RX1 mixer source The mixer source index value for SDW2RX1 is different between A1 and B0 silicon. As the driver doesn't provide a DAI for SDW2 just remove it as a mixer source option. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230418144309.1100721-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-shared.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index f5fa6bb04d38..93a1b056660b 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -278,7 +278,7 @@ const char * const cs35l56_tx_input_texts[] = { "None", "ASP1RX1", "ASP1RX2", "VMON", "IMON", "ERRVOL", "CLASSH", "VDDBMON", "VBSTMON", "DSP1TX1", "DSP1TX2", "DSP1TX3", "DSP1TX4", "DSP1TX5", "DSP1TX6", "DSP1TX7", "DSP1TX8", "TEMPMON", - "INTERPOLATOR", "SDW1RX1", "SDW1RX2", "SDW2RX1", + "INTERPOLATOR", "SDW1RX1", "SDW1RX2", }; EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_texts, SND_SOC_CS35L56_SHARED); @@ -304,7 +304,6 @@ const unsigned int cs35l56_tx_input_values[] = { CS35L56_INPUT_SRC_INTERPOLATOR, CS35L56_INPUT_SRC_SWIRE_RX1, CS35L56_INPUT_SRC_SWIRE_RX2, - CS35L56_INPUT_SRC_SWIRE_RX3, }; EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED); -- cgit From d29a966b72fb370128096393961f2c456ff24e3d Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 18 Apr 2023 15:43:09 +0100 Subject: ASoC: cs35l56: Rename mixer source defines for SoundWire DP1 Rename the mixer source defines from CS35L56_INPUT_SRC_SWIRE_RXn to CS35L56_INPUT_SRC_SWIRE_DP1_CHANNELn to match the latest datasheet. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230418144309.1100721-5-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-shared.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index 93a1b056660b..60da8c75b7b9 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -302,8 +302,8 @@ const unsigned int cs35l56_tx_input_values[] = { CS35L56_INPUT_SRC_DSP1TX8, CS35L56_INPUT_SRC_TEMPMON, CS35L56_INPUT_SRC_INTERPOLATOR, - CS35L56_INPUT_SRC_SWIRE_RX1, - CS35L56_INPUT_SRC_SWIRE_RX2, + CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL1, + CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL2, }; EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED); -- cgit From 574399f4c997ad71fab95dd875a9ff55424f9a3d Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 16 Apr 2023 08:29:34 +0200 Subject: ASoC: fsl: Simplify an error message dev_err_probe() already display the error code. There is no need to duplicate it explicitly in the error message. Signed-off-by: Christophe JAILLET Reviewed-by: Iuliana Prodan Acked-by: Shengjiu Wang Link: https://lore.kernel.org/r/c167c16a535049d56f817bbede9c9f6f0a0f4c68.1681626553.git.christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/fsl/fsl-asoc-card.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index bffa1048d31e..40870668ee24 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -858,7 +858,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(&pdev->dev, &priv->card); if (ret) { - dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed: %d\n", ret); + dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n"); goto asrc_fail; } -- cgit From 09cda705860125ffee1b1359b1da79f8e0c77a40 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 19 Apr 2023 18:29:18 +0800 Subject: ASoC: fsl: Restore configuration of platform This reverts commit 33683cbf49b54 ("ASoC: fsl: remove unnecessary dai_link->platform"). dai_link->platform is needed. The platform component is "snd_dmaengine_pcm", which is registered from cpu driver, If dai_link->platform is not assigned, then platform component will not be probed, then there will be issue: aplay: main:831: audio open error: Invalid argument Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1681900158-17428-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmix.c | 14 ++++++++++---- sound/soc/fsl/imx-spdif.c | 5 ++++- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index 2c57fe9d2d08..1292a845c424 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -207,8 +207,8 @@ static int imx_audmix_probe(struct platform_device *pdev) for (i = 0; i < num_dai; i++) { struct snd_soc_dai_link_component *dlc; - /* for CPU/Codec x 2 */ - dlc = devm_kcalloc(&pdev->dev, 4, sizeof(*dlc), GFP_KERNEL); + /* for CPU/Codec/Platform x 2 */ + dlc = devm_kcalloc(&pdev->dev, 6, sizeof(*dlc), GFP_KERNEL); if (!dlc) return -ENOMEM; @@ -240,9 +240,11 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[i].cpus = &dlc[0]; priv->dai[i].codecs = &dlc[1]; + priv->dai[i].platforms = &dlc[2]; priv->dai[i].num_cpus = 1; priv->dai[i].num_codecs = 1; + priv->dai[i].num_platforms = 1; priv->dai[i].name = dai_name; priv->dai[i].stream_name = "HiFi-AUDMIX-FE"; @@ -250,6 +252,7 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[i].codecs->name = "snd-soc-dummy"; priv->dai[i].cpus->of_node = args.np; priv->dai[i].cpus->dai_name = dev_name(&cpu_pdev->dev); + priv->dai[i].platforms->of_node = args.np; priv->dai[i].dynamic = 1; priv->dai[i].dpcm_playback = 1; priv->dai[i].dpcm_capture = (i == 0 ? 1 : 0); @@ -264,17 +267,20 @@ static int imx_audmix_probe(struct platform_device *pdev) be_cp = devm_kasprintf(&pdev->dev, GFP_KERNEL, "AUDMIX-Capture-%d", i); - priv->dai[num_dai + i].cpus = &dlc[2]; - priv->dai[num_dai + i].codecs = &dlc[3]; + priv->dai[num_dai + i].cpus = &dlc[3]; + priv->dai[num_dai + i].codecs = &dlc[4]; + priv->dai[num_dai + i].platforms = &dlc[5]; priv->dai[num_dai + i].num_cpus = 1; priv->dai[num_dai + i].num_codecs = 1; + priv->dai[num_dai + i].num_platforms = 1; priv->dai[num_dai + i].name = be_name; priv->dai[num_dai + i].codecs->dai_name = "snd-soc-dummy-dai"; priv->dai[num_dai + i].codecs->name = "snd-soc-dummy"; priv->dai[num_dai + i].cpus->of_node = audmix_np; priv->dai[num_dai + i].cpus->dai_name = be_name; + priv->dai[num_dai + i].platforms->name = "snd-soc-dummy"; priv->dai[num_dai + i].no_pcm = 1; priv->dai[num_dai + i].dpcm_playback = 1; priv->dai[num_dai + i].dpcm_capture = 1; diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index 114b49660193..4446fba755b9 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c @@ -26,7 +26,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - comp = devm_kzalloc(&pdev->dev, 2 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); if (!data || !comp) { ret = -ENOMEM; goto end; @@ -34,15 +34,18 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) data->dai.cpus = &comp[0]; data->dai.codecs = &comp[1]; + data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; + data->dai.num_platforms = 1; data->dai.name = "S/PDIF PCM"; data->dai.stream_name = "S/PDIF PCM"; data->dai.codecs->dai_name = "snd-soc-dummy-dai"; data->dai.codecs->name = "snd-soc-dummy"; data->dai.cpus->of_node = spdif_np; + data->dai.platforms->of_node = spdif_np; data->dai.playback_only = true; data->dai.capture_only = true; -- cgit From ccb541a00b5bf87f1b7b9301373bf88a3257c688 Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Wed, 19 Apr 2023 14:40:56 -0500 Subject: ASoC: SOF: ipc: Add no reply inline calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 95% of the calls inside SOF to TX an IPC don't care about a reply. Yet the previous commit cleaned up a bunch of replies that were being populated and then thrown away. This adds some functions so users who do not need replies don't feel obligated to provide the space to the API. Signed-off-by: Curtis Malainey Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230419194057.42205-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-client.h | 4 ++++ sound/soc/sof/sof-priv.h | 10 ++++++++++ 2 files changed, 14 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/sof-client.h b/sound/soc/sof/sof-client.h index 2589714eaa91..10571d1ea9a7 100644 --- a/sound/soc/sof/sof-client.h +++ b/sound/soc/sof/sof-client.h @@ -39,6 +39,10 @@ struct sof_client_dev { int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg, void *reply_data, size_t reply_bytes); +static inline int sof_client_ipc_tx_message_no_reply(struct sof_client_dev *cdev, void *ipc_msg) +{ + return sof_client_ipc_tx_message(cdev, ipc_msg, NULL, 0); +} int sof_client_ipc_set_get_data(struct sof_client_dev *cdev, void *ipc_msg, bool set); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 1170989bea57..cd4f6ac126ec 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -711,10 +711,20 @@ static inline void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev) } int sof_ipc_tx_message(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes, void *reply_data, size_t reply_bytes); +static inline int sof_ipc_tx_message_no_reply(struct snd_sof_ipc *ipc, void *msg_data, + size_t msg_bytes) +{ + return sof_ipc_tx_message(ipc, msg_data, msg_bytes, NULL, 0); +} int sof_ipc_set_get_data(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes, bool set); int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes, void *reply_data, size_t reply_bytes); +static inline int sof_ipc_tx_message_no_pm_no_reply(struct snd_sof_ipc *ipc, void *msg_data, + size_t msg_bytes) +{ + return sof_ipc_tx_message_no_pm(ipc, msg_data, msg_bytes, NULL, 0); +} int sof_ipc_send_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_bytes, size_t reply_bytes); -- cgit From 367fd6ffa294ca3346902aa0814fac31bb5a6059 Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Wed, 19 Apr 2023 14:40:57 -0500 Subject: ASoC: SOF: Use no_reply calls for TX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert all existing calls that pass "NULL, 0" for reply data to the new no_reply calls. Also convert any calls that pass in data but don't actually parse the result. Signed-off-by: Curtis Malainey Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20230419194057.42205-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/compress.c | 8 ++------ sound/soc/sof/intel/hda-loader.c | 2 +- sound/soc/sof/ipc3-dtrace.c | 12 ++++------- sound/soc/sof/ipc3-pcm.c | 6 ++---- sound/soc/sof/ipc3-topology.c | 33 ++++++++++--------------------- sound/soc/sof/ipc3.c | 12 +++-------- sound/soc/sof/ipc4-pcm.c | 6 +++--- sound/soc/sof/ipc4-topology.c | 10 +++++----- sound/soc/sof/sof-client-ipc-flood-test.c | 3 +-- sound/soc/sof/sof-client-probes-ipc3.c | 12 ++++------- sound/soc/sof/sof-client-probes-ipc4.c | 4 ++-- 11 files changed, 37 insertions(+), 71 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c index 8d205eb16d2f..d7b044f33d79 100644 --- a/sound/soc/sof/compress.c +++ b/sound/soc/sof/compress.c @@ -135,7 +135,6 @@ static int sof_compr_free(struct snd_soc_component *component, struct sof_compr_stream *sstream = cstream->runtime->private_data; struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct sof_ipc_stream stream; - struct sof_ipc_reply reply; struct snd_sof_pcm *spcm; int ret = 0; @@ -148,8 +147,7 @@ static int sof_compr_free(struct snd_soc_component *component, stream.comp_id = spcm->stream[cstream->direction].comp_id; if (spcm->prepared[cstream->direction]) { - ret = sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), - &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream)); if (!ret) spcm->prepared[cstream->direction] = false; } @@ -273,7 +271,6 @@ static int sof_compr_trigger(struct snd_soc_component *component, struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct sof_ipc_stream stream; - struct sof_ipc_reply reply; struct snd_sof_pcm *spcm; spcm = snd_sof_find_spcm_dai(component, rtd); @@ -302,8 +299,7 @@ static int sof_compr_trigger(struct snd_soc_component *component, break; } - return sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), - &reply, sizeof(reply)); + return sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream)); } static int sof_compr_copy_playback(struct snd_compr_runtime *rtd, diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index de8d9ad89bc7..50ce6b190002 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -557,7 +557,7 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev, goto cleanup; } - ret = sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); ret1 = cl_trigger(sdev, hext_stream, SNDRV_PCM_TRIGGER_STOP); if (ret1 < 0) { diff --git a/sound/soc/sof/ipc3-dtrace.c b/sound/soc/sof/ipc3-dtrace.c index b815b0244d9e..1d3bca2d28dd 100644 --- a/sound/soc/sof/ipc3-dtrace.c +++ b/sound/soc/sof/ipc3-dtrace.c @@ -150,7 +150,6 @@ static int ipc3_trace_update_filter(struct snd_sof_dev *sdev, int num_elems, struct sof_ipc_trace_filter_elem *elems) { struct sof_ipc_trace_filter *msg; - struct sof_ipc_reply reply; size_t size; int ret; @@ -172,13 +171,13 @@ static int ipc3_trace_update_filter(struct snd_sof_dev *sdev, int num_elems, dev_err(sdev->dev, "enabling device failed: %d\n", ret); goto error; } - ret = sof_ipc_tx_message(sdev->ipc, msg, msg->hdr.size, &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, msg, msg->hdr.size); pm_runtime_mark_last_busy(sdev->dev); pm_runtime_put_autosuspend(sdev->dev); error: kfree(msg); - return ret ? ret : reply.error; + return ret; } static ssize_t dfsentry_trace_filter_write(struct file *file, const char __user *from, @@ -434,7 +433,6 @@ static int ipc3_dtrace_enable(struct snd_sof_dev *sdev) struct sof_ipc_fw_ready *ready = &sdev->fw_ready; struct sof_ipc_fw_version *v = &ready->version; struct sof_ipc_dma_trace_params_ext params; - struct sof_ipc_reply ipc_reply; int ret; if (!sdev->fw_trace_is_supported) @@ -474,7 +472,7 @@ static int ipc3_dtrace_enable(struct snd_sof_dev *sdev) /* send IPC to the DSP */ priv->dtrace_state = SOF_DTRACE_INITIALIZING; - ret = sof_ipc_tx_message(sdev->ipc, ¶ms, sizeof(params), &ipc_reply, sizeof(ipc_reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, ¶ms, sizeof(params)); if (ret < 0) { dev_err(sdev->dev, "can't set params for DMA for trace %d\n", ret); goto trace_release; @@ -604,7 +602,6 @@ static void ipc3_dtrace_release(struct snd_sof_dev *sdev, bool only_stop) struct sof_ipc_fw_ready *ready = &sdev->fw_ready; struct sof_ipc_fw_version *v = &ready->version; struct sof_ipc_cmd_hdr hdr; - struct sof_ipc_reply ipc_reply; int ret; if (!sdev->fw_trace_is_supported || priv->dtrace_state == SOF_DTRACE_DISABLED) @@ -623,8 +620,7 @@ static void ipc3_dtrace_release(struct snd_sof_dev *sdev, bool only_stop) hdr.size = sizeof(hdr); hdr.cmd = SOF_IPC_GLB_TRACE_MSG | SOF_IPC_TRACE_DMA_FREE; - ret = sof_ipc_tx_message(sdev->ipc, &hdr, hdr.size, - &ipc_reply, sizeof(ipc_reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &hdr, hdr.size); if (ret < 0) dev_err(sdev->dev, "DMA_TRACE_FREE failed with error: %d\n", ret); } diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c index b7f1eb21ca26..304faf6425ab 100644 --- a/sound/soc/sof/ipc3-pcm.c +++ b/sound/soc/sof/ipc3-pcm.c @@ -19,7 +19,6 @@ static int sof_ipc3_pcm_hw_free(struct snd_soc_component *component, struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sof_ipc_stream stream; - struct sof_ipc_reply reply; struct snd_sof_pcm *spcm; spcm = snd_sof_find_spcm_dai(component, rtd); @@ -34,7 +33,7 @@ static int sof_ipc3_pcm_hw_free(struct snd_soc_component *component, stream.comp_id = spcm->stream[substream->stream].comp_id; /* send IPC to the DSP */ - return sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), &reply, sizeof(reply)); + return sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream)); } static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component, @@ -146,7 +145,6 @@ static int sof_ipc3_pcm_trigger(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct sof_ipc_stream stream; - struct sof_ipc_reply reply; struct snd_sof_pcm *spcm; spcm = snd_sof_find_spcm_dai(component, rtd); @@ -178,7 +176,7 @@ static int sof_ipc3_pcm_trigger(struct snd_soc_component *component, } /* send IPC to the DSP */ - return sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), &reply, sizeof(reply)); + return sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream)); } static void ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const char *link_name, diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index b1f425b39db9..fc1eb8e2de2c 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -1627,7 +1627,6 @@ static void sof_ipc3_widget_free_comp_dai(struct snd_sof_widget *swidget) static int sof_ipc3_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *sroute) { struct sof_ipc_pipe_comp_connect connect; - struct sof_ipc_reply reply; int ret; connect.hdr.size = sizeof(connect); @@ -1640,7 +1639,7 @@ static int sof_ipc3_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * sroute->sink_widget->widget->name); /* send ipc */ - ret = sof_ipc_tx_message(sdev->ipc, &connect, sizeof(connect), &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &connect, sizeof(connect)); if (ret < 0) dev_err(sdev->dev, "%s: route %s -> %s failed\n", __func__, sroute->src_widget->widget->name, sroute->sink_widget->widget->name); @@ -1789,7 +1788,7 @@ static int sof_ipc3_control_free(struct snd_sof_dev *sdev, struct snd_sof_contro fcomp.id = scontrol->comp_id; /* send IPC to the DSP */ - return sof_ipc_tx_message(sdev->ipc, &fcomp, sizeof(fcomp), NULL, 0); + return sof_ipc_tx_message_no_reply(sdev->ipc, &fcomp, sizeof(fcomp)); } /* send pcm params ipc */ @@ -1797,7 +1796,6 @@ static int sof_ipc3_keyword_detect_pcm_params(struct snd_sof_widget *swidget, in { struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - struct sof_ipc_pcm_params_reply ipc_params_reply; struct snd_pcm_hw_params *params; struct sof_ipc_pcm_params pcm; struct snd_sof_pcm *spcm; @@ -1841,8 +1839,7 @@ static int sof_ipc3_keyword_detect_pcm_params(struct snd_sof_widget *swidget, in } /* send IPC to the DSP */ - ret = sof_ipc_tx_message(sdev->ipc, &pcm, sizeof(pcm), - &ipc_params_reply, sizeof(ipc_params_reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &pcm, sizeof(pcm)); if (ret < 0) dev_err(scomp->dev, "%s: PCM params failed for %s\n", __func__, swidget->widget->name); @@ -1856,7 +1853,6 @@ static int sof_ipc3_keyword_detect_trigger(struct snd_sof_widget *swidget, int c struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc_stream stream; - struct sof_ipc_reply reply; int ret; /* set IPC stream params */ @@ -1865,7 +1861,7 @@ static int sof_ipc3_keyword_detect_trigger(struct snd_sof_widget *swidget, int c stream.comp_id = swidget->comp_id; /* send IPC to the DSP */ - ret = sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream)); if (ret < 0) dev_err(scomp->dev, "%s: Failed to trigger %s\n", __func__, swidget->widget->name); @@ -1982,7 +1978,6 @@ static int sof_ipc3_widget_bind_event(struct snd_soc_component *scomp, static int sof_ipc3_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { struct sof_ipc_pipe_ready ready; - struct sof_ipc_reply reply; int ret; dev_dbg(sdev->dev, "tplg: complete pipeline %s id %d\n", @@ -1993,7 +1988,7 @@ static int sof_ipc3_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_w ready.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_COMPLETE; ready.comp_id = swidget->comp_id; - ret = sof_ipc_tx_message(sdev->ipc, &ready, sizeof(ready), &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &ready, sizeof(ready)); if (ret < 0) return ret; @@ -2009,7 +2004,6 @@ static int sof_ipc3_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget }, .id = swidget->comp_id, }; - struct sof_ipc_reply reply; int ret; if (!swidget->private) @@ -2029,8 +2023,7 @@ static int sof_ipc3_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget break; } - ret = sof_ipc_tx_message(sdev->ipc, &ipc_free, sizeof(ipc_free), - &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &ipc_free, sizeof(ipc_free)); if (ret < 0) dev_err(sdev->dev, "failed to free widget %s\n", swidget->widget->name); @@ -2044,7 +2037,6 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * struct snd_sof_dai *dai = swidget->private; struct sof_dai_private_data *private; struct sof_ipc_dai_config *config; - struct sof_ipc_reply reply; int ret = 0; if (!dai || !dai->private) { @@ -2118,8 +2110,7 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * /* only send the IPC if the widget is set up in the DSP */ if (swidget->use_count > 0) { - ret = sof_ipc_tx_message(sdev->ipc, config, config->hdr.size, - &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, config, config->hdr.size); if (ret < 0) dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name); @@ -2132,7 +2123,6 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { - struct sof_ipc_comp_reply reply; int ret; if (!swidget->private) @@ -2146,8 +2136,7 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget struct sof_dai_private_data *dai_data = dai->private; struct sof_ipc_comp *comp = &dai_data->comp_dai->comp; - ret = sof_ipc_tx_message(sdev->ipc, dai_data->comp_dai, - comp->hdr.size, &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, dai_data->comp_dai, comp->hdr.size); break; } case snd_soc_dapm_scheduler: @@ -2155,8 +2144,7 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget struct sof_ipc_pipe_new *pipeline; pipeline = swidget->private; - ret = sof_ipc_tx_message(sdev->ipc, pipeline, sizeof(*pipeline), - &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, pipeline, sizeof(*pipeline)); break; } default: @@ -2164,8 +2152,7 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget struct sof_ipc_cmd_hdr *hdr; hdr = swidget->private; - ret = sof_ipc_tx_message(sdev->ipc, swidget->private, hdr->size, - &reply, sizeof(reply)); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, swidget->private, hdr->size); break; } } diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c index 4493bbd7faf1..c67767742093 100644 --- a/sound/soc/sof/ipc3.c +++ b/sound/soc/sof/ipc3.c @@ -1044,15 +1044,13 @@ static int sof_ipc3_set_core_state(struct snd_sof_dev *sdev, int core_idx, bool .hdr.size = sizeof(core_cfg), .hdr.cmd = SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CORE_ENABLE, }; - struct sof_ipc_reply reply; if (on) core_cfg.enable_mask = sdev->enabled_cores_mask | BIT(core_idx); else core_cfg.enable_mask = sdev->enabled_cores_mask & ~BIT(core_idx); - return sof_ipc3_tx_msg(sdev, &core_cfg, sizeof(core_cfg), - &reply, sizeof(reply), false); + return sof_ipc3_tx_msg(sdev, &core_cfg, sizeof(core_cfg), NULL, 0, false); } static int sof_ipc3_ctx_ipc(struct snd_sof_dev *sdev, int cmd) @@ -1061,11 +1059,9 @@ static int sof_ipc3_ctx_ipc(struct snd_sof_dev *sdev, int cmd) .hdr.size = sizeof(pm_ctx), .hdr.cmd = SOF_IPC_GLB_PM_MSG | cmd, }; - struct sof_ipc_reply reply; /* send ctx save ipc to dsp */ - return sof_ipc3_tx_msg(sdev, &pm_ctx, sizeof(pm_ctx), - &reply, sizeof(reply), false); + return sof_ipc3_tx_msg(sdev, &pm_ctx, sizeof(pm_ctx), NULL, 0, false); } static int sof_ipc3_ctx_save(struct snd_sof_dev *sdev) @@ -1081,7 +1077,6 @@ static int sof_ipc3_ctx_restore(struct snd_sof_dev *sdev) static int sof_ipc3_set_pm_gate(struct snd_sof_dev *sdev, u32 flags) { struct sof_ipc_pm_gate pm_gate; - struct sof_ipc_reply reply; memset(&pm_gate, 0, sizeof(pm_gate)); @@ -1091,8 +1086,7 @@ static int sof_ipc3_set_pm_gate(struct snd_sof_dev *sdev, u32 flags) pm_gate.flags = flags; /* send pm_gate ipc to dsp */ - return sof_ipc_tx_message_no_pm(sdev->ipc, &pm_gate, sizeof(pm_gate), - &reply, sizeof(reply)); + return sof_ipc_tx_message_no_pm_no_reply(sdev->ipc, &pm_gate, sizeof(pm_gate)); } static const struct sof_ipc_pm_ops ipc3_pm_ops = { diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index a2cd21256e44..6a4c91ea47ed 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -39,7 +39,7 @@ static int sof_ipc4_set_multi_pipeline_state(struct snd_sof_dev *sdev, u32 state msg.data_size = ipc_size; msg.data_ptr = trigger_list; - return sof_ipc_tx_message(sdev->ipc, &msg, ipc_size, NULL, 0); + return sof_ipc_tx_message_no_reply(sdev->ipc, &msg, ipc_size); } int sof_ipc4_set_pipeline_state(struct snd_sof_dev *sdev, u32 id, u32 state) @@ -57,7 +57,7 @@ int sof_ipc4_set_pipeline_state(struct snd_sof_dev *sdev, u32 id, u32 state) msg.primary = primary; - return sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); + return sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); } EXPORT_SYMBOL(sof_ipc4_set_pipeline_state); @@ -272,7 +272,7 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev, if (enable) msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_ENABLE_MASK; - return sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); + return sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); } static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index d2d41c53260c..a010e7c38817 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -2118,7 +2118,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget msg->data_size = ipc_size; msg->data_ptr = ipc_data; - ret = sof_ipc_tx_message(sdev->ipc, msg, ipc_size, NULL, 0); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, msg, ipc_size); if (ret < 0) { dev_err(sdev->dev, "failed to create module %s\n", swidget->widget->name); @@ -2162,7 +2162,7 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget msg.primary = header; - ret = sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); if (ret < 0) dev_err(sdev->dev, "failed to free pipeline widget %s\n", swidget->widget->name); @@ -2320,7 +2320,7 @@ static int sof_ipc4_set_copier_sink_format(struct snd_sof_dev *sdev, msg.primary = header; msg.extension = extension; - return sof_ipc_tx_message(sdev->ipc, &msg, msg.data_size, NULL, 0); + return sof_ipc_tx_message_no_reply(sdev->ipc, &msg, msg.data_size); } static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *sroute) @@ -2403,7 +2403,7 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * msg.primary = header; msg.extension = extension; - ret = sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); if (ret < 0) { dev_err(sdev->dev, "failed to bind modules %s:%d -> %s:%d\n", src_widget->widget->name, sroute->src_queue_id, @@ -2462,7 +2462,7 @@ static int sof_ipc4_route_free(struct snd_sof_dev *sdev, struct snd_sof_route *s msg.primary = header; msg.extension = extension; - ret = sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); if (ret < 0) dev_err(sdev->dev, "failed to unbind modules %s:%d -> %s:%d\n", src_widget->widget->name, sroute->src_queue_id, diff --git a/sound/soc/sof/sof-client-ipc-flood-test.c b/sound/soc/sof/sof-client-ipc-flood-test.c index 4bdecd80248a..c0d6723aed59 100644 --- a/sound/soc/sof/sof-client-ipc-flood-test.c +++ b/sound/soc/sof/sof-client-ipc-flood-test.c @@ -64,7 +64,6 @@ static int sof_debug_ipc_flood_test(struct sof_client_dev *cdev, struct sof_ipc_flood_priv *priv = cdev->data; struct device *dev = &cdev->auxdev.dev; struct sof_ipc_cmd_hdr hdr; - struct sof_ipc_reply reply; u64 min_response_time = U64_MAX; ktime_t start, end, test_end; u64 avg_response_time = 0; @@ -84,7 +83,7 @@ static int sof_debug_ipc_flood_test(struct sof_client_dev *cdev, /* send test IPC's */ while (1) { start = ktime_get(); - ret = sof_client_ipc_tx_message(cdev, &hdr, &reply, sizeof(reply)); + ret = sof_client_ipc_tx_message_no_reply(cdev, &hdr); end = ktime_get(); if (ret < 0) diff --git a/sound/soc/sof/sof-client-probes-ipc3.c b/sound/soc/sof/sof-client-probes-ipc3.c index ef768db5f04d..5e8eb19582a8 100644 --- a/sound/soc/sof/sof-client-probes-ipc3.c +++ b/sound/soc/sof/sof-client-probes-ipc3.c @@ -65,7 +65,6 @@ static int ipc3_probes_init(struct sof_client_dev *cdev, u32 stream_tag, { struct sof_ipc_probe_dma_add_params *msg; size_t size = struct_size(msg, dma, 1); - struct sof_ipc_reply reply; int ret; msg = kmalloc(size, GFP_KERNEL); @@ -77,7 +76,7 @@ static int ipc3_probes_init(struct sof_client_dev *cdev, u32 stream_tag, msg->dma[0].stream_tag = stream_tag; msg->dma[0].dma_buffer_size = buffer_size; - ret = sof_client_ipc_tx_message(cdev, msg, &reply, sizeof(reply)); + ret = sof_client_ipc_tx_message_no_reply(cdev, msg); kfree(msg); return ret; } @@ -93,12 +92,11 @@ static int ipc3_probes_init(struct sof_client_dev *cdev, u32 stream_tag, static int ipc3_probes_deinit(struct sof_client_dev *cdev) { struct sof_ipc_cmd_hdr msg; - struct sof_ipc_reply reply; msg.size = sizeof(msg); msg.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_DEINIT; - return sof_client_ipc_tx_message(cdev, &msg, &reply, sizeof(reply)); + return sof_client_ipc_tx_message_no_reply(cdev, &msg); } static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd, @@ -180,7 +178,6 @@ static int ipc3_probes_points_add(struct sof_client_dev *cdev, { struct sof_ipc_probe_point_add_params *msg; size_t size = struct_size(msg, desc, num_desc); - struct sof_ipc_reply reply; int ret; msg = kmalloc(size, GFP_KERNEL); @@ -191,7 +188,7 @@ static int ipc3_probes_points_add(struct sof_client_dev *cdev, msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_POINT_ADD; memcpy(&msg->desc[0], desc, size - sizeof(*msg)); - ret = sof_client_ipc_tx_message(cdev, msg, &reply, sizeof(reply)); + ret = sof_client_ipc_tx_message_no_reply(cdev, msg); kfree(msg); return ret; } @@ -211,7 +208,6 @@ static int ipc3_probes_points_remove(struct sof_client_dev *cdev, { struct sof_ipc_probe_point_remove_params *msg; size_t size = struct_size(msg, buffer_id, num_buffer_id); - struct sof_ipc_reply reply; int ret; msg = kmalloc(size, GFP_KERNEL); @@ -222,7 +218,7 @@ static int ipc3_probes_points_remove(struct sof_client_dev *cdev, msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_POINT_REMOVE; memcpy(&msg->buffer_id[0], buffer_id, size - sizeof(*msg)); - ret = sof_client_ipc_tx_message(cdev, msg, &reply, sizeof(reply)); + ret = sof_client_ipc_tx_message_no_reply(cdev, msg); kfree(msg); return ret; } diff --git a/sound/soc/sof/sof-client-probes-ipc4.c b/sound/soc/sof/sof-client-probes-ipc4.c index 66fa7c2f390a..ea21ef176c42 100644 --- a/sound/soc/sof/sof-client-probes-ipc4.c +++ b/sound/soc/sof/sof-client-probes-ipc4.c @@ -129,7 +129,7 @@ static int ipc4_probes_init(struct sof_client_dev *cdev, u32 stream_tag, msg.data_size = sizeof(cfg); msg.data_ptr = &cfg; - return sof_client_ipc_tx_message(cdev, &msg, NULL, 0); + return sof_client_ipc_tx_message_no_reply(cdev, &msg); } /** @@ -156,7 +156,7 @@ static int ipc4_probes_deinit(struct sof_client_dev *cdev) msg.data_size = 0; msg.data_ptr = NULL; - return sof_client_ipc_tx_message(cdev, &msg, NULL, 0); + return sof_client_ipc_tx_message_no_reply(cdev, &msg); } /** -- cgit From 058924644f9596b8c55fc81f01f741d628eed940 Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Wed, 19 Apr 2023 14:55:18 -0500 Subject: ASoC: Intel: sof_cirrus_common: Guard against missing buses Even if we find a acpi device we can still be missing the physical node. Signed-off-by: Curtis Malainey Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20230419195524.46995-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_cirrus_common.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_cirrus_common.c b/sound/soc/intel/boards/sof_cirrus_common.c index 851c516c8f5b..8b8b07e4f2fe 100644 --- a/sound/soc/intel/boards/sof_cirrus_common.c +++ b/sound/soc/intel/boards/sof_cirrus_common.c @@ -168,11 +168,16 @@ static int cs35l41_compute_codec_conf(void) continue; } physdev = get_device(acpi_get_first_physical_node(adev)); + acpi_dev_put(adev); + if (!physdev) { + pr_devel("Cannot find physical node for HID %s UID %u (%s)\n", CS35L41_HID, + uid, cs35l41_name_prefixes[uid]); + return 0; + } cs35l41_components[sz].name = dev_name(physdev); cs35l41_components[sz].dai_name = CS35L41_CODEC_DAI; cs35l41_codec_conf[sz].dlc.name = dev_name(physdev); cs35l41_codec_conf[sz].name_prefix = cs35l41_name_prefixes[uid]; - acpi_dev_put(adev); sz++; } -- cgit From f5460a155ecb961463f6ff766c7d3092f07e6642 Mon Sep 17 00:00:00 2001 From: apoorv Date: Wed, 19 Apr 2023 14:55:19 -0500 Subject: ASoC: Intel: soc-acpi: Add entry for rt711-sdca-sdw at link 2 in RPL match table RT711 sdca sdw is added with SDW2 link for RPL-P CRB platform. Signed-off-by: apoorv Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20230419195524.46995-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-rpl-match.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c index 13cbd8e9d41f..749d371a86ae 100644 --- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c @@ -284,6 +284,15 @@ static const struct snd_soc_acpi_link_adr rpl_sdw_rt1316_link12_rt714_link0[] = {} }; +static const struct snd_soc_acpi_link_adr rplp_crb[] = { + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt711_sdca_2_adr), + .adr_d = rt711_sdca_2_adr, + }, + {} +}; + static const struct snd_soc_acpi_codecs rpl_rt5682_hp = { .num_codecs = 2, .codecs = {"10EC5682", "RTL5682"}, @@ -348,7 +357,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_sdw_machines[] = { .link_mask = 0x1, /* link0 required */ .links = rpl_rvp, .drv_name = "sof_sdw", - .sof_tplg_filename = "sof-rpl-rt711.tplg", + .sof_tplg_filename = "sof-rpl-rt711-l0.tplg", + }, + { + .link_mask = 0x4, /* link2 required */ + .links = rplp_crb, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-rpl-rt711-l2.tplg", }, {}, }; -- cgit From 06b830bd73ec66b9316b899ae37b1d5b83d16a32 Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Wed, 19 Apr 2023 14:55:20 -0500 Subject: ASoC: Intel: sof_sdw: remove late_probe flag in struct sof_sdw_codec_info Just use codec_card_late_probe ptr in struct sof_sdw_codec_info for validation check and drop late_probe variable. Signed-off-by: Yong Zhi Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20230419195524.46995-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 11 +++++------ sound/soc/intel/boards/sof_sdw_common.h | 1 - sound/soc/intel/boards/sof_sdw_max98373.c | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 6897705a193c..7d398b45d48f 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -621,7 +621,6 @@ static struct sof_sdw_codec_info codec_info_list[] = { .direction = {true, true}, .dai_name = "max98373-aif1", .init = sof_sdw_mx8373_init, - .codec_card_late_probe = sof_sdw_mx8373_late_probe, .codec_type = SOF_SDW_CODEC_TYPE_AMP, }, { @@ -1490,12 +1489,12 @@ static int sof_sdw_card_late_probe(struct snd_soc_card *card) int i; for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { - if (!codec_info_list[i].late_probe) - continue; + if (codec_info_list[i].codec_card_late_probe) { + ret = codec_info_list[i].codec_card_late_probe(card); - ret = codec_info_list[i].codec_card_late_probe(card); - if (ret < 0) - return ret; + if (ret < 0) + return ret; + } } if (ctx->idisp_codec) diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 350010b0e5f4..4962dc11a088 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -74,7 +74,6 @@ struct sof_sdw_codec_info { bool playback); int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); - bool late_probe; int (*codec_card_late_probe)(struct snd_soc_card *card); }; diff --git a/sound/soc/intel/boards/sof_sdw_max98373.c b/sound/soc/intel/boards/sof_sdw_max98373.c index 77a3f32db11e..22bd1e356e22 100644 --- a/sound/soc/intel/boards/sof_sdw_max98373.c +++ b/sound/soc/intel/boards/sof_sdw_max98373.c @@ -130,7 +130,7 @@ int sof_sdw_mx8373_init(struct snd_soc_card *card, if (info->amp_num == 2) dai_links->init = spk_init; - info->late_probe = true; + info->codec_card_late_probe = sof_sdw_mx8373_late_probe; dai_links->ops = &max_98373_sdw_ops; -- cgit From e9fcbaff5fb871f1a10f09d7d1a4cd13c923e280 Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Wed, 19 Apr 2023 14:55:21 -0500 Subject: ASoC: Intel: sof_sdw_max98373: change sof_sdw_mx8373_late_probe to static call sof_sdw_mx8373_late_probe is only used in sof_sdw_max98373, so it should be static and rename it to 'mx8373_sdw_late_probe'. Signed-off-by: Yong Zhi Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20230419195524.46995-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw_common.h | 2 -- sound/soc/intel/boards/sof_sdw_max98373.c | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 13 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 4962dc11a088..081ab7eac5b6 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -158,8 +158,6 @@ int sof_sdw_mx8373_init(struct snd_soc_card *card, struct sof_sdw_codec_info *info, bool playback); -int sof_sdw_mx8373_late_probe(struct snd_soc_card *card); - /* RT5682 support */ int sof_sdw_rt5682_init(struct snd_soc_card *card, const struct snd_soc_acpi_link_adr *link, diff --git a/sound/soc/intel/boards/sof_sdw_max98373.c b/sound/soc/intel/boards/sof_sdw_max98373.c index 22bd1e356e22..3d7df58c0f1d 100644 --- a/sound/soc/intel/boards/sof_sdw_max98373.c +++ b/sound/soc/intel/boards/sof_sdw_max98373.c @@ -120,6 +120,16 @@ static const struct snd_soc_ops max_98373_sdw_ops = { .shutdown = sdw_shutdown, }; +static int mx8373_sdw_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_dapm_context *dapm = &card->dapm; + + /* Disable Left and Right Spk pin after boot */ + snd_soc_dapm_disable_pin(dapm, "Left Spk"); + snd_soc_dapm_disable_pin(dapm, "Right Spk"); + return snd_soc_dapm_sync(dapm); +} + int sof_sdw_mx8373_init(struct snd_soc_card *card, const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, @@ -130,19 +140,9 @@ int sof_sdw_mx8373_init(struct snd_soc_card *card, if (info->amp_num == 2) dai_links->init = spk_init; - info->codec_card_late_probe = sof_sdw_mx8373_late_probe; + info->codec_card_late_probe = mx8373_sdw_late_probe; dai_links->ops = &max_98373_sdw_ops; return 0; } - -int sof_sdw_mx8373_late_probe(struct snd_soc_card *card) -{ - struct snd_soc_dapm_context *dapm = &card->dapm; - - /* Disable Left and Right Spk pin after boot */ - snd_soc_dapm_disable_pin(dapm, "Left Spk"); - snd_soc_dapm_disable_pin(dapm, "Right Spk"); - return snd_soc_dapm_sync(dapm); -} -- cgit From 16373f30777f45823fa68e850b230fa2ef9d7e92 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 19 Apr 2023 14:55:22 -0500 Subject: ASoC: Intel: sof_sdw: set codec_num = 1 if the device is not aggregated We assume adr_link->num_adr = 1 if a device is not aggregated. However, the assumption is not valid if there are different type devices on the same soundwire link. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230419195524.46995-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 7d398b45d48f..e5729df4fd44 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -961,6 +961,7 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, cpu_dai_id[index++] = ffs(adr_link->mask) - 1; if (!adr_d->endpoints->aggregated || no_aggregation) { *cpu_dai_num = 1; + *codec_num = 1; *group_id = 0; return 0; } -- cgit From c8db7b50128b8cc61a5ca6e4717cf8158fca302a Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 19 Apr 2023 14:55:23 -0500 Subject: ASoC: Intel: sof_sdw: support different devices on the same sdw link The existing code assumes all devices on the same soundwire link are the same devices. eg. all rt1316. This commit removes the assumption and supports different devices on the same soundwire link. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230419195524.46995-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 130 +++++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 53 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index e5729df4fd44..6a6c81df72bd 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -732,34 +732,36 @@ static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_li int stream; u64 adr; - adr = link->adr_d->adr; - codec_index = find_codec_info_part(adr); - if (codec_index < 0) - return codec_index; + for (i = 0; i < link->num_adr; i++) { + adr = link->adr_d[i].adr; + codec_index = find_codec_info_part(adr); + if (codec_index < 0) + return codec_index; - if (codec_info_list[codec_index].codec_type < _codec_type) - dev_warn(dev, - "Unexpected address table ordering. Expected order: jack -> amp -> mic\n"); + if (codec_info_list[codec_index].codec_type < _codec_type) + dev_warn(dev, + "Unexpected address table ordering. Expected order: jack -> amp -> mic\n"); - _codec_type = codec_info_list[codec_index].codec_type; + _codec_type = codec_info_list[codec_index].codec_type; - endpoint = link->adr_d->endpoints; + endpoint = link->adr_d[i].endpoints; - /* count DAI number for playback and capture */ - for_each_pcm_streams(stream) { - if (!codec_info_list[codec_index].direction[stream]) - continue; + /* count DAI number for playback and capture */ + for_each_pcm_streams(stream) { + if (!codec_info_list[codec_index].direction[stream]) + continue; - (*sdw_cpu_dai_num)++; + (*sdw_cpu_dai_num)++; - /* count BE for each non-aggregated slave or group */ - if (!endpoint->aggregated || no_aggregation || - !group_visited[endpoint->group_id]) - (*sdw_be_num)++; - } + /* count BE for each non-aggregated slave or group */ + if (!endpoint->aggregated || no_aggregation || + !group_visited[endpoint->group_id]) + (*sdw_be_num)++; + } - if (endpoint->aggregated) - group_visited[endpoint->group_id] = true; + if (endpoint->aggregated) + group_visited[endpoint->group_id] = true; + } } return 0; @@ -829,17 +831,19 @@ static int create_codec_dai_name(struct device *dev, int offset, struct snd_soc_codec_conf *codec_conf, int codec_count, - int *codec_conf_index) + int *codec_conf_index, + int adr_index) { + int _codec_index = -1; int i; /* sanity check */ - if (*codec_conf_index + link->num_adr > codec_count) { + if (*codec_conf_index + link->num_adr - adr_index > codec_count) { dev_err(dev, "codec_conf: out-of-bounds access requested\n"); return -EINVAL; } - for (i = 0; i < link->num_adr; i++) { + for (i = adr_index; i < link->num_adr; i++) { unsigned int sdw_version, unique_id, mfg_id; unsigned int link_id, part_id, class_id; int codec_index, comp_index; @@ -855,7 +859,7 @@ static int create_codec_dai_name(struct device *dev, part_id = SDW_PART_ID(adr); class_id = SDW_CLASS_ID(adr); - comp_index = i + offset; + comp_index = i - adr_index + offset; if (is_unique_device(link, sdw_version, mfg_id, part_id, class_id, i)) { codec_str = "sdw:%01x:%04x:%04x:%02x"; @@ -877,6 +881,11 @@ static int create_codec_dai_name(struct device *dev, codec_index = find_codec_info_part(adr); if (codec_index < 0) return codec_index; + if (_codec_index != -1 && codec_index != _codec_index) { + dev_dbg(dev, "Different devices on the same sdw link\n"); + break; + } + _codec_index = codec_index; codec[comp_index].dai_name = codec_info_list[codec_index].dai_name; @@ -943,16 +952,16 @@ static int set_codec_init_func(struct snd_soc_card *card, static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, struct device *dev, int *cpu_dai_id, int *cpu_dai_num, int *codec_num, unsigned int *group_id, - bool *group_generated) + bool *group_generated, int adr_index) { const struct snd_soc_acpi_adr_device *adr_d; const struct snd_soc_acpi_link_adr *adr_next; bool no_aggregation; int index = 0; + int i; no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; - *codec_num = adr_link->num_adr; - adr_d = adr_link->adr_d; + adr_d = &adr_link->adr_d[adr_index]; /* make sure the link mask has a single bit set */ if (!is_power_of_2(adr_link->mask)) @@ -968,6 +977,14 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, *group_id = adr_d->endpoints->group_id; + /* Count endpoints with the same group_id in the adr_link */ + *codec_num = 0; + for (i = 0; i < adr_link->num_adr; i++) { + if (adr_link->adr_d[i].endpoints->aggregated && + adr_link->adr_d[i].endpoints->group_id == *group_id) + (*codec_num)++; + } + /* gather other link ID of slaves in the same group */ for (adr_next = adr_link + 1; adr_next && adr_next->num_adr; adr_next++) { @@ -988,7 +1005,11 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, } cpu_dai_id[index++] = ffs(adr_next->mask) - 1; - *codec_num += adr_next->num_adr; + for (i = 0; i < adr_next->num_adr; i++) { + if (adr_next->adr_d[i].endpoints->aggregated && + adr_next->adr_d[i].endpoints->group_id == *group_id) + (*codec_num)++; + } } /* @@ -1011,7 +1032,8 @@ static int create_sdw_dailink(struct snd_soc_card *card, struct snd_soc_codec_conf *codec_conf, int codec_count, int *link_id, int *codec_conf_index, - bool *ignore_pch_dmic) + bool *ignore_pch_dmic, + int adr_index) { const struct snd_soc_acpi_link_adr *link_next; struct snd_soc_dai_link_component *codecs; @@ -1027,7 +1049,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int k; ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num, - &group_id, group_generated); + &group_id, group_generated, adr_index); if (ret) return ret; @@ -1050,7 +1072,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, continue; ret = create_codec_dai_name(dev, link_next, codecs, codec_idx, - codec_conf, codec_count, codec_conf_index); + codec_conf, codec_count, codec_conf_index, adr_index); if (ret < 0) return ret; @@ -1060,7 +1082,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, } /* find codec info to create BE DAI */ - codec_index = find_codec_info_part(link->adr_d[0].adr); + codec_index = find_codec_info_part(link->adr_d[adr_index].adr); if (codec_index < 0) return codec_index; @@ -1303,29 +1325,31 @@ static int sof_card_dai_links_create(struct device *dev, /* generate DAI links by each sdw link */ for (; adr_link->num_adr; adr_link++) { - const struct snd_soc_acpi_endpoint *endpoint; + for (i = 0; i < adr_link->num_adr; i++) { + const struct snd_soc_acpi_endpoint *endpoint; - endpoint = adr_link->adr_d->endpoints; - if (endpoint->aggregated && !endpoint->group_id) { - dev_err(dev, "invalid group id on link %x", - adr_link->mask); - continue; - } + endpoint = adr_link->adr_d[i].endpoints; + if (endpoint->aggregated && !endpoint->group_id) { + dev_err(dev, "invalid group id on link %x", + adr_link->mask); + continue; + } - /* this group has been generated */ - if (endpoint->aggregated && - group_generated[endpoint->group_id]) - continue; + /* this group has been generated */ + if (endpoint->aggregated && + group_generated[endpoint->group_id]) + continue; - ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num, - sdw_cpu_dai_num, cpus, adr_link, - &cpu_id, group_generated, - codec_conf, codec_conf_count, - &be_id, &codec_conf_index, - &ignore_pch_dmic); - if (ret < 0) { - dev_err(dev, "failed to create dai link %d", link_index); - return ret; + ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num, + sdw_cpu_dai_num, cpus, adr_link, + &cpu_id, group_generated, + codec_conf, codec_conf_count, + &be_id, &codec_conf_index, + &ignore_pch_dmic, i); + if (ret < 0) { + dev_err(dev, "failed to create dai link %d", link_index); + return ret; + } } } -- cgit From dc5a3e60a4b5974a0cb5bf2c5df70a490dce9df2 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 19 Apr 2023 14:55:24 -0500 Subject: ASoC: Intel: sof_sdw: append codec type to dai link name The existing sdw_sof machine driver constructs two SoundWire interfaces by direction and sdw link id. It means that we will have exactly the same dai link name if two dai links are on the same sdw link with the same direction. The new Realtek codec has two SoundWire interfaces for jack and DMIC functions and they are treated as different codecs. To create two dai links for jack and DMIC, we need to have different dai link names. This patch suggests to append codec type if there are two or more different types of devices on the same sdw bus. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20230419195524.46995-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 41 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 6a6c81df72bd..6faf4a43eaf5 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1022,6 +1022,8 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, return 0; } +static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; + static int create_sdw_dailink(struct snd_soc_card *card, struct device *dev, int *link_index, struct snd_soc_dai_link *dai_links, @@ -1033,6 +1035,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int codec_count, int *link_id, int *codec_conf_index, bool *ignore_pch_dmic, + bool append_codec_type, int adr_index) { const struct snd_soc_acpi_link_adr *link_next; @@ -1109,14 +1112,22 @@ static int create_sdw_dailink(struct snd_soc_card *card, static const char * const sdw_stream_name[] = { "SDW%d-Playback", "SDW%d-Capture", + "SDW%d-Playback-%s", + "SDW%d-Capture-%s", }; if (!codec_info_list[codec_index].direction[stream]) continue; /* create stream name according to first link id */ - name = devm_kasprintf(dev, GFP_KERNEL, - sdw_stream_name[stream], cpu_dai_id[0]); + if (append_codec_type) { + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream + 2], cpu_dai_id[0], + type_strings[codec_info_list[codec_index].codec_type]); + } else { + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream], cpu_dai_id[0]); + } if (!name) return -ENOMEM; @@ -1232,6 +1243,7 @@ static int sof_card_dai_links_create(struct device *dev, const struct snd_soc_acpi_link_adr *adr_link; struct snd_soc_dai_link_component *cpus; struct snd_soc_codec_conf *codec_conf; + bool append_codec_type = false; bool ignore_pch_dmic = false; int codec_conf_count; int codec_conf_index = 0; @@ -1323,8 +1335,29 @@ static int sof_card_dai_links_create(struct device *dev, for (i = 0; i < SDW_MAX_GROUPS; i++) group_generated[i] = false; - /* generate DAI links by each sdw link */ for (; adr_link->num_adr; adr_link++) { + /* + * If there are two or more different devices on the same sdw link, we have to + * append the codec type to the dai link name to prevent duplicated dai link name. + * The same type devices on the same sdw link will be in the same + * snd_soc_acpi_adr_device array. They won't be described in different adr_links. + */ + for (i = 0; i < adr_link->num_adr; i++) { + for (j = 0; j < i; j++) { + if ((SDW_PART_ID(adr_link->adr_d[i].adr) != + SDW_PART_ID(adr_link->adr_d[j].adr)) || + (SDW_MFG_ID(adr_link->adr_d[i].adr) != + SDW_MFG_ID(adr_link->adr_d[i].adr))) { + append_codec_type = true; + goto out; + } + } + } + } +out: + + /* generate DAI links by each sdw link */ + for (adr_link = mach_params->links ; adr_link->num_adr; adr_link++) { for (i = 0; i < adr_link->num_adr; i++) { const struct snd_soc_acpi_endpoint *endpoint; @@ -1345,7 +1378,7 @@ static int sof_card_dai_links_create(struct device *dev, &cpu_id, group_generated, codec_conf, codec_conf_count, &be_id, &codec_conf_index, - &ignore_pch_dmic, i); + &ignore_pch_dmic, append_codec_type, i); if (ret < 0) { dev_err(dev, "failed to create dai link %d", link_index); return ret; -- cgit From 3e94369729ea8a825cf8bf304bfb1749de62ebf4 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 20 Apr 2023 14:41:36 +0300 Subject: ASoC: SOF: Intel: hda: Do not stop/start DMA during pause/release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FW does not pause/stop the host DMA during pause and stopping the host DMA from the driver could result in an unknown behaviour. So, skip triggering the HD-Audio host DMA during pause/release. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230420114137.27613-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 79d818e6a0fa..8de422604ad5 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -337,7 +337,13 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, /* cmd must be for audio stream */ switch (cmd) { case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (!sdev->dspless_mode_selected) + break; + fallthrough; case SNDRV_PCM_TRIGGER_START: + if (hstream->running) + break; + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, 1 << hstream->index, 1 << hstream->index); @@ -360,8 +366,11 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, hstream->running = true; break; - case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (!sdev->dspless_mode_selected) + break; + fallthrough; + case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, -- cgit From 6d0a21dd95c349bbe3663a4870ff7e70ddc6c9b6 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 20 Apr 2023 14:41:37 +0300 Subject: ASoC: SOF: pcm: Add an option to skip platform trigger during stop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the case of IPC4, a pipeline is only paused during STOP/PAUSE/SUSPEND triggers and the FW keeps the host DMA running when a pipeline is paused. The start/stop tests iterate through STOP/START triggers without involving a hw_free. This means that the pipeline state will only toggle between PAUSED (during the STOP trigger) and RUNNING (during the START trigger). So this test should be treated in the same way as a PAUSE_PUSH/PAUSE_RELEASE test and the DMA should be kept running when toggling the pipeline states between PAUSED and RUNNING. Since there is no way to tell if a STOP trigger will be followed by hw_free or not, this patch proposes to always skip DMA stop during the STOP trigger and handle it later during hw_free. Introduce a new flag in struct sof_ipc_pcm_ops, delayed_platform_trigger, that will be used to ensure that the host DMA will not be stopped during the STOP/PAUSE/RELEASE triggers and set it for IPC4. The platform_trigger call to stop the DMA will be invoked during PCM hw_free instead when the pipeline is reset. Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230420114137.27613-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-pcm.c | 3 ++- sound/soc/sof/pcm.c | 23 +++++++++++++++-------- sound/soc/sof/sof-audio.c | 22 ++++++++++++++-------- sound/soc/sof/sof-audio.h | 6 ++++++ 4 files changed, 37 insertions(+), 17 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index a2cd21256e44..ea19bd0330e2 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -836,5 +836,6 @@ const struct sof_ipc_pcm_ops ipc4_pcm_ops = { .pcm_setup = sof_ipc4_pcm_setup, .pcm_free = sof_ipc4_pcm_free, .delay = sof_ipc4_pcm_delay, - .ipc_first_on_start = true + .ipc_first_on_start = true, + .platform_stop_during_hw_free = true, }; diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 127b68caf9e1..567db32173a8 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -211,16 +211,22 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, dev_dbg(component->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); - /* free PCM in the DSP */ - if (pcm_ops && pcm_ops->hw_free && spcm->prepared[substream->stream]) { - ret = pcm_ops->hw_free(component, substream); - if (ret < 0) - err = ret; + if (spcm->prepared[substream->stream]) { + /* stop DMA first if needed */ + if (pcm_ops && pcm_ops->platform_stop_during_hw_free) + snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP); + + /* free PCM in the DSP */ + if (pcm_ops && pcm_ops->hw_free) { + ret = pcm_ops->hw_free(component, substream); + if (ret < 0) + err = ret; + } spcm->prepared[substream->stream] = false; } - /* stop DMA */ + /* reset DMA */ ret = snd_sof_pcm_platform_hw_free(sdev, substream); if (ret < 0) { dev_err(component->dev, "error: platform hw free failed\n"); @@ -362,8 +368,9 @@ static int sof_pcm_trigger(struct snd_soc_component *component, case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_STOP: - /* invoke platform trigger to stop DMA even if pcm_ops failed */ - snd_sof_pcm_platform_trigger(sdev, substream, cmd); + /* invoke platform trigger to stop DMA even if pcm_ops isn't set or if it failed */ + if (!pcm_ops || (pcm_ops && !pcm_ops->platform_stop_during_hw_free)) + snd_sof_pcm_platform_trigger(sdev, substream, cmd); break; default: break; diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 7651644fcd62..1cbda595c518 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -805,16 +805,22 @@ int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *subs const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); int ret; - /* Send PCM_FREE IPC to reset pipeline */ - if (pcm_ops && pcm_ops->hw_free && spcm->prepared[substream->stream]) { - ret = pcm_ops->hw_free(sdev->component, substream); - if (ret < 0) - return ret; - } + if (spcm->prepared[substream->stream]) { + /* stop DMA first if needed */ + if (pcm_ops && pcm_ops->platform_stop_during_hw_free) + snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP); + + /* Send PCM_FREE IPC to reset pipeline */ + if (pcm_ops && pcm_ops->hw_free) { + ret = pcm_ops->hw_free(sdev->component, substream); + if (ret < 0) + return ret; + } - spcm->prepared[substream->stream] = false; + spcm->prepared[substream->stream] = false; + } - /* stop the DMA */ + /* reset the DMA */ ret = snd_sof_pcm_platform_hw_free(sdev, substream); if (ret < 0) return ret; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 6c64376858b3..a090a9eb4828 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -108,6 +108,11 @@ struct snd_sof_dai_config_data { * STOP pcm trigger * @ipc_first_on_start: Send IPC before invoking platform trigger during * START/PAUSE_RELEASE triggers + * @platform_stop_during_hw_free: Invoke the platform trigger during hw_free. This is needed for + * IPC4 where a pipeline is only paused during stop/pause/suspend + * triggers. The FW keeps the host DMA running in this case and + * therefore the host must do the same and should stop the DMA during + * hw_free. */ struct sof_ipc_pcm_ops { int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream, @@ -123,6 +128,7 @@ struct sof_ipc_pcm_ops { struct snd_pcm_substream *substream); bool reset_hw_params_during_stop; bool ipc_first_on_start; + bool platform_stop_during_hw_free; }; /** -- cgit From 996b07efe49620325332081afdb0dc0bd6fe5cd0 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 20 Apr 2023 13:47:14 +0300 Subject: ASoC: SOF: Intel: Split the set_power_op for IPC3 and IPC4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suspending to S0iX with IPC3 requires the PM_GATE IPC to be sent again to stop the DMA trace. But with IPC4, this is not needed as the trace is stopped with the LARGE_CONFIG_SET IPC. Also, sending the MOD_D0IX IPC to set the D0I3 state again when the DSP is in D0I3 already results in an imbalance in PM runtime states in the firmware. So split the set_power_state ops for IPC3 and IPC4 to avoid sending the MOD_D0IX IPC when the DSP is already in D0I3 with IPC4. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20230420104714.29573-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/apl.c | 4 +++ sound/soc/sof/intel/cnl.c | 4 +++ sound/soc/sof/intel/hda-common-ops.c | 1 - sound/soc/sof/intel/hda-dsp.c | 60 +++++++++++++++++++++++------------- sound/soc/sof/intel/hda.h | 6 ++-- sound/soc/sof/intel/icl.c | 4 +++ sound/soc/sof/intel/mtl.c | 2 ++ sound/soc/sof/intel/tgl.c | 4 +++ 8 files changed, 60 insertions(+), 25 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 0e7a7e4ad976..e1f25a8f0c32 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -48,6 +48,8 @@ int sof_apl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_apl_ops.ipc_dump = hda_ipc_dump; + + sof_apl_ops.set_power_state = hda_dsp_set_power_state_ipc3; } if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { @@ -73,6 +75,8 @@ int sof_apl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_apl_ops.ipc_dump = hda_ipc4_dump; + + sof_apl_ops.set_power_state = hda_dsp_set_power_state_ipc4; } /* set DAI driver ops */ diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index a08a77fa946b..a95222e53ecf 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -395,6 +395,8 @@ int sof_cnl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_cnl_ops.ipc_dump = cnl_ipc_dump; + + sof_cnl_ops.set_power_state = hda_dsp_set_power_state_ipc3; } if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { @@ -420,6 +422,8 @@ int sof_cnl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_cnl_ops.ipc_dump = cnl_ipc4_dump; + + sof_cnl_ops.set_power_state = hda_dsp_set_power_state_ipc4; } /* set DAI driver ops */ diff --git a/sound/soc/sof/intel/hda-common-ops.c b/sound/soc/sof/intel/hda-common-ops.c index 397303b3ac9d..8e1cd0babd32 100644 --- a/sound/soc/sof/intel/hda-common-ops.c +++ b/sound/soc/sof/intel/hda-common-ops.c @@ -89,7 +89,6 @@ struct snd_sof_dsp_ops sof_hda_common_ops = { .runtime_resume = hda_dsp_runtime_resume, .runtime_idle = hda_dsp_runtime_idle, .set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume, - .set_power_state = hda_dsp_set_power_state, /* ALSA HW info flags */ .hw_info = SNDRV_PCM_INFO_MMAP | diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 77df536cf901..44f39a520bb3 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -574,31 +574,11 @@ static void hda_dsp_state_log(struct snd_sof_dev *sdev) * is called again either because of a new IPC sent to the DSP or * during system suspend/resume. */ -int hda_dsp_set_power_state(struct snd_sof_dev *sdev, - const struct sof_dsp_power_state *target_state) +static int hda_dsp_set_power_state(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state) { int ret = 0; - /* - * When the DSP is already in D0I3 and the target state is D0I3, - * it could be the case that the DSP is in D0I3 during S0 - * and the system is suspending to S0Ix. Therefore, - * hda_dsp_set_D0_state() must be called to disable trace DMA - * by sending the PM_GATE IPC to the FW. - */ - if (target_state->substate == SOF_HDA_DSP_PM_D0I3 && - sdev->system_suspend_target == SOF_SUSPEND_S0IX) - goto set_state; - - /* - * For all other cases, return without doing anything if - * the DSP is already in the target state. - */ - if (target_state->state == sdev->dsp_power_state.state && - target_state->substate == sdev->dsp_power_state.substate) - return 0; - -set_state: switch (target_state->state) { case SOF_DSP_PM_D0: ret = hda_dsp_set_D0_state(sdev, target_state); @@ -630,6 +610,42 @@ set_state: return ret; } +int hda_dsp_set_power_state_ipc3(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state) +{ + /* + * When the DSP is already in D0I3 and the target state is D0I3, + * it could be the case that the DSP is in D0I3 during S0 + * and the system is suspending to S0Ix. Therefore, + * hda_dsp_set_D0_state() must be called to disable trace DMA + * by sending the PM_GATE IPC to the FW. + */ + if (target_state->substate == SOF_HDA_DSP_PM_D0I3 && + sdev->system_suspend_target == SOF_SUSPEND_S0IX) + return hda_dsp_set_power_state(sdev, target_state); + + /* + * For all other cases, return without doing anything if + * the DSP is already in the target state. + */ + if (target_state->state == sdev->dsp_power_state.state && + target_state->substate == sdev->dsp_power_state.substate) + return 0; + + return hda_dsp_set_power_state(sdev, target_state); +} + +int hda_dsp_set_power_state_ipc4(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state) +{ + /* Return without doing anything if the DSP is already in the target state */ + if (target_state->state == sdev->dsp_power_state.state && + target_state->substate == sdev->dsp_power_state.substate) + return 0; + + return hda_dsp_set_power_state(sdev, target_state); +} + /* * Audio DSP states may transform as below:- * diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 0e0cfa81a8f2..c4befacde23e 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -584,8 +584,10 @@ void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev); void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev); bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev, unsigned int core_mask); -int hda_dsp_set_power_state(struct snd_sof_dev *sdev, - const struct sof_dsp_power_state *target_state); +int hda_dsp_set_power_state_ipc3(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state); +int hda_dsp_set_power_state_ipc4(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state); int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state); int hda_dsp_resume(struct snd_sof_dev *sdev); diff --git a/sound/soc/sof/intel/icl.c b/sound/soc/sof/intel/icl.c index 435941a1692f..0f249efc6a5a 100644 --- a/sound/soc/sof/intel/icl.c +++ b/sound/soc/sof/intel/icl.c @@ -116,6 +116,8 @@ int sof_icl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_icl_ops.ipc_dump = cnl_ipc_dump; + + sof_icl_ops.set_power_state = hda_dsp_set_power_state_ipc3; } if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { @@ -141,6 +143,8 @@ int sof_icl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_icl_ops.ipc_dump = cnl_ipc4_dump; + + sof_icl_ops.set_power_state = hda_dsp_set_power_state_ipc4; } /* debug */ diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 9f969e07fc27..46caf3ccde66 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -668,6 +668,8 @@ int sof_mtl_ops_init(struct snd_sof_dev *sdev) /* set DAI ops */ hda_set_dai_drv_ops(sdev, &sof_mtl_ops); + sof_mtl_ops.set_power_state = hda_dsp_set_power_state_ipc4; + return 0; }; EXPORT_SYMBOL_NS(sof_mtl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index 58ac3a46e6a7..2713b7dc7931 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -71,6 +71,8 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_tgl_ops.ipc_dump = cnl_ipc_dump; + + sof_tgl_ops.set_power_state = hda_dsp_set_power_state_ipc3; } if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { @@ -96,6 +98,8 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_tgl_ops.ipc_dump = cnl_ipc4_dump; + + sof_tgl_ops.set_power_state = hda_dsp_set_power_state_ipc4; } /* set DAI driver ops */ -- cgit From 2cc3fdcddc86644c070223c522e418416cb7b1a2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 19 Apr 2023 19:45:06 +0100 Subject: ASoC: es8316: Don't use ranges based register lookup for a single register The es8316 driver uses a register range to specify the single volatile register it has. While the cost will be in the noise this is a bunch of overhead compared to just having a volatile_reg() callback so switch to the callback. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20230419-asoc-es8316-volatile-v1-1-2074ec93d8f1@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/es8316.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index f7d7a9c91e04..a27d80956459 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -803,14 +803,15 @@ static const struct snd_soc_component_driver soc_component_dev_es8316 = { .endianness = 1, }; -static const struct regmap_range es8316_volatile_ranges[] = { - regmap_reg_range(ES8316_GPIO_FLAG, ES8316_GPIO_FLAG), -}; - -static const struct regmap_access_table es8316_volatile_table = { - .yes_ranges = es8316_volatile_ranges, - .n_yes_ranges = ARRAY_SIZE(es8316_volatile_ranges), -}; +static bool es8316_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ES8316_GPIO_FLAG: + return true; + default: + return false; + } +} static const struct regmap_config es8316_regmap = { .reg_bits = 8, @@ -818,7 +819,7 @@ static const struct regmap_config es8316_regmap = { .use_single_read = true, .use_single_write = true, .max_register = 0x53, - .volatile_table = &es8316_volatile_table, + .volatile_reg = es8316_volatile_reg, .cache_type = REGCACHE_RBTREE, }; -- cgit From a9e42d9e8b4be36a1e0dde0285a9ff36b2e06a46 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Thu, 20 Apr 2023 11:20:43 +0100 Subject: ASoC: cs35l56: Remove duplicate mbox log messages cs35l56_mbox_send() logs a warning when sending a mbox command fails so the callers can be simplified. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20230420102043.1151830-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index c0a857cfb8cb..46762f7f1449 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -859,10 +859,8 @@ static void cs35l56_dsp_work(struct work_struct *work) } ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_SHUTDOWN); - if (ret) { - dev_dbg(cs35l56->dev, "%s: CS35L56_MBOX_CMD_SHUTDOWN ret %d\n", __func__, ret); + if (ret) goto err; - } if (cs35l56->rev < CS35L56_REVID_B0) reg = CS35L56_DSP1_PM_CUR_STATE_A1; @@ -1033,9 +1031,7 @@ int cs35l56_runtime_suspend(struct device *dev) * Enable auto-hibernate. If it is woken by some other wake source * it will automatically return to hibernate. */ - ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE); - if (ret) - dev_warn(cs35l56->dev, "ALLOW_HIBERNATE failed: %d\n", ret); + cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE); /* * Must enter cache-only first so there can't be any more register -- cgit From d6e28695dcb6f653c7f2adf38021a5e934a6f416 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 21 Apr 2023 00:10:56 +0000 Subject: ASoC: fsl: imx-es8328: cleanup platform which is using Generic DMA If CPU is using soc-generic-dmaengine-pcm, Platform Component will be same as CPU Component. In this case, we can use CPU dlc for Platform dlc. This patch shares CPU dlc with Platform, and add comment. Signed-off-by: Kuninori Morimoto Acked-by: Shengjiu Wang Tested-by: Shengjiu Wang Link: https://lore.kernel.org/r/87bkjif628.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-es8328.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/imx-es8328.c b/sound/soc/fsl/imx-es8328.c index b80c57362fb8..85bd36fb68a2 100644 --- a/sound/soc/fsl/imx-es8328.c +++ b/sound/soc/fsl/imx-es8328.c @@ -149,7 +149,7 @@ static int imx_es8328_probe(struct platform_device *pdev) goto put_device; } - comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(dev, 2 * sizeof(*comp), GFP_KERNEL); if (!comp) { ret = -ENOMEM; goto put_device; @@ -159,9 +159,13 @@ static int imx_es8328_probe(struct platform_device *pdev) data->jack_gpio = of_get_named_gpio(pdev->dev.of_node, "jack-gpio", 0); - data->dai.cpus = &comp[0]; + /* + * CPU == Platform + * platform is using soc-generic-dmaengine-pcm + */ + data->dai.cpus = + data->dai.platforms = &comp[0]; data->dai.codecs = &comp[1]; - data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; @@ -172,7 +176,6 @@ static int imx_es8328_probe(struct platform_device *pdev) data->dai.codecs->dai_name = "es8328-hifi-analog"; data->dai.codecs->of_node = codec_np; data->dai.cpus->of_node = ssi_np; - data->dai.platforms->of_node = ssi_np; data->dai.init = &imx_es8328_dai_init; data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; -- cgit From 2324bc107b0b3d2de351f35032dc5093cbb61493 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 21 Apr 2023 00:11:07 +0000 Subject: ASoC: fsl: imx-spdif: cleanup platform which is using Generic DMA If CPU is using soc-generic-dmaengine-pcm, Platform Component will be same as CPU Component. In this case, we can use CPU dlc for Platform dlc. This patch shares CPU dlc with Platform, and add comment. Signed-off-by: Kuninori Morimoto Acked-by: Shengjiu Wang Tested-by: Shengjiu Wang Link: https://lore.kernel.org/r/87a5z2f61w.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-spdif.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index 4446fba755b9..ab978431ac98 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c @@ -26,15 +26,19 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); + comp = devm_kzalloc(&pdev->dev, 2 * sizeof(*comp), GFP_KERNEL); if (!data || !comp) { ret = -ENOMEM; goto end; } - data->dai.cpus = &comp[0]; + /* + * CPU == Platform + * platform is using soc-generic-dmaengine-pcm + */ + data->dai.cpus = + data->dai.platforms = &comp[0]; data->dai.codecs = &comp[1]; - data->dai.platforms = &comp[2]; data->dai.num_cpus = 1; data->dai.num_codecs = 1; @@ -45,7 +49,6 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) data->dai.codecs->dai_name = "snd-soc-dummy-dai"; data->dai.codecs->name = "snd-soc-dummy"; data->dai.cpus->of_node = spdif_np; - data->dai.platforms->of_node = spdif_np; data->dai.playback_only = true; data->dai.capture_only = true; -- cgit From 3ce08f85133fc93278801aba3efb4548d3ef3ca0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 21 Apr 2023 00:11:21 +0000 Subject: ASoC: fsl: imx-audmix: cleanup platform which is using Generic DMA If CPU is using soc-generic-dmaengine-pcm, Platform Component will be same as CPU Component. In this case, we can use CPU dlc for Platform dlc. This patch shares CPU dlc with Platform, and add comment. Signed-off-by: Kuninori Morimoto Acked-by: Shengjiu Wang Tested-by: Shengjiu Wang Link: https://lore.kernel.org/r/878remf61j.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmix.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index 1292a845c424..cabef0de3891 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -207,8 +207,8 @@ static int imx_audmix_probe(struct platform_device *pdev) for (i = 0; i < num_dai; i++) { struct snd_soc_dai_link_component *dlc; - /* for CPU/Codec/Platform x 2 */ - dlc = devm_kcalloc(&pdev->dev, 6, sizeof(*dlc), GFP_KERNEL); + /* for CPU/Codec x 2 + Platform */ + dlc = devm_kcalloc(&pdev->dev, 5, sizeof(*dlc), GFP_KERNEL); if (!dlc) return -ENOMEM; @@ -238,9 +238,13 @@ static int imx_audmix_probe(struct platform_device *pdev) dai_name, "CPU-Capture"); } - priv->dai[i].cpus = &dlc[0]; - priv->dai[i].codecs = &dlc[1]; - priv->dai[i].platforms = &dlc[2]; + /* + * CPU == Platform + * platform is using soc-generic-dmaengine-pcm + */ + priv->dai[i].cpus = + priv->dai[i].platforms = &dlc[0]; + priv->dai[i].codecs = &dlc[1]; priv->dai[i].num_cpus = 1; priv->dai[i].num_codecs = 1; @@ -252,7 +256,6 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[i].codecs->name = "snd-soc-dummy"; priv->dai[i].cpus->of_node = args.np; priv->dai[i].cpus->dai_name = dev_name(&cpu_pdev->dev); - priv->dai[i].platforms->of_node = args.np; priv->dai[i].dynamic = 1; priv->dai[i].dpcm_playback = 1; priv->dai[i].dpcm_capture = (i == 0 ? 1 : 0); @@ -267,9 +270,9 @@ static int imx_audmix_probe(struct platform_device *pdev) be_cp = devm_kasprintf(&pdev->dev, GFP_KERNEL, "AUDMIX-Capture-%d", i); - priv->dai[num_dai + i].cpus = &dlc[3]; - priv->dai[num_dai + i].codecs = &dlc[4]; - priv->dai[num_dai + i].platforms = &dlc[5]; + priv->dai[num_dai + i].cpus = &dlc[2]; + priv->dai[num_dai + i].codecs = &dlc[3]; + priv->dai[num_dai + i].platforms = &dlc[4]; priv->dai[num_dai + i].num_cpus = 1; priv->dai[num_dai + i].num_codecs = 1; -- cgit From dc801ea8ae37d54706e6f1cef140731ac5981c9c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 21 Apr 2023 00:11:31 +0000 Subject: ASoC: fsl: imx-audmix: remove dummy dai_link->platform Dummy dai_link->platform is not needed. Signed-off-by: Kuninori Morimoto Acked-by: Shengjiu Wang Tested-by: Shengjiu Wang Link: https://lore.kernel.org/r/877cu6f619.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmix.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index cabef0de3891..b2c5aca92c6b 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -207,8 +207,8 @@ static int imx_audmix_probe(struct platform_device *pdev) for (i = 0; i < num_dai; i++) { struct snd_soc_dai_link_component *dlc; - /* for CPU/Codec x 2 + Platform */ - dlc = devm_kcalloc(&pdev->dev, 5, sizeof(*dlc), GFP_KERNEL); + /* for CPU/Codec x 2 */ + dlc = devm_kcalloc(&pdev->dev, 4, sizeof(*dlc), GFP_KERNEL); if (!dlc) return -ENOMEM; @@ -272,18 +272,15 @@ static int imx_audmix_probe(struct platform_device *pdev) priv->dai[num_dai + i].cpus = &dlc[2]; priv->dai[num_dai + i].codecs = &dlc[3]; - priv->dai[num_dai + i].platforms = &dlc[4]; priv->dai[num_dai + i].num_cpus = 1; priv->dai[num_dai + i].num_codecs = 1; - priv->dai[num_dai + i].num_platforms = 1; priv->dai[num_dai + i].name = be_name; priv->dai[num_dai + i].codecs->dai_name = "snd-soc-dummy-dai"; priv->dai[num_dai + i].codecs->name = "snd-soc-dummy"; priv->dai[num_dai + i].cpus->of_node = audmix_np; priv->dai[num_dai + i].cpus->dai_name = be_name; - priv->dai[num_dai + i].platforms->name = "snd-soc-dummy"; priv->dai[num_dai + i].no_pcm = 1; priv->dai[num_dai + i].dpcm_playback = 1; priv->dai[num_dai + i].dpcm_capture = 1; -- cgit