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