sc7280.c (9783B)
1// SPDX-License-Identifier: GPL-2.0-only 2// 3// Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. 4// 5// ALSA SoC Machine driver for sc7280 6 7#include <linux/input.h> 8#include <linux/module.h> 9#include <linux/of_device.h> 10#include <linux/platform_device.h> 11#include <sound/core.h> 12#include <sound/jack.h> 13#include <sound/pcm.h> 14#include <sound/soc.h> 15#include <sound/rt5682s.h> 16#include <linux/soundwire/sdw.h> 17 18#include "../codecs/rt5682.h" 19#include "../codecs/rt5682s.h" 20#include "common.h" 21#include "lpass.h" 22 23#define DEFAULT_MCLK_RATE 19200000 24#define RT5682_PLL_FREQ (48000 * 512) 25 26struct sc7280_snd_data { 27 struct snd_soc_card card; 28 struct sdw_stream_runtime *sruntime[LPASS_MAX_PORTS]; 29 u32 pri_mi2s_clk_count; 30 struct snd_soc_jack hs_jack; 31 struct snd_soc_jack hdmi_jack; 32 bool jack_setup; 33 bool stream_prepared[LPASS_MAX_PORTS]; 34}; 35 36static void sc7280_jack_free(struct snd_jack *jack) 37{ 38 struct snd_soc_component *component = jack->private_data; 39 40 snd_soc_component_set_jack(component, NULL, NULL); 41} 42 43static int sc7280_headset_init(struct snd_soc_pcm_runtime *rtd) 44{ 45 struct snd_soc_card *card = rtd->card; 46 struct sc7280_snd_data *pdata = snd_soc_card_get_drvdata(card); 47 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 48 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 49 struct snd_soc_component *component = codec_dai->component; 50 struct snd_jack *jack; 51 int rval, i; 52 53 if (!pdata->jack_setup) { 54 rval = snd_soc_card_jack_new(card, "Headset Jack", 55 SND_JACK_HEADSET | SND_JACK_LINEOUT | 56 SND_JACK_MECHANICAL | 57 SND_JACK_BTN_0 | SND_JACK_BTN_1 | 58 SND_JACK_BTN_2 | SND_JACK_BTN_3 | 59 SND_JACK_BTN_4 | SND_JACK_BTN_5, 60 &pdata->hs_jack); 61 62 if (rval < 0) { 63 dev_err(card->dev, "Unable to add Headset Jack\n"); 64 return rval; 65 } 66 67 jack = pdata->hs_jack.jack; 68 69 snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 70 snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); 71 snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP); 72 snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); 73 74 jack->private_data = component; 75 jack->private_free = sc7280_jack_free; 76 pdata->jack_setup = true; 77 } 78 switch (cpu_dai->id) { 79 case MI2S_PRIMARY: 80 case LPASS_CDC_DMA_RX0: 81 case LPASS_CDC_DMA_TX3: 82 for_each_rtd_codec_dais(rtd, i, codec_dai) { 83 rval = snd_soc_component_set_jack(component, &pdata->hs_jack, NULL); 84 if (rval != 0 && rval != -ENOTSUPP) { 85 dev_err(card->dev, "Failed to set jack: %d\n", rval); 86 return rval; 87 } 88 } 89 break; 90 default: 91 break; 92 } 93 94 return 0; 95} 96 97static int sc7280_hdmi_init(struct snd_soc_pcm_runtime *rtd) 98{ 99 struct snd_soc_card *card = rtd->card; 100 struct sc7280_snd_data *pdata = snd_soc_card_get_drvdata(card); 101 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 102 struct snd_soc_component *component = codec_dai->component; 103 struct snd_jack *jack; 104 int rval; 105 106 rval = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT, 107 &pdata->hdmi_jack); 108 109 if (rval < 0) { 110 dev_err(card->dev, "Unable to add HDMI Jack\n"); 111 return rval; 112 } 113 114 jack = pdata->hdmi_jack.jack; 115 jack->private_data = component; 116 jack->private_free = sc7280_jack_free; 117 118 return snd_soc_component_set_jack(component, &pdata->hdmi_jack, NULL); 119} 120 121static int sc7280_rt5682_init(struct snd_soc_pcm_runtime *rtd) 122{ 123 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 124 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 125 struct snd_soc_card *card = rtd->card; 126 struct sc7280_snd_data *data = snd_soc_card_get_drvdata(card); 127 int ret; 128 129 if (++data->pri_mi2s_clk_count == 1) { 130 snd_soc_dai_set_sysclk(cpu_dai, 131 LPASS_MCLK0, 132 DEFAULT_MCLK_RATE, 133 SNDRV_PCM_STREAM_PLAYBACK); 134 } 135 snd_soc_dai_set_fmt(codec_dai, 136 SND_SOC_DAIFMT_CBC_CFC | 137 SND_SOC_DAIFMT_NB_NF | 138 SND_SOC_DAIFMT_I2S); 139 140 ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL2, RT5682S_PLL_S_MCLK, 141 DEFAULT_MCLK_RATE, RT5682_PLL_FREQ); 142 if (ret) { 143 dev_err(rtd->dev, "can't set codec pll: %d\n", ret); 144 return ret; 145 } 146 147 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL2, 148 RT5682_PLL_FREQ, 149 SND_SOC_CLOCK_IN); 150 151 if (ret) { 152 dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", 153 ret); 154 return ret; 155 } 156 157 return 0; 158} 159 160static int sc7280_init(struct snd_soc_pcm_runtime *rtd) 161{ 162 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 163 164 switch (cpu_dai->id) { 165 case MI2S_PRIMARY: 166 case LPASS_CDC_DMA_TX3: 167 return sc7280_headset_init(rtd); 168 case LPASS_CDC_DMA_RX0: 169 case LPASS_CDC_DMA_VA_TX0: 170 case MI2S_SECONDARY: 171 return 0; 172 case LPASS_DP_RX: 173 return sc7280_hdmi_init(rtd); 174 default: 175 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__, cpu_dai->id); 176 } 177 178 return -EINVAL; 179} 180 181static int sc7280_snd_hw_params(struct snd_pcm_substream *substream, 182 struct snd_pcm_hw_params *params) 183{ 184 struct snd_pcm_runtime *runtime = substream->runtime; 185 struct snd_soc_pcm_runtime *rtd = substream->private_data; 186 struct snd_soc_dai *codec_dai; 187 const struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 188 struct sc7280_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); 189 struct sdw_stream_runtime *sruntime; 190 int i; 191 192 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); 193 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, 48000, 48000); 194 195 switch (cpu_dai->id) { 196 case LPASS_CDC_DMA_TX3: 197 case LPASS_CDC_DMA_RX0: 198 for_each_rtd_codec_dais(rtd, i, codec_dai) { 199 sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream); 200 if (sruntime != ERR_PTR(-ENOTSUPP)) 201 pdata->sruntime[cpu_dai->id] = sruntime; 202 } 203 break; 204 } 205 206 return 0; 207} 208 209static int sc7280_snd_swr_prepare(struct snd_pcm_substream *substream) 210{ 211 struct snd_soc_pcm_runtime *rtd = substream->private_data; 212 const struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 213 struct sc7280_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 214 struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; 215 int ret; 216 217 if (!sruntime) 218 return 0; 219 220 if (data->stream_prepared[cpu_dai->id]) { 221 sdw_disable_stream(sruntime); 222 sdw_deprepare_stream(sruntime); 223 data->stream_prepared[cpu_dai->id] = false; 224 } 225 226 ret = sdw_prepare_stream(sruntime); 227 if (ret) 228 return ret; 229 230 ret = sdw_enable_stream(sruntime); 231 if (ret) { 232 sdw_deprepare_stream(sruntime); 233 return ret; 234 } 235 data->stream_prepared[cpu_dai->id] = true; 236 237 return ret; 238} 239 240static int sc7280_snd_prepare(struct snd_pcm_substream *substream) 241{ 242 struct snd_soc_pcm_runtime *rtd = substream->private_data; 243 const struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 244 245 switch (cpu_dai->id) { 246 case LPASS_CDC_DMA_RX0: 247 case LPASS_CDC_DMA_TX3: 248 return sc7280_snd_swr_prepare(substream); 249 default: 250 break; 251 } 252 253 return 0; 254} 255 256static int sc7280_snd_hw_free(struct snd_pcm_substream *substream) 257{ 258 struct snd_soc_pcm_runtime *rtd = substream->private_data; 259 struct sc7280_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 260 const struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 261 struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; 262 263 switch (cpu_dai->id) { 264 case LPASS_CDC_DMA_RX0: 265 case LPASS_CDC_DMA_TX3: 266 if (sruntime && data->stream_prepared[cpu_dai->id]) { 267 sdw_disable_stream(sruntime); 268 sdw_deprepare_stream(sruntime); 269 data->stream_prepared[cpu_dai->id] = false; 270 } 271 break; 272 default: 273 break; 274 } 275 return 0; 276} 277 278static void sc7280_snd_shutdown(struct snd_pcm_substream *substream) 279{ 280 struct snd_soc_pcm_runtime *rtd = substream->private_data; 281 struct snd_soc_card *card = rtd->card; 282 struct sc7280_snd_data *data = snd_soc_card_get_drvdata(card); 283 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 284 285 switch (cpu_dai->id) { 286 case MI2S_PRIMARY: 287 if (--data->pri_mi2s_clk_count == 0) { 288 snd_soc_dai_set_sysclk(cpu_dai, 289 LPASS_MCLK0, 290 0, 291 SNDRV_PCM_STREAM_PLAYBACK); 292 } 293 break; 294 default: 295 break; 296 } 297} 298 299static int sc7280_snd_startup(struct snd_pcm_substream *substream) 300{ 301 struct snd_soc_pcm_runtime *rtd = substream->private_data; 302 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 303 int ret = 0; 304 305 switch (cpu_dai->id) { 306 case MI2S_PRIMARY: 307 ret = sc7280_rt5682_init(rtd); 308 break; 309 default: 310 break; 311 } 312 return ret; 313} 314 315static const struct snd_soc_ops sc7280_ops = { 316 .startup = sc7280_snd_startup, 317 .hw_params = sc7280_snd_hw_params, 318 .hw_free = sc7280_snd_hw_free, 319 .prepare = sc7280_snd_prepare, 320 .shutdown = sc7280_snd_shutdown, 321}; 322 323static const struct snd_soc_dapm_widget sc7280_snd_widgets[] = { 324 SND_SOC_DAPM_HP("Headphone Jack", NULL), 325 SND_SOC_DAPM_MIC("Headset Mic", NULL), 326}; 327 328static int sc7280_snd_platform_probe(struct platform_device *pdev) 329{ 330 struct snd_soc_card *card; 331 struct sc7280_snd_data *data; 332 struct device *dev = &pdev->dev; 333 struct snd_soc_dai_link *link; 334 int ret, i; 335 336 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 337 if (!data) 338 return -ENOMEM; 339 340 card = &data->card; 341 snd_soc_card_set_drvdata(card, data); 342 343 card->owner = THIS_MODULE; 344 card->driver_name = "SC7280"; 345 card->dev = dev; 346 347 card->dapm_widgets = sc7280_snd_widgets; 348 card->num_dapm_widgets = ARRAY_SIZE(sc7280_snd_widgets); 349 350 ret = qcom_snd_parse_of(card); 351 if (ret) 352 return ret; 353 354 for_each_card_prelinks(card, i, link) { 355 link->init = sc7280_init; 356 link->ops = &sc7280_ops; 357 } 358 359 return devm_snd_soc_register_card(dev, card); 360} 361 362static const struct of_device_id sc7280_snd_device_id[] = { 363 { .compatible = "google,sc7280-herobrine" }, 364 {} 365}; 366MODULE_DEVICE_TABLE(of, sc7280_snd_device_id); 367 368static struct platform_driver sc7280_snd_driver = { 369 .probe = sc7280_snd_platform_probe, 370 .driver = { 371 .name = "msm-snd-sc7280", 372 .of_match_table = sc7280_snd_device_id, 373 .pm = &snd_soc_pm_ops, 374 }, 375}; 376module_platform_driver(sc7280_snd_driver); 377 378MODULE_DESCRIPTION("sc7280 ASoC Machine Driver"); 379MODULE_LICENSE("GPL");