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 "usb_offload_utils.h" 17 #include "sdw.h" 18 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 snd_soc_jack jack; 25 struct snd_soc_jack usb_offload_jack; 26 bool usb_offload_jack_setup; 27 struct snd_soc_jack dp_jack; 28 bool jack_setup; 29 }; 30 31 static int sm8250_snd_init(struct snd_soc_pcm_runtime *rtd) 32 { 33 struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 34 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 35 36 switch (cpu_dai->id) { 37 case DISPLAY_PORT_RX: 38 return qcom_snd_dp_jack_setup(rtd, &data->dp_jack, 0); 39 case USB_RX: 40 return qcom_snd_usb_offload_jack_setup(rtd, &data->usb_offload_jack, 41 &data->usb_offload_jack_setup); 42 default: 43 return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup); 44 } 45 } 46 47 static void sm8250_snd_exit(struct snd_soc_pcm_runtime *rtd) 48 { 49 struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 50 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 51 52 if (cpu_dai->id == USB_RX) 53 qcom_snd_usb_offload_jack_remove(rtd, 54 &data->usb_offload_jack_setup); 55 56 } 57 58 static int sm8250_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 59 struct snd_pcm_hw_params *params) 60 { 61 struct snd_interval *rate = hw_param_interval(params, 62 SNDRV_PCM_HW_PARAM_RATE); 63 struct snd_interval *channels = hw_param_interval(params, 64 SNDRV_PCM_HW_PARAM_CHANNELS); 65 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 66 67 rate->min = rate->max = 48000; 68 channels->min = channels->max = 2; 69 snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); 70 71 return 0; 72 } 73 74 static int sm8250_snd_startup(struct snd_pcm_substream *substream) 75 { 76 unsigned int fmt = SND_SOC_DAIFMT_BP_FP; 77 unsigned int codec_dai_fmt = SND_SOC_DAIFMT_BC_FC; 78 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 79 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 80 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 81 82 switch (cpu_dai->id) { 83 case PRIMARY_MI2S_RX: 84 codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; 85 snd_soc_dai_set_sysclk(cpu_dai, 86 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT, 87 MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); 88 snd_soc_dai_set_fmt(cpu_dai, fmt); 89 snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); 90 break; 91 case SECONDARY_MI2S_RX: 92 codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; 93 snd_soc_dai_set_sysclk(cpu_dai, 94 Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT, 95 MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); 96 snd_soc_dai_set_fmt(cpu_dai, fmt); 97 snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); 98 break; 99 case TERTIARY_MI2S_RX: 100 codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; 101 snd_soc_dai_set_sysclk(cpu_dai, 102 Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT, 103 MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); 104 snd_soc_dai_set_fmt(cpu_dai, fmt); 105 snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); 106 break; 107 case QUINARY_MI2S_RX: 108 codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; 109 snd_soc_dai_set_sysclk(cpu_dai, 110 Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT, 111 MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); 112 snd_soc_dai_set_fmt(cpu_dai, fmt); 113 snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); 114 break; 115 case LPI_MI2S_RX_0: 116 codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; 117 snd_soc_dai_set_sysclk(cpu_dai, 118 Q6AFE_LPASS_CLK_ID_INT0_MI2S_IBIT, 119 MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); 120 snd_soc_dai_set_fmt(cpu_dai, fmt); 121 snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); 122 break; 123 case LPI_MI2S_TX_3: 124 codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; 125 snd_soc_dai_set_sysclk(cpu_dai, 126 Q6AFE_LPASS_CLK_ID_INT3_MI2S_IBIT, 127 MI2S_BCLK_RATE, SNDRV_PCM_STREAM_CAPTURE); 128 snd_soc_dai_set_fmt(cpu_dai, fmt); 129 snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); 130 break; 131 default: 132 break; 133 } 134 135 return qcom_snd_sdw_startup(substream); 136 } 137 138 static int sm8250_snd_prepare(struct snd_pcm_substream *substream) 139 { 140 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 141 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 142 struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 143 144 return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]); 145 } 146 147 static int sm8250_snd_hw_free(struct snd_pcm_substream *substream) 148 { 149 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 150 struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 151 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 152 153 return qcom_snd_sdw_hw_free(substream, &data->stream_prepared[cpu_dai->id]); 154 } 155 156 static const struct snd_soc_ops sm8250_be_ops = { 157 .startup = sm8250_snd_startup, 158 .shutdown = qcom_snd_sdw_shutdown, 159 .hw_free = sm8250_snd_hw_free, 160 .prepare = sm8250_snd_prepare, 161 }; 162 163 static void sm8250_add_be_ops(struct snd_soc_card *card) 164 { 165 struct snd_soc_dai_link *link; 166 int i; 167 168 for_each_card_prelinks(card, i, link) { 169 if (link->no_pcm == 1) { 170 link->init = sm8250_snd_init; 171 link->exit = sm8250_snd_exit; 172 link->be_hw_params_fixup = sm8250_be_hw_params_fixup; 173 link->ops = &sm8250_be_ops; 174 } 175 } 176 } 177 178 static int sm8250_platform_probe(struct platform_device *pdev) 179 { 180 struct snd_soc_card *card; 181 struct sm8250_snd_data *data; 182 struct device *dev = &pdev->dev; 183 int ret; 184 185 card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); 186 if (!card) 187 return -ENOMEM; 188 189 card->owner = THIS_MODULE; 190 /* Allocate the private data */ 191 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 192 if (!data) 193 return -ENOMEM; 194 195 card->dev = dev; 196 dev_set_drvdata(dev, card); 197 snd_soc_card_set_drvdata(card, data); 198 ret = qcom_snd_parse_of(card); 199 if (ret) 200 return ret; 201 202 card->driver_name = of_device_get_match_data(dev); 203 sm8250_add_be_ops(card); 204 return devm_snd_soc_register_card(dev, card); 205 } 206 207 static const struct of_device_id snd_sm8250_dt_match[] = { 208 { .compatible = "fairphone,fp4-sndcard", .data = "sm7225" }, 209 { .compatible = "fairphone,fp5-sndcard", .data = "qcm6490" }, 210 { .compatible = "qcom,qrb2210-sndcard", .data = "qcm2290" }, 211 { .compatible = "qcom,qrb4210-rb2-sndcard", .data = "sm4250" }, 212 { .compatible = "qcom,qrb5165-rb5-sndcard", .data = "sm8250" }, 213 { .compatible = "qcom,sdm660-sndcard", .data = "sdm660" }, 214 { .compatible = "qcom,sm8250-sndcard", .data = "sm8250" }, 215 {} 216 }; 217 218 MODULE_DEVICE_TABLE(of, snd_sm8250_dt_match); 219 220 static struct platform_driver snd_sm8250_driver = { 221 .probe = sm8250_platform_probe, 222 .driver = { 223 .name = "snd-sm8250", 224 .of_match_table = snd_sm8250_dt_match, 225 }, 226 }; 227 module_platform_driver(snd_sm8250_driver); 228 MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org"); 229 MODULE_DESCRIPTION("SM8250 ASoC Machine Driver"); 230 MODULE_LICENSE("GPL"); 231