~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/qcom/sdm845.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  4  */
  5 
  6 #include <dt-bindings/sound/qcom,q6afe.h>
  7 #include <linux/module.h>
  8 #include <linux/platform_device.h>
  9 #include <sound/core.h>
 10 #include <sound/pcm.h>
 11 #include <sound/pcm_params.h>
 12 #include <sound/jack.h>
 13 #include <sound/soc.h>
 14 #include <linux/soundwire/sdw.h>
 15 #include <uapi/linux/input-event-codes.h>
 16 #include "common.h"
 17 #include "qdsp6/q6afe.h"
 18 #include "../codecs/rt5663.h"
 19 
 20 #define DRIVER_NAME     "sdm845"
 21 #define DEFAULT_SAMPLE_RATE_48K         48000
 22 #define DEFAULT_MCLK_RATE               24576000
 23 #define TDM_BCLK_RATE           6144000
 24 #define MI2S_BCLK_RATE          1536000
 25 #define LEFT_SPK_TDM_TX_MASK    0x30
 26 #define RIGHT_SPK_TDM_TX_MASK   0xC0
 27 #define SPK_TDM_RX_MASK         0x03
 28 #define NUM_TDM_SLOTS           8
 29 #define SLIM_MAX_TX_PORTS 16
 30 #define SLIM_MAX_RX_PORTS 13
 31 #define WCD934X_DEFAULT_MCLK_RATE       9600000
 32 
 33 struct sdm845_snd_data {
 34         struct snd_soc_jack jack;
 35         bool jack_setup;
 36         bool slim_port_setup;
 37         bool stream_prepared[AFE_PORT_MAX];
 38         struct snd_soc_card *card;
 39         uint32_t pri_mi2s_clk_count;
 40         uint32_t sec_mi2s_clk_count;
 41         uint32_t quat_tdm_clk_count;
 42         struct sdw_stream_runtime *sruntime[AFE_PORT_MAX];
 43 };
 44 
 45 static struct snd_soc_jack_pin sdm845_jack_pins[] = {
 46         {
 47                 .pin = "Headphone Jack",
 48                 .mask = SND_JACK_HEADPHONE,
 49         },
 50         {
 51                 .pin = "Headset Mic",
 52                 .mask = SND_JACK_MICROPHONE,
 53         },
 54 };
 55 
 56 static unsigned int tdm_slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28};
 57 
 58 static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream,
 59                                      struct snd_pcm_hw_params *params)
 60 {
 61         struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 62         struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
 63         struct snd_soc_dai *codec_dai;
 64         struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
 65         u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
 66         struct sdw_stream_runtime *sruntime;
 67         u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
 68         int ret = 0, i;
 69 
 70         for_each_rtd_codec_dais(rtd, i, codec_dai) {
 71                 sruntime = snd_soc_dai_get_stream(codec_dai,
 72                                                   substream->stream);
 73                 if (sruntime != ERR_PTR(-ENOTSUPP))
 74                         pdata->sruntime[cpu_dai->id] = sruntime;
 75 
 76                 ret = snd_soc_dai_get_channel_map(codec_dai,
 77                                 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
 78 
 79                 if (ret != 0 && ret != -ENOTSUPP) {
 80                         pr_err("failed to get codec chan map, err:%d\n", ret);
 81                         return ret;
 82                 } else if (ret == -ENOTSUPP) {
 83                         /* Ignore unsupported */
 84                         continue;
 85                 }
 86 
 87                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 88                         ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
 89                                                           rx_ch_cnt, rx_ch);
 90                 else
 91                         ret = snd_soc_dai_set_channel_map(cpu_dai, tx_ch_cnt,
 92                                                           tx_ch, 0, NULL);
 93         }
 94 
 95         return 0;
 96 }
 97 
 98 static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream,
 99                                         struct snd_pcm_hw_params *params)
