1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2022, Linaro Limited 3 4 #include <linux/module.h> 5 #include <linux/platform_device.h> 6 #include <linux/of_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 "sc8280xp" 18 19 struct sc8280xp_snd_data { 20 bool stream_prepared[AFE_PORT_MAX]; 21 struct snd_soc_card *card; 22 struct sdw_stream_runtime *sruntime[AFE_PORT_MAX]; 23 struct snd_soc_jack jack; 24 bool jack_setup; 25 }; 26 27 static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd) 28 { 29 struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 30 31 return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup); 32 } 33 34 static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 35 struct snd_pcm_hw_params *params) 36 { 37 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 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 = 2; 45 channels->max = 2; 46 switch (cpu_dai->id) { 47 case TX_CODEC_DMA_TX_0: 48 case TX_CODEC_DMA_TX_1: 49 case TX_CODEC_DMA_TX_2: 50 case TX_CODEC_DMA_TX_3: 51 channels->min = 1; 52 break; 53 default: 54 break; 55 } 56 57 58 return 0; 59 } 60 61 static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream, 62 struct snd_pcm_hw_params *params) 63 { 64 struct snd_soc_pcm_runtime *rtd = substream->private_data; 65 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 66 struct sc8280xp_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); 67 68 return qcom_snd_sdw_hw_params(substream, params, &pdata->sruntime[cpu_dai->id]); 69 } 70 71 static int sc8280xp_snd_prepare(struct snd_pcm_substream *substream) 72 { 73 struct snd_soc_pcm_runtime *rtd = substream->private_data; 74 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 75 struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 76 struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; 77 78 return qcom_snd_sdw_prepare(substream, sruntime, 79 &data->stream_prepared[cpu_dai->id]); 80 } 81 82 static int sc8280xp_snd_hw_free(struct snd_pcm_substream *substream) 83 { 84 struct snd_soc_pcm_runtime *rtd = substream->private_data; 85 struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 86 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 87 struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; 88 89 return qcom_snd_sdw_hw_free(substream, sruntime, 90 &data->stream_prepared[cpu_dai->id]); 91 } 92 93 static const struct snd_soc_ops sc8280xp_be_ops = { 94 .hw_params = sc8280xp_snd_hw_params, 95 .hw_free = sc8280xp_snd_hw_free, 96 .prepare = sc8280xp_snd_prepare, 97 }; 98 99 static void sc8280xp_add_be_ops(struct snd_soc_card *card) 100 { 101 struct snd_soc_dai_link *link; 102 int i; 103 104 for_each_card_prelinks(card, i, link) { 105 if (link->no_pcm == 1) { 106 link->init = sc8280xp_snd_init; 107 link->be_hw_params_fixup = sc8280xp_be_hw_params_fixup; 108 link->ops = &sc8280xp_be_ops; 109 } 110 } 111 } 112 113 static int sc8280xp_platform_probe(struct platform_device *pdev) 114 { 115 struct snd_soc_card *card; 116 struct sc8280xp_snd_data *data; 117 struct device *dev = &pdev->dev; 118 int ret; 119 120 card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); 121 if (!card) 122 return -ENOMEM; 123 card->owner = THIS_MODULE; 124 /* Allocate the private data */ 125 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 126 if (!data) 127 return -ENOMEM; 128 129 card->dev = dev; 130 dev_set_drvdata(dev, card); 131 snd_soc_card_set_drvdata(card, data); 132 ret = qcom_snd_parse_of(card); 133 if (ret) 134 return ret; 135 136 card->driver_name = DRIVER_NAME; 137 sc8280xp_add_be_ops(card); 138 return devm_snd_soc_register_card(dev, card); 139 } 140 141 static const struct of_device_id snd_sc8280xp_dt_match[] = { 142 {.compatible = "qcom,sc8280xp-sndcard",}, 143 {} 144 }; 145 146 MODULE_DEVICE_TABLE(of, snd_sc8280xp_dt_match); 147 148 static struct platform_driver snd_sc8280xp_driver = { 149 .probe = sc8280xp_platform_probe, 150 .driver = { 151 .name = "snd-sc8280xp", 152 .of_match_table = snd_sc8280xp_dt_match, 153 }, 154 }; 155 module_platform_driver(snd_sc8280xp_driver); 156 MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org"); 157 MODULE_DESCRIPTION("SC8280XP ASoC Machine Driver"); 158 MODULE_LICENSE("GPL v2"); 159