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

TOMOYO Linux Cross Reference
Linux/sound/soc/intel/skylake/skl-pcm.c

Version: ~ [ linux-5.12-rc7 ] ~ [ linux-5.11.13 ] ~ [ linux-5.10.29 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.111 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.186 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.230 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.266 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.266 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ 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.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  skl-pcm.c -ASoC HDA Platform driver file implementing PCM functionality
  3  *
  4  *  Copyright (C) 2014-2015 Intel Corp
  5  *  Author:  Jeeja KP <jeeja.kp@intel.com>
  6  *
  7  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  8  *
  9  *  This program is free software; you can redistribute it and/or modify
 10  *  it under the terms of the GNU General Public License as published by
 11  *  the Free Software Foundation; version 2 of the License.
 12  *
 13  *  This program is distributed in the hope that it will be useful, but
 14  *  WITHOUT ANY WARRANTY; without even the implied warranty of
 15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16  *  General Public License for more details.
 17  *
 18  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 19  *
 20  */
 21 
 22 #include <linux/pci.h>
 23 #include <linux/pm_runtime.h>
 24 #include <sound/pcm_params.h>
 25 #include <sound/soc.h>
 26 #include "skl.h"
 27 
 28 #define HDA_MONO 1
 29 #define HDA_STEREO 2
 30 
 31 static struct snd_pcm_hardware azx_pcm_hw = {
 32         .info =                 (SNDRV_PCM_INFO_MMAP |
 33                                  SNDRV_PCM_INFO_INTERLEAVED |
 34                                  SNDRV_PCM_INFO_BLOCK_TRANSFER |
 35                                  SNDRV_PCM_INFO_MMAP_VALID |
 36                                  SNDRV_PCM_INFO_PAUSE |
 37                                  SNDRV_PCM_INFO_SYNC_START |
 38                                  SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */
 39                                  SNDRV_PCM_INFO_HAS_LINK_ATIME |
 40                                  SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
 41         .formats =              SNDRV_PCM_FMTBIT_S16_LE,
 42         .rates =                SNDRV_PCM_RATE_48000,
 43         .rate_min =             48000,
 44         .rate_max =             48000,
 45         .channels_min =         2,
 46         .channels_max =         2,
 47         .buffer_bytes_max =     AZX_MAX_BUF_SIZE,
 48         .period_bytes_min =     128,
 49         .period_bytes_max =     AZX_MAX_BUF_SIZE / 2,
 50         .periods_min =          2,
 51         .periods_max =          AZX_MAX_FRAG,
 52         .fifo_size =            0,
 53 };
 54 
 55 static inline
 56 struct hdac_ext_stream *get_hdac_ext_stream(struct snd_pcm_substream *substream)
 57 {
 58         return substream->runtime->private_data;
 59 }
 60 
 61 static struct hdac_ext_bus *get_bus_ctx(struct snd_pcm_substream *substream)
 62 {
 63         struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
 64         struct hdac_stream *hstream = hdac_stream(stream);
 65         struct hdac_bus *bus = hstream->bus;
 66 
 67         return hbus_to_ebus(bus);
 68 }
 69 
 70 static int skl_substream_alloc_pages(struct hdac_ext_bus *ebus,
 71                                  struct snd_pcm_substream *substream,
 72                                  size_t size)
 73 {
 74         struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
 75 
 76         hdac_stream(stream)->bufsize = 0;
 77         hdac_stream(stream)->period_bytes = 0;
 78         hdac_stream(stream)->format_val = 0;
 79 
 80         return snd_pcm_lib_malloc_pages(substream, size);
 81 }
 82 
 83 static int skl_substream_free_pages(struct hdac_bus *bus,
 84                                 struct snd_pcm_substream *substream)
 85 {
 86         return snd_pcm_lib_free_pages(substream);
 87 }
 88 
 89 static void skl_set_pcm_constrains(struct hdac_ext_bus *ebus,
 90                                  struct snd_pcm_runtime *runtime)
 91 {
 92         snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
 93 
 94         /* avoid wrap-around with wall-clock */
 95         snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME,
 96                                      20, 178000000);
 97 }
 98 
 99 static enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_ext_bus *ebus)
