Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sst_platform.c
Go to the documentation of this file.
1 /*
2  * sst_platform.c - Intel MID Platform driver
3  *
4  * Copyright (C) 2010-2012 Intel Corp
5  * Author: Vinod Koul <[email protected]>
6  * Author: Harsha Priya <[email protected]>
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  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21  *
22  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23  *
24  *
25  */
26 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
27 
28 #include <linux/slab.h>
29 #include <linux/io.h>
30 #include <linux/module.h>
31 #include <sound/core.h>
32 #include <sound/pcm.h>
33 #include <sound/pcm_params.h>
34 #include <sound/soc.h>
35 #include <sound/compress_driver.h>
36 #include "sst_platform.h"
37 
38 static struct sst_device *sst;
39 static DEFINE_MUTEX(sst_lock);
40 
42 {
43  BUG_ON(!dev);
44  if (!try_module_get(dev->dev->driver->owner))
45  return -ENODEV;
46  mutex_lock(&sst_lock);
47  if (sst) {
48  pr_err("we already have a device %s\n", sst->name);
49  module_put(dev->dev->driver->owner);
50  mutex_unlock(&sst_lock);
51  return -EEXIST;
52  }
53  pr_debug("registering device %s\n", dev->name);
54  sst = dev;
55  mutex_unlock(&sst_lock);
56  return 0;
57 }
59 
61 {
62  BUG_ON(!dev);
63  if (dev != sst)
64  return -EINVAL;
65 
66  mutex_lock(&sst_lock);
67 
68  if (!sst) {
69  mutex_unlock(&sst_lock);
70  return -EIO;
71  }
72 
73  module_put(sst->dev->driver->owner);
74  pr_debug("unreg %s\n", sst->name);
75  sst = NULL;
76  mutex_unlock(&sst_lock);
77  return 0;
78 }
80 
81 static struct snd_pcm_hardware sst_platform_pcm_hw = {
90  .formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |
91  SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |
92  SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32),
93  .rates = (SNDRV_PCM_RATE_8000|
106 };
107 
108 /* MFLD - MSIC */
109 static struct snd_soc_dai_driver sst_platform_dai[] = {
110 {
111  .name = "Headset-cpu-dai",
112  .id = 0,
113  .playback = {
114  .channels_min = SST_STEREO,
115  .channels_max = SST_STEREO,
116  .rates = SNDRV_PCM_RATE_48000,
117  .formats = SNDRV_PCM_FMTBIT_S24_LE,
118  },
119  .capture = {
120  .channels_min = 1,
121  .channels_max = 5,
122  .rates = SNDRV_PCM_RATE_48000,
123  .formats = SNDRV_PCM_FMTBIT_S24_LE,
124  },
125 },
126 {
127  .name = "Speaker-cpu-dai",
128  .id = 1,
129  .playback = {
130  .channels_min = SST_MONO,
131  .channels_max = SST_STEREO,
132  .rates = SNDRV_PCM_RATE_48000,
133  .formats = SNDRV_PCM_FMTBIT_S24_LE,
134  },
135 },
136 {
137  .name = "Vibra1-cpu-dai",
138  .id = 2,
139  .playback = {
140  .channels_min = SST_MONO,
141  .channels_max = SST_MONO,
142  .rates = SNDRV_PCM_RATE_48000,
143  .formats = SNDRV_PCM_FMTBIT_S24_LE,
144  },
145 },
146 {
147  .name = "Vibra2-cpu-dai",
148  .id = 3,
149  .playback = {
150  .channels_min = SST_MONO,
151  .channels_max = SST_STEREO,
152  .rates = SNDRV_PCM_RATE_48000,
153  .formats = SNDRV_PCM_FMTBIT_S24_LE,
154  },
155 },
156 {
157  .name = "Compress-cpu-dai",
158  .compress_dai = 1,
159  .playback = {
160  .channels_min = SST_STEREO,
161  .channels_max = SST_STEREO,
163  .formats = SNDRV_PCM_FMTBIT_S16_LE,
164  },
165 },
166 };
167 
168 /* helper functions */
169 static inline void sst_set_stream_status(struct sst_runtime_stream *stream,
170  int state)
171 {
172  unsigned long flags;
173  spin_lock_irqsave(&stream->status_lock, flags);
174  stream->stream_status = state;
175  spin_unlock_irqrestore(&stream->status_lock, flags);
176 }
177 
178 static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
179 {
180  int state;
181  unsigned long flags;
182 
183  spin_lock_irqsave(&stream->status_lock, flags);
184  state = stream->stream_status;
185  spin_unlock_irqrestore(&stream->status_lock, flags);
186  return state;
187 }
188 
189 static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
190  struct sst_pcm_params *param)
191 {
192 
193  param->codec = SST_CODEC_TYPE_PCM;
194  param->num_chan = (u8) substream->runtime->channels;
195  param->pcm_wd_sz = substream->runtime->sample_bits;
196  param->reserved = 0;
197  param->sfreq = substream->runtime->rate;
198  param->ring_buffer_size = snd_pcm_lib_buffer_bytes(substream);
199  param->period_count = substream->runtime->period_size;
200  param->ring_buffer_addr = virt_to_phys(substream->dma_buffer.area);
201  pr_debug("period_cnt = %d\n", param->period_count);
202  pr_debug("sfreq= %d, wd_sz = %d\n", param->sfreq, param->pcm_wd_sz);
203 }
204 
205 static int sst_platform_alloc_stream(struct snd_pcm_substream *substream)
206 {
207  struct sst_runtime_stream *stream =
208  substream->runtime->private_data;
209  struct sst_pcm_params param = {0};
210  struct sst_stream_params str_params = {0};
211  int ret_val;
212 
213  /* set codec params and inform SST driver the same */
214  sst_fill_pcm_params(substream, &param);
215  substream->runtime->dma_area = substream->dma_buffer.area;
216  str_params.sparams = param;
217  str_params.codec = param.codec;
218  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
219  str_params.ops = STREAM_OPS_PLAYBACK;
220  str_params.device_type = substream->pcm->device + 1;
221  pr_debug("Playbck stream,Device %d\n",
222  substream->pcm->device);
223  } else {
224  str_params.ops = STREAM_OPS_CAPTURE;
225  str_params.device_type = SND_SST_DEVICE_CAPTURE;
226  pr_debug("Capture stream,Device %d\n",
227  substream->pcm->device);
228  }
229  ret_val = stream->ops->open(&str_params);
230  pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val);
231  if (ret_val < 0)
232  return ret_val;
233 
234  stream->stream_info.str_id = ret_val;
235  pr_debug("str id : %d\n", stream->stream_info.str_id);
236  return ret_val;
237 }
238 
239 static void sst_period_elapsed(void *mad_substream)
240 {
241  struct snd_pcm_substream *substream = mad_substream;
242  struct sst_runtime_stream *stream;
243  int status;
244 
245  if (!substream || !substream->runtime)
246  return;
247  stream = substream->runtime->private_data;
248  if (!stream)
249  return;
250  status = sst_get_stream_status(stream);
251  if (status != SST_PLATFORM_RUNNING)
252  return;
253  snd_pcm_period_elapsed(substream);
254 }
255 
256 static int sst_platform_init_stream(struct snd_pcm_substream *substream)
257 {
258  struct sst_runtime_stream *stream =
259  substream->runtime->private_data;
260  int ret_val;
261 
262  pr_debug("setting buffer ptr param\n");
263  sst_set_stream_status(stream, SST_PLATFORM_INIT);
264  stream->stream_info.period_elapsed = sst_period_elapsed;
265  stream->stream_info.mad_substream = substream;
266  stream->stream_info.buffer_ptr = 0;
267  stream->stream_info.sfreq = substream->runtime->rate;
268  ret_val = stream->ops->device_control(
269  SST_SND_STREAM_INIT, &stream->stream_info);
270  if (ret_val)
271  pr_err("control_set ret error %d\n", ret_val);
272  return ret_val;
273 
274 }
275 /* end -- helper functions */
276 
277 static int sst_platform_open(struct snd_pcm_substream *substream)
278 {
279  struct snd_pcm_runtime *runtime = substream->runtime;
280  struct sst_runtime_stream *stream;
281  int ret_val;
282 
283  pr_debug("sst_platform_open called\n");
284 
285  snd_soc_set_runtime_hwparams(substream, &sst_platform_pcm_hw);
286  ret_val = snd_pcm_hw_constraint_integer(runtime,
288  if (ret_val < 0)
289  return ret_val;
290 
291  stream = kzalloc(sizeof(*stream), GFP_KERNEL);
292  if (!stream)
293  return -ENOMEM;
294  spin_lock_init(&stream->status_lock);
295 
296  /* get the sst ops */
297  mutex_lock(&sst_lock);
298  if (!sst) {
299  pr_err("no device available to run\n");
300  mutex_unlock(&sst_lock);
301  kfree(stream);
302  return -ENODEV;
303  }
304  if (!try_module_get(sst->dev->driver->owner)) {
305  mutex_unlock(&sst_lock);
306  kfree(stream);
307  return -ENODEV;
308  }
309  stream->ops = sst->ops;
310  mutex_unlock(&sst_lock);
311 
312  stream->stream_info.str_id = 0;
313  sst_set_stream_status(stream, SST_PLATFORM_INIT);
314  stream->stream_info.mad_substream = substream;
315  /* allocate memory for SST API set */
316  runtime->private_data = stream;
317 
318  return 0;
319 }
320 
321 static int sst_platform_close(struct snd_pcm_substream *substream)
322 {
323  struct sst_runtime_stream *stream;
324  int ret_val = 0, str_id;
325 
326  pr_debug("sst_platform_close called\n");
327  stream = substream->runtime->private_data;
328  str_id = stream->stream_info.str_id;
329  if (str_id)
330  ret_val = stream->ops->close(str_id);
331  module_put(sst->dev->driver->owner);
332  kfree(stream);
333  return ret_val;
334 }
335 
336 static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream)
337 {
338  struct sst_runtime_stream *stream;
339  int ret_val = 0, str_id;
340 
341  pr_debug("sst_platform_pcm_prepare called\n");
342  stream = substream->runtime->private_data;
343  str_id = stream->stream_info.str_id;
344  if (stream->stream_info.str_id) {
345  ret_val = stream->ops->device_control(
346  SST_SND_DROP, &str_id);
347  return ret_val;
348  }
349 
350  ret_val = sst_platform_alloc_stream(substream);
351  if (ret_val < 0)
352  return ret_val;
353  snprintf(substream->pcm->id, sizeof(substream->pcm->id),
354  "%d", stream->stream_info.str_id);
355 
356  ret_val = sst_platform_init_stream(substream);
357  if (ret_val)
358  return ret_val;
359  substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER;
360  return ret_val;
361 }
362 
363 static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
364  int cmd)
365 {
366  int ret_val = 0, str_id;
367  struct sst_runtime_stream *stream;
368  int str_cmd, status;
369 
370  pr_debug("sst_platform_pcm_trigger called\n");
371  stream = substream->runtime->private_data;
372  str_id = stream->stream_info.str_id;
373  switch (cmd) {
375  pr_debug("sst: Trigger Start\n");
376  str_cmd = SST_SND_START;
377  status = SST_PLATFORM_RUNNING;
378  stream->stream_info.mad_substream = substream;
379  break;
381  pr_debug("sst: in stop\n");
382  str_cmd = SST_SND_DROP;
383  status = SST_PLATFORM_DROPPED;
384  break;
386  pr_debug("sst: in pause\n");
387  str_cmd = SST_SND_PAUSE;
388  status = SST_PLATFORM_PAUSED;
389  break;
391  pr_debug("sst: in pause release\n");
392  str_cmd = SST_SND_RESUME;
393  status = SST_PLATFORM_RUNNING;
394  break;
395  default:
396  return -EINVAL;
397  }
398  ret_val = stream->ops->device_control(str_cmd, &str_id);
399  if (!ret_val)
400  sst_set_stream_status(stream, status);
401 
402  return ret_val;
403 }
404 
405 
406 static snd_pcm_uframes_t sst_platform_pcm_pointer
407  (struct snd_pcm_substream *substream)
408 {
409  struct sst_runtime_stream *stream;
410  int ret_val, status;
411  struct pcm_stream_info *str_info;
412 
413  stream = substream->runtime->private_data;
414  status = sst_get_stream_status(stream);
415  if (status == SST_PLATFORM_INIT)
416  return 0;
417  str_info = &stream->stream_info;
418  ret_val = stream->ops->device_control(
419  SST_SND_BUFFER_POINTER, str_info);
420  if (ret_val) {
421  pr_err("sst: error code = %d\n", ret_val);
422  return ret_val;
423  }
424  return stream->stream_info.buffer_ptr;
425 }
426 
427 static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream,
428  struct snd_pcm_hw_params *params)
429 {
430  snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
431  memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
432 
433  return 0;
434 }
435 
436 static int sst_platform_pcm_hw_free(struct snd_pcm_substream *substream)
437 {
438  return snd_pcm_lib_free_pages(substream);
439 }
440 
441 static struct snd_pcm_ops sst_platform_ops = {
442  .open = sst_platform_open,
443  .close = sst_platform_close,
444  .ioctl = snd_pcm_lib_ioctl,
445  .prepare = sst_platform_pcm_prepare,
446  .trigger = sst_platform_pcm_trigger,
447  .pointer = sst_platform_pcm_pointer,
448  .hw_params = sst_platform_pcm_hw_params,
449  .hw_free = sst_platform_pcm_hw_free,
450 };
451 
452 static void sst_pcm_free(struct snd_pcm *pcm)
453 {
454  pr_debug("sst_pcm_free called\n");
456 }
457 
458 static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
459 {
460  struct snd_pcm *pcm = rtd->pcm;
461  int retval = 0;
462 
463  pr_debug("sst_pcm_new called\n");
464  if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream ||
465  pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
470  if (retval) {
471  pr_err("dma buffer allocationf fail\n");
472  return retval;
473  }
474  }
475  return retval;
476 }
477 
478 /* compress stream operations */
479 static void sst_compr_fragment_elapsed(void *arg)
480 {
481  struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
482 
483  pr_debug("fragment elapsed by driver\n");
484  if (cstream)
485  snd_compr_fragment_elapsed(cstream);
486 }
487 
488 static int sst_platform_compr_open(struct snd_compr_stream *cstream)
489 {
490 
491  int ret_val = 0;
492  struct snd_compr_runtime *runtime = cstream->runtime;
493  struct sst_runtime_stream *stream;
494 
495  stream = kzalloc(sizeof(*stream), GFP_KERNEL);
496  if (!stream)
497  return -ENOMEM;
498 
499  spin_lock_init(&stream->status_lock);
500 
501  /* get the sst ops */
502  if (!sst || !try_module_get(sst->dev->driver->owner)) {
503  pr_err("no device available to run\n");
504  ret_val = -ENODEV;
505  goto out_ops;
506  }
507  stream->compr_ops = sst->compr_ops;
508 
509  stream->id = 0;
510  sst_set_stream_status(stream, SST_PLATFORM_INIT);
511  runtime->private_data = stream;
512  return 0;
513 out_ops:
514  kfree(stream);
515  return ret_val;
516 }
517 
518 static int sst_platform_compr_free(struct snd_compr_stream *cstream)
519 {
520  struct sst_runtime_stream *stream;
521  int ret_val = 0, str_id;
522 
523  stream = cstream->runtime->private_data;
524  /*need to check*/
525  str_id = stream->id;
526  if (str_id)
527  ret_val = stream->compr_ops->close(str_id);
528  module_put(sst->dev->driver->owner);
529  kfree(stream);
530  pr_debug("%s: %d\n", __func__, ret_val);
531  return 0;
532 }
533 
534 static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
535  struct snd_compr_params *params)
536 {
537  struct sst_runtime_stream *stream;
538  int retval;
539  struct snd_sst_params str_params;
540  struct sst_compress_cb cb;
541 
542  stream = cstream->runtime->private_data;
543  /* construct fw structure for this*/
544  memset(&str_params, 0, sizeof(str_params));
545 
546  str_params.ops = STREAM_OPS_PLAYBACK;
547  str_params.stream_type = SST_STREAM_TYPE_MUSIC;
549 
550  switch (params->codec.id) {
551  case SND_AUDIOCODEC_MP3: {
552  str_params.codec = SST_CODEC_TYPE_MP3;
553  str_params.sparams.uc.mp3_params.codec = SST_CODEC_TYPE_MP3;
554  str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in;
555  str_params.sparams.uc.mp3_params.pcm_wd_sz = 16;
556  break;
557  }
558 
559  case SND_AUDIOCODEC_AAC: {
560  str_params.codec = SST_CODEC_TYPE_AAC;
561  str_params.sparams.uc.aac_params.codec = SST_CODEC_TYPE_AAC;
562  str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in;
563  str_params.sparams.uc.aac_params.pcm_wd_sz = 16;
564  if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)
565  str_params.sparams.uc.aac_params.bs_format =
567  else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW)
568  str_params.sparams.uc.aac_params.bs_format =
570  else {
571  pr_err("Undefined format%d\n", params->codec.format);
572  return -EINVAL;
573  }
574  str_params.sparams.uc.aac_params.externalsr =
575  params->codec.sample_rate;
576  break;
577  }
578 
579  default:
580  pr_err("codec not supported, id =%d\n", params->codec.id);
581  return -EINVAL;
582  }
583 
584  str_params.aparams.ring_buf_info[0].addr =
585  virt_to_phys(cstream->runtime->buffer);
586  str_params.aparams.ring_buf_info[0].size =
587  cstream->runtime->buffer_size;
588  str_params.aparams.sg_count = 1;
589  str_params.aparams.frag_size = cstream->runtime->fragment_size;
590 
591  cb.param = cstream;
592  cb.compr_cb = sst_compr_fragment_elapsed;
593 
594  retval = stream->compr_ops->open(&str_params, &cb);
595  if (retval < 0) {
596  pr_err("stream allocation failed %d\n", retval);
597  return retval;
598  }
599 
600  stream->id = retval;
601  return 0;
602 }
603 
604 static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd)
605 {
606  struct sst_runtime_stream *stream =
607  cstream->runtime->private_data;
608 
609  return stream->compr_ops->control(cmd, stream->id);
610 }
611 
612 static int sst_platform_compr_pointer(struct snd_compr_stream *cstream,
613  struct snd_compr_tstamp *tstamp)
614 {
615  struct sst_runtime_stream *stream;
616 
617  stream = cstream->runtime->private_data;
618  stream->compr_ops->tstamp(stream->id, tstamp);
619  tstamp->byte_offset = tstamp->copied_total %
620  (u32)cstream->runtime->buffer_size;
621  pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset);
622  return 0;
623 }
624 
625 static int sst_platform_compr_ack(struct snd_compr_stream *cstream,
626  size_t bytes)
627 {
628  struct sst_runtime_stream *stream;
629 
630  stream = cstream->runtime->private_data;
631  stream->compr_ops->ack(stream->id, (unsigned long)bytes);
632  stream->bytes_written += bytes;
633 
634  return 0;
635 }
636 
637 static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream,
638  struct snd_compr_caps *caps)
639 {
640  struct sst_runtime_stream *stream =
641  cstream->runtime->private_data;
642 
643  return stream->compr_ops->get_caps(caps);
644 }
645 
646 static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream,
647  struct snd_compr_codec_caps *codec)
648 {
649  struct sst_runtime_stream *stream =
650  cstream->runtime->private_data;
651 
652  return stream->compr_ops->get_codec_caps(codec);
653 }
654 
655 static struct snd_compr_ops sst_platform_compr_ops = {
656 
657  .open = sst_platform_compr_open,
658  .free = sst_platform_compr_free,
659  .set_params = sst_platform_compr_set_params,
660  .trigger = sst_platform_compr_trigger,
661  .pointer = sst_platform_compr_pointer,
662  .ack = sst_platform_compr_ack,
663  .get_caps = sst_platform_compr_get_caps,
664  .get_codec_caps = sst_platform_compr_get_codec_caps,
665 };
666 
667 static struct snd_soc_platform_driver sst_soc_platform_drv = {
668  .ops = &sst_platform_ops,
669  .compr_ops = &sst_platform_compr_ops,
670  .pcm_new = sst_pcm_new,
671  .pcm_free = sst_pcm_free,
672 };
673 
674 static int sst_platform_probe(struct platform_device *pdev)
675 {
676  int ret;
677 
678  pr_debug("sst_platform_probe called\n");
679  sst = NULL;
680  ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv);
681  if (ret) {
682  pr_err("registering soc platform failed\n");
683  return ret;
684  }
685 
686  ret = snd_soc_register_dais(&pdev->dev,
687  sst_platform_dai, ARRAY_SIZE(sst_platform_dai));
688  if (ret) {
689  pr_err("registering cpu dais failed\n");
691  }
692  return ret;
693 }
694 
695 static int sst_platform_remove(struct platform_device *pdev)
696 {
697 
698  snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sst_platform_dai));
700  pr_debug("sst_platform_remove success\n");
701  return 0;
702 }
703 
704 static struct platform_driver sst_platform_driver = {
705  .driver = {
706  .name = "sst-platform",
707  .owner = THIS_MODULE,
708  },
709  .probe = sst_platform_probe,
710  .remove = sst_platform_remove,
711 };
712 
713 module_platform_driver(sst_platform_driver);
714 
715 MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver");
716 MODULE_AUTHOR("Vinod Koul <[email protected]>");
717 MODULE_AUTHOR("Harsha Priya <[email protected]>");
718 MODULE_LICENSE("GPL v2");
719 MODULE_ALIAS("platform:sst-platform");