1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2020, Linaro Limited 3 4 #include <dt-bindings/sound/qcom,q6afe.h> 5 #include <linux/module.h> 6 #include <linux/platform_device.h> 7 #include <sound/soc.h> 8 #include <sound/soc-dapm.h> 9 #include <sound/pcm.h> 10 #include <sound/pcm_params.h> 11 #include <linux/soundwire/sdw.h> 12 #include <sound/jack.h> 13 #include <linux/input-event-codes.h> 14 #include "qdsp6/q6afe.h" 15 #include "common.h" 16 #include "sdw.h" 17 18 #define DRIVER_NAME "sm8250" 19 #define MI2S_BCLK_RATE 1536000 20 21 struct sm8250_snd_data { 22 bool stream_prepared[AFE_PORT_MAX]; 23 struct snd_soc_card *card; 24 struct sdw_stream_runtime *sruntime[AFE_PORT_MAX]; 25 struct snd_soc_jack jack; 26 bool jack_setup; 27 }; 28 29 static int sm8250_snd_init(struct snd_soc_pcm_runtime *rtd) 30 { 31 struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 32 33 return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup); 34 } 35 36 static int sm8250_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 37 struct snd_pcm_hw_params *params) 38 { 39 struct snd_interval *rate = hw_param_interval(params, 40 SNDRV_PCM_HW_PARAM_RATE); 41 struct snd_interval *channels = hw_param_interval(params, 42 SNDRV_PCM_HW_PARAM_CHANNELS); 43 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 44 45 rate->min = rate->max = 48000; 46 channels->min = channels->max = 2; 47 snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); 48 49 return 0; 50 } 51 52 static int sm8250_snd_startup(struct snd_pcm_substream *substream) 53 { 54 unsigned int fmt = SND_SOC_DAIFMT_BP_FP; 55 unsigned int codec_dai_fmt = SND_SOC_DAIFMT_BC_FC; 56 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 57 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 58 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 59 60 switch (cpu_dai->id) { 61 case PRIMARY_MI2S_RX: 62 codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; 63 snd_soc_dai_set_sysclk(cpu_dai, 64 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT, 65 MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); 66 snd_soc_dai_set_fmt(cpu_dai, fmt); 67 snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); 68 break; 69 case SECONDARY_MI2S_RX: 70 codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; 71 snd_soc_dai_set_sysclk(cpu_dai, 72 Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT, 73 MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); 74 snd_soc_dai_set_fmt(cpu_dai, fmt); 75 snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); 76 break; 77 case TERTIARY_MI2S_RX: 78 codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; 79 snd_soc_dai_set_sysclk(cpu_dai, 80 Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT, 81 MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); 82 snd_soc_dai_set_fmt(cpu_dai, fmt); 83 snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); 84 break; 85 default: 86 break; 87 } 88 89 return qcom_snd_sdw_startup(substream); 90 } 91 92 static void sm8250_snd_shutdown(struct snd_pcm_substream *substream) 93 { 94 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 95 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 96 struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 97 struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; 98 99 data->sruntime[cpu_dai->id] = NULL; 100 sdw_release_stream(sruntime); 101 } 102 103 static int sm8250_snd_hw_params(struct snd_pcm_substream *substream, 104 struct snd_pcm_hw_params *params) 105 { 106 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 107 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 108 struct sm8250_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); 109 110 return qcom_snd_sdw_hw_params(substream, params, &pdata->sruntime[cpu_dai->id]); 111 } 112 113 static int sm8250_snd_prepare(struct snd_pcm_substream *substream) 114 { 115 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 116 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 117 struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 118 struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; 119 120 return qcom_snd_sdw_prepare(substream, sruntime, 121 &data->stream_prepared[cpu_dai->id]); 122 } 123 124 static int sm8250_snd_hw_free(struct snd_pcm_substream *substream) 125 { 126 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 127 struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 128 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 129 struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; 130 131 return qcom_snd_sdw_hw_free(substream, sruntime, 132 &data->stream_prepared[cpu_dai->id]); 133 } 134 135 static const struct snd_soc_ops sm8250_be_ops = { 136 .startup = sm8250_snd_startup, 137 .shutdown = sm8250_snd_shutdown, 138 .hw_params = sm8250_snd_hw_params, 139 .hw_free = sm8250_snd_hw_free, 140 .prepare = sm8250_snd_prepare, 141 }; 142 143 static void sm8250_add_be_ops(struct snd_soc_card *card) 144 { 145 struct snd_soc_dai_link *link; 146 int i; 147 148 for_each_card_prelinks(card, i, link) { 149 if (link->no_pcm == 1) { 150 link->init = sm8250_snd_init; 151 link->be_hw_params_fixup = sm8250_be_hw_params_fixup; 152 link->ops = &sm8250_be_ops; 153 } 154 } 155 } 156 157 static int sm8250_platform_probe(struct platform_device *pdev) 158 { 159 struct snd_soc_card *card; 160 struct sm8250_snd_data *data; 161 struct device *dev = &pdev->dev; 162 int ret; 163 164 card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); 165 if (!card) 166 return -ENOMEM; 167 168 card->owner = THIS_MODULE; 169 /* Allocate the private data */ 170 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 171 if (!data) 172 return -ENOMEM; 173 174 card->dev = dev; 175 dev_set_drvdata(dev, card); 176 snd_soc_card_set_drvdata(card, data); 177 ret = qcom_snd_parse_of(card); 178 if (ret) 179 return ret; 180 181 card->driver_name = DRIVER_NAME; 182 sm8250_add_be_ops(card); 183 return devm_snd_soc_register_card(dev, card); 184 } 185 186 static const struct of_device_id snd_sm8250_dt_match[] = { 187 {.compatible = "qcom,sm8250-sndcard"}, 188 {.compatible = "qcom,qrb4210-rb2-sndcard"}, 189 {.compatible = "qcom,qrb5165-rb5-sndcard"}, 190 {} 191 }; 192 193 MODULE_DEVICE_TABLE(of, snd_sm8250_dt_match); 194 195 static struct platform_driver snd_sm8250_driver = { 196 .probe = sm8250_platform_probe, 197 .driver = { 198 .name = "snd-sm8250", 199 .of_match_table = snd_sm8250_dt_match, 200 }, 201 }; 202 module_platform_driver(snd_sm8250_driver); 203 MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org"); 204 MODULE_DESCRIPTION("SM8250 ASoC Machine Driver"); 205 MODULE_LICENSE("GPL"); 206