100 {
101         if (ebus->ppcap)
102                 return HDAC_EXT_STREAM_TYPE_HOST;
103         else
104                 return HDAC_EXT_STREAM_TYPE_COUPLED;
105 }
106 
107 static int skl_pcm_open(struct snd_pcm_substream *substream,
108                 struct snd_soc_dai *dai)
109 {
110         struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
111         struct hdac_ext_stream *stream;
112         struct snd_pcm_runtime *runtime = substream->runtime;
113         struct skl_dma_params *dma_params;
114         int ret;
115 
116         dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
117         ret = pm_runtime_get_sync(dai->dev);
118         if (ret)
119                 return ret;
120 
121         stream = snd_hdac_ext_stream_assign(ebus, substream,
122                                         skl_get_host_stream_type(ebus));
123         if (stream == NULL)
124                 return -EBUSY;
125 
126         skl_set_pcm_constrains(ebus, runtime);
127 
128         /*
129          * disable WALLCLOCK timestamps for capture streams
130          * until we figure out how to handle digital inputs
131          */
132         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
133                 runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK; /* legacy */
134                 runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_LINK_ATIME;
135         }
136 
137         runtime->private_data = stream;
138 
139         dma_params = kzalloc(sizeof(*dma_params), GFP_KERNEL);
140         if (!dma_params)
141                 return -ENOMEM;
142 
143         dma_params->stream_tag = hdac_stream(stream)->stream_tag;
144         snd_soc_dai_set_dma_data(dai, substream, dma_params);
145 
146         dev_dbg(dai->dev, "stream tag set in dma params=%d\n",
147                                  dma_params->stream_tag);
148         snd_pcm_set_sync(substream);
149 
150         return 0;
151 }
152 
153 static int skl_get_format(struct snd_pcm_substream *substream,
154                 struct snd_soc_dai *dai)
155 {
156         struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
157         struct skl_dma_params *dma_params;
158         struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
159         int format_val = 0;
160 
161         if (ebus->ppcap) {
162                 struct snd_pcm_runtime *runtime = substream->runtime;
163 
164                 format_val = snd_hdac_calc_stream_format(runtime->rate,
165                                                 runtime->channels,
166                                                 runtime->format,
167                                                 32, 0);
168         } else {
169                 struct snd_soc_dai *codec_dai = rtd->codec_dai;
170 
171                 dma_params = snd_soc_dai_get_dma_data(codec_dai, substream);
172                 if (dma_params)
173                         format_val = dma_params->format;
174         }
175 
176         return format_val;
177 }
178 
179 static int skl_pcm_prepare(struct snd_pcm_substream *substream,
180                 struct snd_soc_dai *dai)
181 {
182         struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
183         unsigned int format_val;
184         int err;
185 
186         dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
187         if (hdac_stream(stream)->prepared) {
188                 dev_dbg(dai->dev, "already stream is prepared - returning\n");
189                 return 0;
190         }
191 
192         format_val = skl_get_format(substream, dai);
193         dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d\n",
194                                 hdac_stream(stream)->stream_tag, format_val);
195         snd_hdac_stream_reset(hdac_stream(stream));
196 
197         err = snd_hdac_stream_set_params(hdac_stream(stream), format_val);
198         if (err < 0)
199                 return err;
200 
201         err = snd_hdac_stream_setup(hdac_stream(stream));
202         if (err < 0)
203                 return err;
204 
205         hdac_stream(stream)->prepared = 1;
206 
207         return err;
208 }
209 
210 static int skl_pcm_hw_params(struct snd_pcm_substream *substream,
211                                 struct snd_pcm_hw_params *params,
212                                 struct snd_soc_dai *dai)
213 {
214         struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
215         struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
216         struct snd_pcm_runtime *runtime = substream->runtime;
217         int ret, dma_id;
218 
219         dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
220         ret = skl_substream_alloc_pages(ebus, substream,
221                                           params_buffer_bytes(params));
222         if (ret < 0)
223                 return ret;
224 
225         dev_dbg(dai->dev, "format_val, rate=%d, ch=%d, format=%d\n",
226                         runtime->rate, runtime->channels, runtime->format);
227 
228         dma_id = hdac_stream(stream)->stream_tag - 1;
229         dev_dbg(dai->dev, "dma_id=%d\n", dma_id);
230 
231         return 0;
232 }
233 
234 static void skl_pcm_close(struct snd_pcm_substream *substream,
235                 struct snd_soc_dai *dai)
236 {
237         struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
238         struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
239         struct skl_dma_params *dma_params = NULL;
240 
241         dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
242 
243         snd_hdac_ext_stream_release(stream, skl_get_host_stream_type(ebus));
244 
245         dma_params = snd_soc_dai_get_dma_data(dai, substream);
246         /*
247          * now we should set this to NULL as we are freeing by the
248          * dma_params
249          */
250         snd_soc_dai_set_dma_data(dai, substream, NULL);
251 
252         pm_runtime_mark_last_busy(dai->dev);
253         pm_runtime_put_autosuspend(dai->dev);
254         kfree(dma_params);
255 }
256 
257 static int skl_pcm_hw_free(struct snd_pcm_substream *substream,
258                 struct snd_soc_dai *dai)
259 {
260         struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
261         struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
262 
263         dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
264 
265         snd_hdac_stream_cleanup(hdac_stream(stream));
266         hdac_stream(stream)->prepared = 0;
267 
268         return skl_substream_free_pages(ebus_to_hbus(ebus), substream);
269 }
270 
271 static int skl_link_hw_params(struct snd_pcm_substream *substream,
272                                 struct snd_pcm_hw_params *params,
273                                 struct snd_soc_dai *dai)
274 {
275         struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
276         struct hdac_ext_stream *link_dev;
277         struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
278         struct skl_dma_params *dma_params;
279         struct snd_soc_dai *codec_dai = rtd->codec_dai;
280         int dma_id;
281 
282         pr_debug("%s\n", __func__);
283         link_dev = snd_hdac_ext_stream_assign(ebus, substream,
284                                         HDAC_EXT_STREAM_TYPE_LINK);
285         if (!link_dev)
286                 return -EBUSY;
287 
288         snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
289 
290         /* set the stream tag in the codec dai dma params  */
291         dma_params = (struct skl_dma_params *)
292                         snd_soc_dai_get_dma_data(codec_dai, substream);
293         if (dma_params)
294                 dma_params->stream_tag =  hdac_stream(link_dev)->stream_tag;
295         snd_soc_dai_set_dma_data(codec_dai, substream, (void *)dma_params);
296         dma_id = hdac_stream(link_dev)->stream_tag - 1;
297 
298         return 0;
299 }
300 
301 static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
302                 struct snd_soc_dai *dai)
303 {
304         struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
305         struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
306         struct hdac_ext_stream *link_dev =
307                         snd_soc_dai_get_dma_data(dai, substream);
308         unsigned int format_val = 0;
309         struct skl_dma_params *dma_params;
310         struct snd_soc_dai *codec_dai = rtd->codec_dai;
311         struct snd_pcm_hw_params *params;
312         struct snd_interval *channels, *rate;
313         struct hdac_ext_link *link;
314 
315         dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
316         if (link_dev->link_prepared) {
317                 dev_dbg(dai->dev, "already stream is prepared - returning\n");
318                 return 0;
319         }
320         params  = devm_kzalloc(dai->dev, sizeof(*params), GFP_KERNEL);
321         if (params == NULL)
322                 return -ENOMEM;
323 
324         channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
325         channels->min = channels->max = substream->runtime->channels;
326         rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
327         rate->min = rate->max = substream->runtime->rate;
328         snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
329                                         SNDRV_PCM_HW_PARAM_FIRST_MASK],
330                                         substream->runtime->format);
331 
332 
333         dma_params  = (struct skl_dma_params *)
334                         snd_soc_dai_get_dma_data(codec_dai, substream);
335         if (dma_params)
336                 format_val = dma_params->format;
337         dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d codec_dai_name=%s\n",
338                         hdac_stream(link_dev)->stream_tag, format_val, codec_dai->name);
339 
340         snd_hdac_ext_link_stream_reset(link_dev);
341 
342         snd_hdac_ext_link_stream_setup(link_dev, format_val);
343 
344         link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name);
345         if (!link)
346                 return -EINVAL;
347 
348         snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_dev)->stream_tag);
349         link_dev->link_prepared = 1;
350 
351         return 0;
352 }
353 
354 static int skl_link_pcm_trigger(struct snd_pcm_substream *substream,
355         int cmd, struct snd_soc_dai *dai)
356 {
357         struct hdac_ext_stream *link_dev =
358                                 snd_soc_dai_get_dma_data(dai, substream);
359 
360         dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd);
361         switch (cmd) {
362         case SNDRV_PCM_TRIGGER_START:
363         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
364         case SNDRV_PCM_TRIGGER_RESUME:
365                 snd_hdac_ext_link_stream_start(link_dev);
366                 break;
367 
368         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
369         case SNDRV_PCM_TRIGGER_SUSPEND:
370         case SNDRV_PCM_TRIGGER_STOP:
371                 snd_hdac_ext_link_stream_clear(link_dev);
372                 break;
373 
374         default:
375                 return -EINVAL;
376         }
377         return 0;
378 }
379 
380 static int skl_link_hw_free(struct snd_pcm_substream *substream,
381                 struct snd_soc_dai *dai)
382 {
383         struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
384         struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
385         struct hdac_ext_stream *link_dev =
386                                 snd_soc_dai_get_dma_data(dai, substream);
387         struct hdac_ext_link *link;
388 
389         dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
390 
391         link_dev->link_prepared = 0;
392 
393         link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name);
394         if (!link)
395                 return -EINVAL;
396 
397         snd_hdac_ext_link_clear_stream_id(link, hdac_stream(link_dev)->stream_tag);
398         snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK);
399         return 0;
400 }
401 
402 static int skl_hda_be_startup(struct snd_pcm_substream *substream,
403                 struct snd_soc_dai *dai)
404 {
405         return pm_runtime_get_sync(dai->dev);
406 }
407 
408 static void skl_hda_be_shutdown(struct snd_pcm_substream *substream,
409                 struct snd_soc_dai *dai)
410 {
411         pm_runtime_mark_last_busy(dai->dev);
412         pm_runtime_put_autosuspend(dai->dev);
413 }
414 
415 static struct snd_soc_dai_ops skl_pcm_dai_ops = {
416         .startup = skl_pcm_open,
417         .shutdown = skl_pcm_close,
418         .prepare = skl_pcm_prepare,
419         .hw_params = skl_pcm_hw_params,
420         .hw_free = skl_pcm_hw_free,
421 };
422 
423 static struct snd_soc_dai_ops skl_dmic_dai_ops = {
424         .startup = skl_hda_be_startup,
425         .shutdown = skl_hda_be_shutdown,
426 };
427 
428 static struct snd_soc_dai_ops skl_link_dai_ops = {
429         .startup = skl_hda_be_startup,
430         .prepare = skl_link_pcm_prepare,
431         .hw_params = skl_link_hw_params,
432         .hw_free = skl_link_hw_free,
433         .trigger = skl_link_pcm_trigger,
434         .shutdown = skl_hda_be_shutdown,
435 };
436 
437 static struct snd_soc_dai_driver skl_platform_dai[] = {
438 {
439         .name = "System Pin",
440         .ops = &skl_pcm_dai_ops,
441         .playback = {
442                 .stream_name = "System Playback",
443                 .channels_min = HDA_MONO,
444                 .channels_max = HDA_STEREO,
445                 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_8000,
446                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
447         },
448         .capture = {
449                 .stream_name = "System Capture",
450                 .channels_min = HDA_MONO,
451                 .channels_max = HDA_STEREO,
452                 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
453                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
454         },
455 },
456 {
457         .name = "Reference Pin",
458         .ops = &skl_pcm_dai_ops,
459         .capture = {
460                 .stream_name = "Reference Capture",
461                 .channels_min = HDA_MONO,
462                 .channels_max = HDA_STEREO,
463                 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
464                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
465         },
466 },
467 {
468         .name = "Deepbuffer Pin",
469         .ops = &skl_pcm_dai_ops,
470         .playback = {
471                 .stream_name = "Deepbuffer Playback",
472                 .channels_min = HDA_STEREO,
473                 .channels_max = HDA_STEREO,
474                 .rates = SNDRV_PCM_RATE_48000,
475                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
476         },
477 },
478 {
479         .name = "LowLatency Pin",
480         .ops = &skl_pcm_dai_ops,
481         .playback = {
482                 .stream_name = "Low Latency Playback",
483                 .channels_min = HDA_STEREO,
484                 .channels_max = HDA_STEREO,
485                 .rates = SNDRV_PCM_RATE_48000,
486                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
487         },
488 },
489 /* BE CPU  Dais */
490 {
491         .name = "iDisp Pin",
492         .ops = &skl_link_dai_ops,
493         .playback = {
494                 .stream_name = "iDisp Tx",
495                 .channels_min = HDA_STEREO,
496                 .channels_max = HDA_STEREO,
497                 .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
498                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
499         },
500 },
501 {
502         .name = "DMIC01 Pin",
503         .ops = &skl_dmic_dai_ops,
504         .capture = {
505                 .stream_name = "DMIC01 Rx",
506                 .channels_min = HDA_STEREO,
507                 .channels_max = HDA_STEREO,
508                 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
509                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
510         },
511 },
512 {
513         .name = "DMIC23 Pin",
514         .ops = &skl_dmic_dai_ops,
515         .capture = {
516                 .stream_name = "DMIC23 Rx",
517                 .channels_min = HDA_STEREO,
518                 .channels_max = HDA_STEREO,
519                 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
520                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
521         },
522 },
523 {
524         .name = "HD-Codec Pin",
525         .ops = &skl_link_dai_ops,
526         .playback = {
527                 .stream_name = "HD-Codec Tx",
528                 .channels_min = HDA_STEREO,
529                 .channels_max = HDA_STEREO,
530                 .rates = SNDRV_PCM_RATE_48000,
531                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
532         },
533         .capture = {
534                 .stream_name = "HD-Codec Rx",
535                 .channels_min = HDA_STEREO,
536                 .channels_max = HDA_STEREO,
537                 .rates = SNDRV_PCM_RATE_48000,
538                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
539         },
540 },
541 {
542         .name = "HD-Codec-SPK Pin",
543         .ops = &skl_link_dai_ops,
544         .playback = {
545                 .stream_name = "HD-Codec-SPK Tx",
546                 .channels_min = HDA_STEREO,
547                 .channels_max = HDA_STEREO,
548                 .rates = SNDRV_PCM_RATE_48000,
549                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
550         },
551 },
552 {
553         .name = "HD-Codec-AMIC Pin",
554         .ops = &skl_link_dai_ops,
555         .capture = {
556                 .stream_name = "HD-Codec-AMIC Rx",
557                 .channels_min = HDA_STEREO,
558                 .channels_max = HDA_STEREO,
559                 .rates = SNDRV_PCM_RATE_48000,
560                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
561         },
562 },
563 };
564 
565 static int skl_platform_open(struct snd_pcm_substream *substream)
566 {
567         struct snd_pcm_runtime *runtime;
568         struct snd_soc_pcm_runtime *rtd = substream->private_data;
569         struct snd_soc_dai_link *dai_link = rtd->dai_link;
570 
571         dev_dbg(rtd->cpu_dai->dev, "In %s:%s\n", __func__,
572                                         dai_link->cpu_dai_name);
573 
574         runtime = substream->runtime;
575         snd_soc_set_runtime_hwparams(substream, &azx_pcm_hw);
576 
577         return 0;
578 }
579 
580 static int skl_pcm_trigger(struct snd_pcm_substream *substream,
581                                         int cmd)
582 {
583         struct hdac_ext_bus *ebus = get_bus_ctx(substream);
584         struct hdac_bus *bus = ebus_to_hbus(ebus);
585         struct hdac_ext_stream *stream;
586         struct snd_pcm_substream *s;
587         bool start;
588         int sbits = 0;
589         unsigned long cookie;
590         struct hdac_stream *hstr;
591 
592         stream = get_hdac_ext_stream(substream);
593         hstr = hdac_stream(stream);
594 
595         dev_dbg(bus->dev, "In %s cmd=%d\n", __func__, cmd);
596 
597         if (!hstr->prepared)
598                 return -EPIPE;
599 
600         switch (cmd) {
601         case SNDRV_PCM_TRIGGER_START:
602         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
603         case SNDRV_PCM_TRIGGER_RESUME:
604                 start = true;
605                 break;
606 
607         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
608         case SNDRV_PCM_TRIGGER_SUSPEND:
609         case SNDRV_PCM_TRIGGER_STOP:
610                 start = false;
611                 break;
612 
613         default:
614                 return -EINVAL;
615         }
616 
617         snd_pcm_group_for_each_entry(s, substream) {
618                 if (s->pcm->card != substream->pcm->card)
619                         continue;
620                 stream = get_hdac_ext_stream(s);
621                 sbits |= 1 << hdac_stream(stream)->index;
622                 snd_pcm_trigger_done(s, substream);
623         }
624 
625         spin_lock_irqsave(&bus->reg_lock, cookie);
626 
627         /* first, set SYNC bits of corresponding streams */
628         snd_hdac_stream_sync_trigger(hstr, true, sbits, AZX_REG_SSYNC);
629 
630         snd_pcm_group_for_each_entry(s, substream) {
631                 if (s->pcm->card != substream->pcm->card)
632                         continue;
633                 stream = get_hdac_ext_stream(s);
634                 if (start)
635                         snd_hdac_stream_start(hdac_stream(stream), true);
636                 else
637                         snd_hdac_stream_stop(hdac_stream(stream));
638         }
639         spin_unlock_irqrestore(&bus->reg_lock, cookie);
640 
641         snd_hdac_stream_sync(hstr, start, sbits);
642 
643         spin_lock_irqsave(&bus->reg_lock, cookie);
644 
645         /* reset SYNC bits */
646         snd_hdac_stream_sync_trigger(hstr, false, sbits, AZX_REG_SSYNC);
647         if (start)
648                 snd_hdac_stream_timecounter_init(hstr, sbits);
649         spin_unlock_irqrestore(&bus->reg_lock, cookie);
650 
651         return 0;
652 }
653 
654 static int skl_dsp_trigger(struct snd_pcm_substream *substream,
655                 int cmd)
656 {
657         struct hdac_ext_bus *ebus = get_bus_ctx(substream);
658         struct hdac_bus *bus = ebus_to_hbus(ebus);
659         struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
660         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
661         struct hdac_ext_stream *stream;
662         int start;
663         unsigned long cookie;
664         struct hdac_stream *hstr;
665 
666         dev_dbg(bus->dev, "In %s cmd=%d streamname=%s\n", __func__, cmd, cpu_dai->name);
667 
668         stream = get_hdac_ext_stream(substream);
669         hstr = hdac_stream(stream);
670 
671         if (!hstr->prepared)
672                 return -EPIPE;
673 
674         switch (cmd) {
675         case SNDRV_PCM_TRIGGER_START:
676         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
677         case SNDRV_PCM_TRIGGER_RESUME:
678                 start = 1;
679                 break;
680 
681         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
682         case SNDRV_PCM_TRIGGER_SUSPEND:
683         case SNDRV_PCM_TRIGGER_STOP:
684                 start = 0;
685                 break;
686 
687         default:
688                 return -EINVAL;
689         }
690 
691         spin_lock_irqsave(&bus->reg_lock, cookie);
692 
693         if (start)
694                 snd_hdac_stream_start(hdac_stream(stream), true);
695         else
696                 snd_hdac_stream_stop(hdac_stream(stream));
697 
698         if (start)
699                 snd_hdac_stream_timecounter_init(hstr, 0);
700 
701         spin_unlock_irqrestore(&bus->reg_lock, cookie);
702 
703         return 0;
704 }
705 static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream,
706                                         int cmd)
707 {
708         struct hdac_ext_bus *ebus = get_bus_ctx(substream);
709 
710         if (ebus->ppcap)
711                 return skl_dsp_trigger(substream, cmd);
712         else
713                 return skl_pcm_trigger(substream, cmd);
714 }
715 
716 /* calculate runtime delay from LPIB */
717 static int skl_get_delay_from_lpib(struct hdac_ext_bus *ebus,
718                                 struct hdac_ext_stream *sstream,
719                                 unsigned int pos)
720 {
721         struct hdac_bus *bus = ebus_to_hbus(ebus);
722         struct hdac_stream *hstream = hdac_stream(sstream);
723         struct snd_pcm_substream *substream = hstream->substream;
724         int stream = substream->stream;
725         unsigned int lpib_pos = snd_hdac_stream_get_pos_lpib(hstream);
726         int delay;
727 
728         if (stream == SNDRV_PCM_STREAM_PLAYBACK)
729                 delay = pos - lpib_pos;
730         else
731                 delay = lpib_pos - pos;
732 
733         if (delay < 0) {
734                 if (delay >= hstream->delay_negative_threshold)
735                         delay = 0;
736                 else
737                         delay += hstream->bufsize;
738         }
739 
740         if (delay >= hstream->period_bytes) {
741                 dev_info(bus->dev,
742                          "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n",
743                          delay, hstream->period_bytes);
744                 delay = 0;
745         }
746 
747         return bytes_to_frames(substream->runtime, delay);
748 }
749 
750 static unsigned int skl_get_position(struct hdac_ext_stream *hstream,
751                                         int codec_delay)
752 {
753         struct hdac_stream *hstr = hdac_stream(hstream);
754         struct snd_pcm_substream *substream = hstr->substream;
755         struct hdac_ext_bus *ebus = get_bus_ctx(substream);
756         unsigned int pos;
757         int delay;
758 
759         /* use the position buffer as default */
760         pos = snd_hdac_stream_get_pos_posbuf(hdac_stream(hstream));
761 
762         if (pos >= hdac_stream(hstream)->bufsize)
763                 pos = 0;
764 
765         if (substream->runtime) {
766                 delay = skl_get_delay_from_lpib(ebus, hstream, pos)
767                                                  + codec_delay;
768                 substream->runtime->delay += delay;
769         }
770 
771         return pos;
772 }
773 
774 static snd_pcm_uframes_t skl_platform_pcm_pointer
775                         (struct snd_pcm_substream *substream)
776 {
777         struct hdac_ext_stream *hstream = get_hdac_ext_stream(substream);
778 
779         return bytes_to_frames(substream->runtime,
780                                skl_get_position(hstream, 0));
781 }
782 
783 static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream,
784                                 u64 nsec)
785 {
786         struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
787         struct snd_soc_dai *codec_dai = rtd->codec_dai;
788         u64 codec_frames, codec_nsecs;
789 
790         if (!codec_dai->driver->ops->delay)
791                 return nsec;
792 
793         codec_frames = codec_dai->driver->ops->delay(substream, codec_dai);
794         codec_nsecs = div_u64(codec_frames * 1000000000LL,
795                               substream->runtime->rate);
796 
797         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
798                 return nsec + codec_nsecs;
799 
800         return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0;
801 }
802 
803 static int skl_get_time_info(struct snd_pcm_substream *substream,
804                         struct timespec *system_ts, struct timespec *audio_ts,
805                         struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
806                         struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
807 {
808         struct hdac_ext_stream *sstream = get_hdac_ext_stream(substream);
809         struct hdac_stream *hstr = hdac_stream(sstream);
810         u64 nsec;
811 
812         if ((substream->runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_ATIME) &&
813                 (audio_tstamp_config->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK)) {
814 
815                 snd_pcm_gettime(substream->runtime, system_ts);
816 
817                 nsec = timecounter_read(&hstr->tc);
818                 nsec = div_u64(nsec, 3); /* can be optimized */
819                 if (audio_tstamp_config->report_delay)
820                         nsec = skl_adjust_codec_delay(substream, nsec);
821 
822                 *audio_ts = ns_to_timespec(nsec);
823 
824                 audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK;
825                 audio_tstamp_report->accuracy_report = 1; /* rest of struct is valid */
826                 audio_tstamp_report->accuracy = 42; /* 24MHzWallClk == 42ns resolution */
827 
828         } else {
829                 audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT;
830         }
831 
832         return 0;
833 }
834 
835 static struct snd_pcm_ops skl_platform_ops = {
836         .open = skl_platform_open,
837         .ioctl = snd_pcm_lib_ioctl,
838         .trigger = skl_platform_pcm_trigger,
839         .pointer = skl_platform_pcm_pointer,
840         .get_time_info =  skl_get_time_info,
841         .mmap = snd_pcm_lib_default_mmap,
842         .page = snd_pcm_sgbuf_ops_page,
843 };
844 
845 static void skl_pcm_free(struct snd_pcm *pcm)
846 {
847         snd_pcm_lib_preallocate_free_for_all(pcm);
848 }
849 
850 #define MAX_PREALLOC_SIZE       (32 * 1024 * 1024)
851 
852 static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
853 {
854         struct snd_soc_dai *dai = rtd->cpu_dai;
855         struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
856         struct snd_pcm *pcm = rtd->pcm;
857         unsigned int size;
858         int retval = 0;
859         struct skl *skl = ebus_to_skl(ebus);
860 
861         if (dai->driver->playback.channels_min ||
862                 dai->driver->capture.channels_min) {
863                 /* buffer pre-allocation */
864                 size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024;
865                 if (size > MAX_PREALLOC_SIZE)
866                         size = MAX_PREALLOC_SIZE;
867                 retval = snd_pcm_lib_preallocate_pages_for_all(pcm,
868                                                 SNDRV_DMA_TYPE_DEV_SG,
869                                                 snd_dma_pci_data(skl->pci),
870                                                 size, MAX_PREALLOC_SIZE);
871                 if (retval) {
872                         dev_err(dai->dev, "dma buffer allocationf fail\n");
873                         return retval;
874                 }
875         }
876 
877         return retval;
878 }
879 
880 static struct snd_soc_platform_driver skl_platform_drv  = {
881         .ops            = &skl_platform_ops,
882         .pcm_new        = skl_pcm_new,
883         .pcm_free       = skl_pcm_free,
884 };
885 
886 static const struct snd_soc_component_driver skl_component = {
887         .name           = "pcm",
888 };
889 
890 int skl_platform_register(struct device *dev)
891 {
892         int ret;
893 
894         ret = snd_soc_register_platform(dev, &skl_platform_drv);
895         if (ret) {
896                 dev_err(dev, "soc platform registration failed %d\n", ret);
897                 return ret;
898         }
899         ret = snd_soc_register_component(dev, &skl_component,
900                                 skl_platform_dai,
901                                 ARRAY_SIZE(skl_platform_dai));
902         if (ret) {
903                 dev_err(dev, "soc component registration failed %d\n", ret);
904                 snd_soc_unregister_platform(dev);
905         }
906 
907         return ret;
908 
909 }
910 
911 int skl_platform_unregister(struct device *dev)
912 {
913         snd_soc_unregister_component(dev);
914         snd_soc_unregister_platform(dev);
915         return 0;
916 }
917 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp