On Thu, Sep 15, 2022 at 01:56:10PM +0100, Srinivas Kandagatla wrote: > SM8450 machine driver code can be reused across multiple Qualcomm SoCs, > At least another 2 of them for now (SM8450 and SM8250XP). s/SM8250XP/SC8280XP/ Regards, Bjorn > > Move some of the common SoundWire stream specific code to common file > so that other drivers can use it instead of duplication. > > This patch is to prepare the common driver to be able to add new SoCs support > with less dupication. > > Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@xxxxxxxxxx> > Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@xxxxxxxxxx> > --- > sound/soc/qcom/common.c | 171 ++++++++++++++++++++++++++++++++++++++++ > sound/soc/qcom/common.h | 35 ++++++++ > sound/soc/qcom/sm8250.c | 152 ++--------------------------------- > 3 files changed, 213 insertions(+), 145 deletions(-) > > diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c > index e53ad84f8ff5..69dd3b504e20 100644 > --- a/sound/soc/qcom/common.c > +++ b/sound/soc/qcom/common.c > @@ -3,6 +3,9 @@ > // Copyright (c) 2018, The Linux Foundation. All rights reserved. > > #include <linux/module.h> > +#include <sound/jack.h> > +#include <linux/input-event-codes.h> > +#include "qdsp6/q6afe.h" > #include "common.h" > > int qcom_snd_parse_of(struct snd_soc_card *card) > @@ -177,4 +180,172 @@ int qcom_snd_parse_of(struct snd_soc_card *card) > } > EXPORT_SYMBOL_GPL(qcom_snd_parse_of); > > +#if IS_ENABLED(CONFIG_SOUNDWIRE) > +int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, > + struct sdw_stream_runtime *sruntime, > + bool *stream_prepared) > +{ > + struct snd_soc_pcm_runtime *rtd = substream->private_data; > + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); > + int ret; > + > + if (!sruntime) > + return 0; > + > + switch (cpu_dai->id) { > + case WSA_CODEC_DMA_RX_0: > + case WSA_CODEC_DMA_RX_1: > + case RX_CODEC_DMA_RX_0: > + case RX_CODEC_DMA_RX_1: > + case TX_CODEC_DMA_TX_0: > + case TX_CODEC_DMA_TX_1: > + case TX_CODEC_DMA_TX_2: > + case TX_CODEC_DMA_TX_3: > + break; > + default: > + return 0; > + } > + > + if (*stream_prepared) { > + sdw_disable_stream(sruntime); > + sdw_deprepare_stream(sruntime); > + *stream_prepared = false; > + } > + > + ret = sdw_prepare_stream(sruntime); > + if (ret) > + return ret; > + > + /** > + * NOTE: there is a strict hw requirement about the ordering of port > + * enables and actual WSA881x PA enable. PA enable should only happen > + * after soundwire ports are enabled if not DC on the line is > + * accumulated resulting in Click/Pop Noise > + * PA enable/mute are handled as part of codec DAPM and digital mute. > + */ > + > + ret = sdw_enable_stream(sruntime); > + if (ret) { > + sdw_deprepare_stream(sruntime); > + return ret; > + } > + *stream_prepared = true; > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare); > + > +int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, > + struct snd_pcm_hw_params *params, > + struct sdw_stream_runtime **psruntime) > +{ > + struct snd_soc_pcm_runtime *rtd = substream->private_data; > + struct snd_soc_dai *codec_dai; > + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); > + struct sdw_stream_runtime *sruntime; > + int i; > + > + switch (cpu_dai->id) { > + case WSA_CODEC_DMA_RX_0: > + case RX_CODEC_DMA_RX_0: > + case RX_CODEC_DMA_RX_1: > + case TX_CODEC_DMA_TX_0: > + case TX_CODEC_DMA_TX_1: > + case TX_CODEC_DMA_TX_2: > + case TX_CODEC_DMA_TX_3: > + for_each_rtd_codec_dais(rtd, i, codec_dai) { > + sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream); > + if (sruntime != ERR_PTR(-ENOTSUPP)) > + *psruntime = sruntime; > + } > + break; > + } > + > + return 0; > + > +} > +EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params); > + > +int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, > + struct sdw_stream_runtime *sruntime, bool *stream_prepared) > +{ > + struct snd_soc_pcm_runtime *rtd = substream->private_data; > + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); > + > + switch (cpu_dai->id) { > + case WSA_CODEC_DMA_RX_0: > + case WSA_CODEC_DMA_RX_1: > + case RX_CODEC_DMA_RX_0: > + case RX_CODEC_DMA_RX_1: > + case TX_CODEC_DMA_TX_0: > + case TX_CODEC_DMA_TX_1: > + case TX_CODEC_DMA_TX_2: > + case TX_CODEC_DMA_TX_3: > + if (sruntime && *stream_prepared) { > + sdw_disable_stream(sruntime); > + sdw_deprepare_stream(sruntime); > + *stream_prepared = false; > + } > + break; > + default: > + break; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free); > +#endif > + > +int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, > + struct snd_soc_jack *jack, bool *jack_setup) > +{ > + 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 snd_soc_card *card = rtd->card; > + int rval, i; > + > + if (!*jack_setup) { > + rval = snd_soc_card_jack_new(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); > + > + if (rval < 0) { > + dev_err(card->dev, "Unable to add Headphone Jack\n"); > + return rval; > + } > + > + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA); > + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); > + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); > + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); > + *jack_setup = true; > + } > + > + switch (cpu_dai->id) { > + case TX_CODEC_DMA_TX_0: > + case TX_CODEC_DMA_TX_1: > + case TX_CODEC_DMA_TX_2: > + case TX_CODEC_DMA_TX_3: > + for_each_rtd_codec_dais(rtd, i, codec_dai) { > + rval = snd_soc_component_set_jack(codec_dai->component, > + jack, NULL); > + if (rval != 0 && rval != -ENOTSUPP) { > + dev_warn(card->dev, "Failed to set jack: %d\n", rval); > + return rval; > + } > + } > + > + break; > + default: > + break; > + } > + > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(qcom_snd_wcd_jack_setup); > MODULE_LICENSE("GPL v2"); > diff --git a/sound/soc/qcom/common.h b/sound/soc/qcom/common.h > index f05c05b12bd7..c5472a642de0 100644 > --- a/sound/soc/qcom/common.h > +++ b/sound/soc/qcom/common.h > @@ -5,7 +5,42 @@ > #define __QCOM_SND_COMMON_H__ > > #include <sound/soc.h> > +#include <linux/soundwire/sdw.h> > > int qcom_snd_parse_of(struct snd_soc_card *card); > +int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, > + struct snd_soc_jack *jack, bool *jack_setup); > > +#if IS_ENABLED(CONFIG_SOUNDWIRE) > +int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, > + struct sdw_stream_runtime *runtime, > + bool *stream_prepared); > +int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, > + struct snd_pcm_hw_params *params, > + struct sdw_stream_runtime **psruntime); > +int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, > + struct sdw_stream_runtime *sruntime, > + bool *stream_prepared); > +#else > +static inline int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, > + struct sdw_stream_runtime *runtime, > + bool *stream_prepared) > +{ > + return -ENOTSUPP; > +} > + > +static inline int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, > + struct snd_pcm_hw_params *params, > + struct sdw_stream_runtime **psruntime) > +{ > + return -ENOTSUPP; > +} > + > +static inline int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, > + struct sdw_stream_runtime *sruntime, > + bool *stream_prepared) > +{ > + return -ENOTSUPP; > +} > +#endif > #endif > diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c > index 98a2fde9e004..8dbe9ef41b1c 100644 > --- a/sound/soc/qcom/sm8250.c > +++ b/sound/soc/qcom/sm8250.c > @@ -27,57 +27,8 @@ struct sm8250_snd_data { > static int sm8250_snd_init(struct snd_soc_pcm_runtime *rtd) > { > struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); > - 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 snd_soc_card *card = rtd->card; > - int rval, i; > - > - if (!data->jack_setup) { > - struct snd_jack *jack; > - > - rval = snd_soc_card_jack_new(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, > - &data->jack); > - > - if (rval < 0) { > - dev_err(card->dev, "Unable to add Headphone Jack\n"); > - return rval; > - } > - > - jack = data->jack.jack; > - > - snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_MEDIA); > - snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); > - snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP); > - snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); > - data->jack_setup = true; > - } > - > - switch (cpu_dai->id) { > - case TX_CODEC_DMA_TX_0: > - case TX_CODEC_DMA_TX_1: > - case TX_CODEC_DMA_TX_2: > - case TX_CODEC_DMA_TX_3: > - for_each_rtd_codec_dais(rtd, i, codec_dai) { > - rval = snd_soc_component_set_jack(codec_dai->component, > - &data->jack, NULL); > - if (rval != 0 && rval != -ENOTSUPP) { > - dev_warn(card->dev, "Failed to set jack: %d\n", rval); > - return rval; > - } > - } > - > - break; > - default: > - break; > - } > > - > - return 0; > + return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup); > } > > static int sm8250_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, > @@ -121,92 +72,21 @@ static int sm8250_snd_hw_params(struct snd_pcm_substream *substream, > struct snd_pcm_hw_params *params) > { > struct snd_soc_pcm_runtime *rtd = substream->private_data; > - struct snd_soc_dai *codec_dai; > struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); > struct sm8250_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); > - struct sdw_stream_runtime *sruntime; > - int i; > - > - switch (cpu_dai->id) { > - case WSA_CODEC_DMA_RX_0: > - case RX_CODEC_DMA_RX_0: > - case RX_CODEC_DMA_RX_1: > - case TX_CODEC_DMA_TX_0: > - case TX_CODEC_DMA_TX_1: > - case TX_CODEC_DMA_TX_2: > - case TX_CODEC_DMA_TX_3: > - for_each_rtd_codec_dais(rtd, i, codec_dai) { > - sruntime = snd_soc_dai_get_stream(codec_dai, > - substream->stream); > - if (sruntime != ERR_PTR(-ENOTSUPP)) > - pdata->sruntime[cpu_dai->id] = sruntime; > - } > - break; > - } > - > - return 0; > > + return qcom_snd_sdw_hw_params(substream, params, &pdata->sruntime[cpu_dai->id]); > } > > -static int sm8250_snd_wsa_dma_prepare(struct snd_pcm_substream *substream) > +static int sm8250_snd_prepare(struct snd_pcm_substream *substream) > { > struct snd_soc_pcm_runtime *rtd = substream->private_data; > struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); > struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); > struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; > - int ret; > - > - if (!sruntime) > - return 0; > > - if (data->stream_prepared[cpu_dai->id]) { > - sdw_disable_stream(sruntime); > - sdw_deprepare_stream(sruntime); > - data->stream_prepared[cpu_dai->id] = false; > - } > - > - ret = sdw_prepare_stream(sruntime); > - if (ret) > - return ret; > - > - /** > - * NOTE: there is a strict hw requirement about the ordering of port > - * enables and actual WSA881x PA enable. PA enable should only happen > - * after soundwire ports are enabled if not DC on the line is > - * accumulated resulting in Click/Pop Noise > - * PA enable/mute are handled as part of codec DAPM and digital mute. > - */ > - > - ret = sdw_enable_stream(sruntime); > - if (ret) { > - sdw_deprepare_stream(sruntime); > - return ret; > - } > - data->stream_prepared[cpu_dai->id] = true; > - > - return ret; > -} > - > -static int sm8250_snd_prepare(struct snd_pcm_substream *substream) > -{ > - struct snd_soc_pcm_runtime *rtd = substream->private_data; > - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); > - > - switch (cpu_dai->id) { > - case WSA_CODEC_DMA_RX_0: > - case WSA_CODEC_DMA_RX_1: > - case RX_CODEC_DMA_RX_0: > - case RX_CODEC_DMA_RX_1: > - case TX_CODEC_DMA_TX_0: > - case TX_CODEC_DMA_TX_1: > - case TX_CODEC_DMA_TX_2: > - case TX_CODEC_DMA_TX_3: > - return sm8250_snd_wsa_dma_prepare(substream); > - default: > - break; > - } > - > - return 0; > + return qcom_snd_sdw_prepare(substream, sruntime, > + &data->stream_prepared[cpu_dai->id]); > } > > static int sm8250_snd_hw_free(struct snd_pcm_substream *substream) > @@ -216,26 +96,8 @@ static int sm8250_snd_hw_free(struct snd_pcm_substream *substream) > struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); > struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; > > - switch (cpu_dai->id) { > - case WSA_CODEC_DMA_RX_0: > - case WSA_CODEC_DMA_RX_1: > - case RX_CODEC_DMA_RX_0: > - case RX_CODEC_DMA_RX_1: > - case TX_CODEC_DMA_TX_0: > - case TX_CODEC_DMA_TX_1: > - case TX_CODEC_DMA_TX_2: > - case TX_CODEC_DMA_TX_3: > - if (sruntime && data->stream_prepared[cpu_dai->id]) { > - sdw_disable_stream(sruntime); > - sdw_deprepare_stream(sruntime); > - data->stream_prepared[cpu_dai->id] = false; > - } > - break; > - default: > - break; > - } > - > - return 0; > + return qcom_snd_sdw_hw_free(substream, sruntime, > + &data->stream_prepared[cpu_dai->id]); > } > > static const struct snd_soc_ops sm8250_be_ops = { > -- > 2.21.0 >