100 {
101         struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
102         struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
103         struct snd_soc_dai *codec_dai;
104         int ret = 0, j;
105         int channels, slot_width;
106 
107         switch (params_format(params)) {
108         case SNDRV_PCM_FORMAT_S16_LE:
109                 slot_width = 16;
110                 break;
111         default:
112                 dev_err(rtd->dev, "%s: invalid param format 0x%x\n",
113                                 __func__, params_format(params));
114                 return -EINVAL;
115         }
116 
117         channels = params_channels(params);
118         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
119                 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0x3,
120                                 8, slot_width);
121                 if (ret < 0) {
122                         dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
123                                         __func__, ret);
124                         goto end;
125                 }
126 
127                 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
128                                 channels, tdm_slot_offset);
129                 if (ret < 0) {
130                         dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
131                                         __func__, ret);
132                         goto end;
133                 }
134         } else {
135                 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xf, 0,
136                                 8, slot_width);
137                 if (ret < 0) {
138                         dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
139                                         __func__, ret);
140                         goto end;
141                 }
142 
143                 ret = snd_soc_dai_set_channel_map(cpu_dai, channels,
144                                 tdm_slot_offset, 0, NULL);
145                 if (ret < 0) {
146                         dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
147                                         __func__, ret);
148                         goto end;
149                 }
150         }
151 
152         for_each_rtd_codec_dais(rtd, j, codec_dai) {
153 
154                 if (!strcmp(codec_dai->component->name_prefix, "Left")) {
155                         ret = snd_soc_dai_set_tdm_slot(
156                                         codec_dai, LEFT_SPK_TDM_TX_MASK,
157                                         SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
158                                         slot_width);
159                         if (ret < 0) {
160                                 dev_err(rtd->dev,
161                                         "DEV0 TDM slot err:%d\n", ret);
162                                 return ret;
163                         }
164                 }
165 
166                 if (!strcmp(codec_dai->component->name_prefix, "Right")) {
167                         ret = snd_soc_dai_set_tdm_slot(
168                                         codec_dai, RIGHT_SPK_TDM_TX_MASK,
169                                         SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
170                                         slot_width);
171                         if (ret < 0) {
172                                 dev_err(rtd->dev,
173                                         "DEV1 TDM slot err:%d\n", ret);
174                                 return ret;
175                         }
176                 }
177         }
178 
179 end:
180         return ret;
181 }
182 
183 static int sdm845_snd_hw_params(struct snd_pcm_substream *substream,
184                                         struct snd_pcm_hw_params *params)
185 {
186         struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
187         struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
188         struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
189         int ret = 0;
190 
191         switch (cpu_dai->id) {
192         case PRIMARY_MI2S_RX:
193         case PRIMARY_MI2S_TX:
194                 /*
195                  * Use ASRC for internal clocks, as PLL rate isn't multiple
196                  * of BCLK.
197                  */
198                 rt5663_sel_asrc_clk_src(
199                         codec_dai->component,
200                         RT5663_DA_STEREO_FILTER | RT5663_AD_STEREO_FILTER,
201                         RT5663_CLK_SEL_I2S1_ASRC);
202                 ret = snd_soc_dai_set_sysclk(
203                         codec_dai, RT5663_SCLK_S_MCLK, DEFAULT_MCLK_RATE,
204                         SND_SOC_CLOCK_IN);
205                 if (ret < 0)
206                         dev_err(rtd->dev,
207                                 "snd_soc_dai_set_sysclk err = %d\n", ret);
208                 break;
209         case QUATERNARY_TDM_RX_0:
210         case QUATERNARY_TDM_TX_0:
211                 ret = sdm845_tdm_snd_hw_params(substream, params);
212                 break;
213         case SLIMBUS_0_RX...SLIMBUS_6_TX:
214                 ret = sdm845_slim_snd_hw_params(substream, params);
215                 break;
216         case QUATERNARY_MI2S_RX:
217                 break;
218         default:
219                 pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
220                 break;
221         }
222         return ret;
223 }
224 
225 static void sdm845_jack_free(struct snd_jack *jack)
226 {
227         struct snd_soc_component *component = jack->private_data;
228 
229         snd_soc_component_set_jack(component, NULL, NULL);
230 }
231 
232 static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
233 {
234         struct snd_soc_component *component;
235         struct snd_soc_card *card = rtd->card;
236         struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
237         struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
238         struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(card);
239         struct snd_soc_dai_link *link = rtd->dai_link;
240         struct snd_jack *jack;
241         /*
242          * Codec SLIMBUS configuration
243          * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
244          * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
245          * TX14, TX15, TX16
246          */
247         unsigned int rx_ch[SLIM_MAX_RX_PORTS] = {144, 145, 146, 147, 148, 149,
248                                         150, 151, 152, 153, 154, 155, 156};
249         unsigned int tx_ch[SLIM_MAX_TX_PORTS] = {128, 129, 130, 131, 132, 133,
250                                             134, 135, 136, 137, 138, 139,
251                                             140, 141, 142, 143};
252         int rval, i;
253 
254 
255         if (!pdata->jack_setup) {
256                 rval = snd_soc_card_jack_new_pins(card, "Headset Jack",
257                                                   SND_JACK_HEADSET |
258                                                   SND_JACK_HEADPHONE |
259                                                   SND_JACK_BTN_0 | SND_JACK_BTN_1 |
260                                                   SND_JACK_BTN_2 | SND_JACK_BTN_3,
261                                                   &pdata->jack,
262                                                   sdm845_jack_pins,
263                                                   ARRAY_SIZE(sdm845_jack_pins));
264 
265                 if (rval < 0) {
266                         dev_err(card->dev, "Unable to add Headphone Jack\n");
267                         return rval;
268                 }
269 
270                 jack = pdata->jack.jack;
271 
272                 snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
273                 snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
274                 snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
275                 snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
276                 pdata->jack_setup = true;
277         }
278 
279         switch (cpu_dai->id) {
280         case PRIMARY_MI2S_RX:
281                 jack  = pdata->jack.jack;
282                 component = codec_dai->component;
283 
284                 jack->private_data = component;
285                 jack->private_free = sdm845_jack_free;
286                 rval = snd_soc_component_set_jack(component,
287                                                   &pdata->jack, NULL);
288                 if (rval != 0 && rval != -ENOTSUPP) {
289                         dev_warn(card->dev, "Failed to set jack: %d\n", rval);
290                         return rval;
291                 }
292                 break;
293         case SLIMBUS_0_RX...SLIMBUS_6_TX:
294                 /* setting up wcd multiple times for slim port is redundant */
295                 if (pdata->slim_port_setup || !link->no_pcm)
296                         return 0;
297 
298                 for_each_rtd_codec_dais(rtd, i, codec_dai) {
299                         rval = snd_soc_dai_set_channel_map(codec_dai,
300                                                           ARRAY_SIZE(tx_ch),
301                                                           tx_ch,
302                                                           ARRAY_SIZE(rx_ch),
303                                                           rx_ch);
304                         if (rval != 0 && rval != -ENOTSUPP)
305                                 return rval;
306 
307                         snd_soc_dai_set_sysclk(codec_dai, 0,
308                                                WCD934X_DEFAULT_MCLK_RATE,
309                                                SNDRV_PCM_STREAM_PLAYBACK);
310 
311                         rval = snd_soc_component_set_jack(codec_dai->component,
312                                                           &pdata->jack, NULL);
313                         if (rval != 0 && rval != -ENOTSUPP) {
314                                 dev_warn(card->dev, "Failed to set jack: %d\n", rval);
315                                 return rval;
316                         }
317                 }
318 
319                 pdata->slim_port_setup = true;
320 
321                 break;
322         default:
323                 break;
324         }
325 
326         return 0;
327 }
328 
329 
330 static int sdm845_snd_startup(struct snd_pcm_substream *substream)
331 {
332         unsigned int fmt = SND_SOC_DAIFMT_BP_FP;
333         unsigned int codec_dai_fmt = SND_SOC_DAIFMT_BC_FC;
334         struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
335         struct snd_soc_card *card = rtd->card;
336         struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card);
337         struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
338         struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
339         int j;
340         int ret;
341 
342         switch (cpu_dai->id) {
343         case PRIMARY_MI2S_RX:
344         case PRIMARY_MI2S_TX:
345                 codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF;
346                 if (++(data->pri_mi2s_clk_count) == 1) {
347                         snd_soc_dai_set_sysclk(cpu_dai,
348                                 Q6AFE_LPASS_CLK_ID_MCLK_1,
349                                 DEFAULT_MCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
350                         snd_soc_dai_set_sysclk(cpu_dai,
351                                 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
352                                 MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
353                 }
354                 snd_soc_dai_set_fmt(cpu_dai, fmt);
355                 snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
356                 break;
357 
358         case SECONDARY_MI2S_TX:
359                 codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S;
360                 if (++(data->sec_mi2s_clk_count) == 1) {
361                         snd_soc_dai_set_sysclk(cpu_dai,
362                                 Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
363                                 MI2S_BCLK_RATE, SNDRV_PCM_STREAM_CAPTURE);
364                 }
365                 snd_soc_dai_set_fmt(cpu_dai, fmt);
366                 snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
367                 break;
368         case QUATERNARY_MI2S_RX:
369                 snd_soc_dai_set_sysclk(cpu_dai,
370                         Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT,
371                         MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
372                 snd_soc_dai_set_fmt(cpu_dai, fmt);
373 
374 
375                 break;
376 
377         case QUATERNARY_TDM_RX_0:
378         case QUATERNARY_TDM_TX_0:
379                 if (++(data->quat_tdm_clk_count) == 1) {
380                         snd_soc_dai_set_sysclk(cpu_dai,
381                                 Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT,
382                                 TDM_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
383                 }
384 
385                 codec_dai_fmt |= SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_DSP_B;
386 
387                 for_each_rtd_codec_dais(rtd, j, codec_dai) {
388 
389                         if (!strcmp(codec_dai->component->name_prefix,
390                                     "Left")) {
391                                 ret = snd_soc_dai_set_fmt(
392                                                 codec_dai, codec_dai_fmt);
393                                 if (ret < 0) {
394                                         dev_err(rtd->dev,
395                                                 "Left TDM fmt err:%d\n", ret);
396                                         return ret;
397                                 }
398                         }
399 
400                         if (!strcmp(codec_dai->component->name_prefix,
401                                     "Right")) {
402                                 ret = snd_soc_dai_set_fmt(
403                                                 codec_dai, codec_dai_fmt);
404                                 if (ret < 0) {
405                                         dev_err(rtd->dev,
406                                                 "Right TDM slot err:%d\n", ret);
407                                         return ret;
408                                 }
409                         }
410                 }
411                 break;
412         case SLIMBUS_0_RX...SLIMBUS_6_TX:
413                 break;
414 
415         default:
416                 pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
417                 break;
418         }
419         return 0;
420 }
421 
422 static void  sdm845_snd_shutdown(struct snd_pcm_substream *substream)
423 {
424         struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
425         struct snd_soc_card *card = rtd->card;
426         struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card);
427         struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
428 
429         switch (cpu_dai->id) {
430         case PRIMARY_MI2S_RX:
431         case PRIMARY_MI2S_TX:
432                 if (--(data->pri_mi2s_clk_count) == 0) {
433                         snd_soc_dai_set_sysclk(cpu_dai,
434                                 Q6AFE_LPASS_CLK_ID_MCLK_1,
435                                 0, SNDRV_PCM_STREAM_PLAYBACK);
436                         snd_soc_dai_set_sysclk(cpu_dai,
437                                 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
438                                 0, SNDRV_PCM_STREAM_PLAYBACK);
439                 }
440                 break;
441 
442         case SECONDARY_MI2S_TX:
443                 if (--(data->sec_mi2s_clk_count) == 0) {
444                         snd_soc_dai_set_sysclk(cpu_dai,
445                                 Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
446                                 0, SNDRV_PCM_STREAM_CAPTURE);
447                 }
448                 break;
449 
450         case QUATERNARY_TDM_RX_0:
451         case QUATERNARY_TDM_TX_0:
452                 if (--(data->quat_tdm_clk_count) == 0) {
453                         snd_soc_dai_set_sysclk(cpu_dai,
454                                 Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT,
455                                 0, SNDRV_PCM_STREAM_PLAYBACK);
456                 }
457                 break;
458         case SLIMBUS_0_RX...SLIMBUS_6_TX:
459         case QUATERNARY_MI2S_RX:
460                 break;
461 
462         default:
463                 pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
464                 break;
465         }
466 }
467 
468 static int sdm845_snd_prepare(struct snd_pcm_substream *substream)
469 {
470         struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
471         struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
472         struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
473         struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
474         int ret;
475 
476         if (!sruntime)
477                 return 0;
478 
479         if (data->stream_prepared[cpu_dai->id]) {
480                 sdw_disable_stream(sruntime);
481                 sdw_deprepare_stream(sruntime);
482                 data->stream_prepared[cpu_dai->id] = false;
483         }
484 
485         ret = sdw_prepare_stream(sruntime);
486         if (ret)
487                 return ret;
488 
489         /**
490          * NOTE: there is a strict hw requirement about the ordering of port
491          * enables and actual WSA881x PA enable. PA enable should only happen
492          * after soundwire ports are enabled if not DC on the line is
493          * accumulated resulting in Click/Pop Noise
494          * PA enable/mute are handled as part of codec DAPM and digital mute.
495          */
496 
497         ret = sdw_enable_stream(sruntime);
498         if (ret) {
499                 sdw_deprepare_stream(sruntime);
500                 return ret;
501         }
502         data->stream_prepared[cpu_dai->id] = true;
503 
504         return ret;
505 }
506 
507 static int sdm845_snd_hw_free(struct snd_pcm_substream *substream)
508 {
509         struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
510         struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
511         struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
512         struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
513 
514         if (sruntime && data->stream_prepared[cpu_dai->id]) {
515                 sdw_disable_stream(sruntime);
516                 sdw_deprepare_stream(sruntime);
517                 data->stream_prepared[cpu_dai->id] = false;
518         }
519 
520         return 0;
521 }
522 
523 static const struct snd_soc_ops sdm845_be_ops = {
524         .hw_params = sdm845_snd_hw_params,
525         .hw_free = sdm845_snd_hw_free,
526         .prepare = sdm845_snd_prepare,
527         .startup = sdm845_snd_startup,
528         .shutdown = sdm845_snd_shutdown,
529 };
530 
531 static int sdm845_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
532                                 struct snd_pcm_hw_params *params)
533 {
534         struct snd_interval *rate = hw_param_interval(params,
535                                         SNDRV_PCM_HW_PARAM_RATE);
536         struct snd_interval *channels = hw_param_interval(params,
537                                         SNDRV_PCM_HW_PARAM_CHANNELS);
538         struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
539 
540         rate->min = rate->max = DEFAULT_SAMPLE_RATE_48K;
541         channels->min = channels->max = 2;
542         snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
543 
544         return 0;
545 }
546 
547 static const struct snd_soc_dapm_widget sdm845_snd_widgets[] = {
548         SND_SOC_DAPM_HP("Headphone Jack", NULL),
549         SND_SOC_DAPM_MIC("Headset Mic", NULL),
550         SND_SOC_DAPM_SPK("Left Spk", NULL),
551         SND_SOC_DAPM_SPK("Right Spk", NULL),
552         SND_SOC_DAPM_MIC("Int Mic", NULL),
553 };
554 
555 static const struct snd_kcontrol_new sdm845_snd_controls[] = {
556         SOC_DAPM_PIN_SWITCH("Headphone Jack"),
557         SOC_DAPM_PIN_SWITCH("Headset Mic"),
558 };
559 
560 static void sdm845_add_ops(struct snd_soc_card *card)
561 {
562         struct snd_soc_dai_link *link;
563         int i;
564 
565         for_each_card_prelinks(card, i, link) {
566                 if (link->no_pcm == 1) {
567                         link->ops = &sdm845_be_ops;
568                         link->be_hw_params_fixup = sdm845_be_hw_params_fixup;
569                 }
570                 link->init = sdm845_dai_init;
571         }
572 }
573 
574 static int sdm845_snd_platform_probe(struct platform_device *pdev)
575 {
576         struct snd_soc_card *card;
577         struct sdm845_snd_data *data;
578         struct device *dev = &pdev->dev;
579         int ret;
580 
581         card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
582         if (!card)
583                 return -ENOMEM;
584 
585         /* Allocate the private data */
586         data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
587         if (!data)
588                 return -ENOMEM;
589 
590         card->driver_name = DRIVER_NAME;
591         card->dapm_widgets = sdm845_snd_widgets;
592         card->num_dapm_widgets = ARRAY_SIZE(sdm845_snd_widgets);
593         card->controls = sdm845_snd_controls;
594         card->num_controls = ARRAY_SIZE(sdm845_snd_controls);
595         card->dev = dev;
596         card->owner = THIS_MODULE;
597         dev_set_drvdata(dev, card);
598         ret = qcom_snd_parse_of(card);
599         if (ret)
600                 return ret;
601 
602         data->card = card;
603         snd_soc_card_set_drvdata(card, data);
604 
605         sdm845_add_ops(card);
606         return devm_snd_soc_register_card(dev, card);
607 }
608 
609 static const struct of_device_id sdm845_snd_device_id[]  = {
610         { .compatible = "qcom,sdm845-sndcard" },
611         /* Do not grow the list for compatible devices */
612         { .compatible = "qcom,db845c-sndcard" },
613         { .compatible = "lenovo,yoga-c630-sndcard" },
614         {},
615 };
616 MODULE_DEVICE_TABLE(of, sdm845_snd_device_id);
617 
618 static struct platform_driver sdm845_snd_driver = {
619         .probe = sdm845_snd_platform_probe,
620         .driver = {
621                 .name = "msm-snd-sdm845",
622                 .of_match_table = sdm845_snd_device_id,
623         },
624 };
625 module_platform_driver(sdm845_snd_driver);
626 
627 MODULE_DESCRIPTION("sdm845 ASoC Machine Driver");
628 MODULE_LICENSE("GPL");
629 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php