diff options
Diffstat (limited to 'sound/soc/qcom/sc7280.c')
| -rw-r--r-- | sound/soc/qcom/sc7280.c | 170 |
1 files changed, 79 insertions, 91 deletions
diff --git a/sound/soc/qcom/sc7280.c b/sound/soc/qcom/sc7280.c index da7469a6a267..abdd58c1d0a4 100644 --- a/sound/soc/qcom/sc7280.c +++ b/sound/soc/qcom/sc7280.c @@ -4,9 +4,11 @@ // // ALSA SoC Machine driver for sc7280 +#include <dt-bindings/sound/qcom,lpass.h> +#include <dt-bindings/sound/qcom,q6afe.h> #include <linux/input.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <sound/core.h> #include <sound/jack.h> @@ -14,12 +16,14 @@ #include <sound/soc.h> #include <sound/rt5682s.h> #include <linux/soundwire/sdw.h> +#include <sound/pcm_params.h> #include "../codecs/rt5682.h" #include "../codecs/rt5682s.h" #include "common.h" #include "lpass.h" #include "qdsp6/q6afe.h" +#include "sdw.h" #define DEFAULT_MCLK_RATE 19200000 #define RT5682_PLL_FREQ (48000 * 512) @@ -27,7 +31,6 @@ struct sc7280_snd_data { struct snd_soc_card card; - struct sdw_stream_runtime *sruntime[LPASS_MAX_PORTS]; u32 pri_mi2s_clk_count; struct snd_soc_jack hs_jack; struct snd_soc_jack hdmi_jack; @@ -42,24 +45,37 @@ static void sc7280_jack_free(struct snd_jack *jack) snd_soc_component_set_jack(component, NULL, NULL); } +static struct snd_soc_jack_pin sc7280_jack_pins[] = { + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + static int sc7280_headset_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; struct sc7280_snd_data *pdata = snd_soc_card_get_drvdata(card); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_soc_component *component = codec_dai->component; struct snd_jack *jack; int rval, i; if (!pdata->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, - &pdata->hs_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, + &pdata->hs_jack, + sc7280_jack_pins, + ARRAY_SIZE(sc7280_jack_pins)); if (rval < 0) { dev_err(card->dev, "Unable to add Headset Jack\n"); @@ -101,7 +117,7 @@ static int sc7280_hdmi_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; struct sc7280_snd_data *pdata = snd_soc_card_get_drvdata(card); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); struct snd_soc_component *component = codec_dai->component; struct snd_jack *jack; int rval; @@ -123,8 +139,8 @@ static int sc7280_hdmi_init(struct snd_soc_pcm_runtime *rtd) static int sc7280_rt5682_init(struct snd_soc_pcm_runtime *rtd) { - 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_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct sc7280_snd_data *data = snd_soc_card_get_drvdata(card); int ret; @@ -162,7 +178,7 @@ static int sc7280_rt5682_init(struct snd_soc_pcm_runtime *rtd) static int sc7280_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); switch (cpu_dai->id) { case MI2S_PRIMARY: @@ -189,29 +205,11 @@ static int sc7280_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai; - const struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); - struct sc7280_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); - struct sdw_stream_runtime *sruntime; - int i; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, 48000, 48000); - - switch (cpu_dai->id) { - case LPASS_CDC_DMA_TX3: - case LPASS_CDC_DMA_RX0: - case RX_CODEC_DMA_RX_0: - case SECONDARY_MI2S_RX: - case TX_CODEC_DMA_TX_3: - case VA_CODEC_DMA_TX_0: - 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; + if (!rtd->dai_link->no_pcm) { + snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); + snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, 48000, 48000); } return 0; @@ -219,39 +217,17 @@ static int sc7280_snd_hw_params(struct snd_pcm_substream *substream, static int sc7280_snd_swr_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - const struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sc7280_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; - ret = sdw_enable_stream(sruntime); - if (ret) { - sdw_deprepare_stream(sruntime); - return ret; - } - data->stream_prepared[cpu_dai->id] = true; - - return ret; + return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]); } static int sc7280_snd_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - const struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); switch (cpu_dai->id) { case LPASS_CDC_DMA_RX0: @@ -269,35 +245,19 @@ static int sc7280_snd_prepare(struct snd_pcm_substream *substream) static int sc7280_snd_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sc7280_snd_data *data = snd_soc_card_get_drvdata(rtd->card); - const struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; + const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - switch (cpu_dai->id) { - case LPASS_CDC_DMA_RX0: - case LPASS_CDC_DMA_TX3: - case RX_CODEC_DMA_RX_0: - case TX_CODEC_DMA_TX_3: - case VA_CODEC_DMA_TX_0: - 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, &data->stream_prepared[cpu_dai->id]); } static void sc7280_snd_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct sc7280_snd_data *data = snd_soc_card_get_drvdata(card); - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); switch (cpu_dai->id) { case MI2S_PRIMARY: @@ -315,20 +275,24 @@ static void sc7280_snd_shutdown(struct snd_pcm_substream *substream) default: break; } + + qcom_snd_sdw_shutdown(substream); } static int sc7280_snd_startup(struct snd_pcm_substream *substream) { - unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; - unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + unsigned int fmt = SND_SOC_DAIFMT_CBC_CFC; + unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBC_CFC; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); int ret = 0; switch (cpu_dai->id) { case MI2S_PRIMARY: ret = sc7280_rt5682_init(rtd); + if (ret) + return ret; break; case SECONDARY_MI2S_RX: codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; @@ -342,7 +306,8 @@ static int sc7280_snd_startup(struct snd_pcm_substream *substream) default: break; } - return ret; + + return qcom_snd_sdw_startup(substream); } static const struct snd_soc_ops sc7280_ops = { @@ -358,6 +323,25 @@ static const struct snd_soc_dapm_widget sc7280_snd_widgets[] = { SND_SOC_DAPM_MIC("Headset Mic", NULL), }; +static const struct snd_kcontrol_new sc7280_snd_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static int sc7280_snd_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); + + return 0; +} + static int sc7280_snd_platform_probe(struct platform_device *pdev) { struct snd_soc_card *card; @@ -379,6 +363,8 @@ static int sc7280_snd_platform_probe(struct platform_device *pdev) card->dapm_widgets = sc7280_snd_widgets; card->num_dapm_widgets = ARRAY_SIZE(sc7280_snd_widgets); + card->controls = sc7280_snd_controls; + card->num_controls = ARRAY_SIZE(sc7280_snd_controls); ret = qcom_snd_parse_of(card); if (ret) @@ -387,6 +373,8 @@ static int sc7280_snd_platform_probe(struct platform_device *pdev) for_each_card_prelinks(card, i, link) { link->init = sc7280_init; link->ops = &sc7280_ops; + if (link->no_pcm == 1) + link->be_hw_params_fixup = sc7280_snd_be_hw_params_fixup; } return devm_snd_soc_register_card(dev, card); |
