sst-mfld-platform-compress.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. * sst_mfld_platform.c - Intel MID Platform driver
  3. *
  4. * Copyright (C) 2010-2014 Intel Corp
  5. * Author: Vinod Koul <vinod.koul@intel.com>
  6. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; version 2 of the License.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  18. */
  19. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  20. #include <linux/slab.h>
  21. #include <linux/io.h>
  22. #include <linux/module.h>
  23. #include <sound/core.h>
  24. #include <sound/pcm.h>
  25. #include <sound/pcm_params.h>
  26. #include <sound/soc.h>
  27. #include <sound/compress_driver.h>
  28. #include "sst-mfld-platform.h"
  29. /* compress stream operations */
  30. static void sst_compr_fragment_elapsed(void *arg)
  31. {
  32. struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
  33. pr_debug("fragment elapsed by driver\n");
  34. if (cstream)
  35. snd_compr_fragment_elapsed(cstream);
  36. }
  37. static void sst_drain_notify(void *arg)
  38. {
  39. struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
  40. pr_debug("drain notify by driver\n");
  41. if (cstream)
  42. snd_compr_drain_notify(cstream);
  43. }
  44. static int sst_platform_compr_open(struct snd_compr_stream *cstream)
  45. {
  46. int ret_val = 0;
  47. struct snd_compr_runtime *runtime = cstream->runtime;
  48. struct sst_runtime_stream *stream;
  49. stream = kzalloc(sizeof(*stream), GFP_KERNEL);
  50. if (!stream)
  51. return -ENOMEM;
  52. spin_lock_init(&stream->status_lock);
  53. /* get the sst ops */
  54. if (!sst || !try_module_get(sst->dev->driver->owner)) {
  55. pr_err("no device available to run\n");
  56. ret_val = -ENODEV;
  57. goto out_ops;
  58. }
  59. stream->compr_ops = sst->compr_ops;
  60. stream->id = 0;
  61. sst_set_stream_status(stream, SST_PLATFORM_INIT);
  62. runtime->private_data = stream;
  63. return 0;
  64. out_ops:
  65. kfree(stream);
  66. return ret_val;
  67. }
  68. static int sst_platform_compr_free(struct snd_compr_stream *cstream)
  69. {
  70. struct sst_runtime_stream *stream;
  71. int ret_val = 0, str_id;
  72. stream = cstream->runtime->private_data;
  73. /*need to check*/
  74. str_id = stream->id;
  75. if (str_id)
  76. ret_val = stream->compr_ops->close(sst->dev, str_id);
  77. module_put(sst->dev->driver->owner);
  78. kfree(stream);
  79. pr_debug("%s: %d\n", __func__, ret_val);
  80. return 0;
  81. }
  82. static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
  83. struct snd_compr_params *params)
  84. {
  85. struct sst_runtime_stream *stream;
  86. int retval;
  87. struct snd_sst_params str_params;
  88. struct sst_compress_cb cb;
  89. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  90. struct snd_soc_platform *platform = rtd->platform;
  91. struct sst_data *ctx = snd_soc_platform_get_drvdata(platform);
  92. stream = cstream->runtime->private_data;
  93. /* construct fw structure for this*/
  94. memset(&str_params, 0, sizeof(str_params));
  95. /* fill the device type and stream id to pass to SST driver */
  96. retval = sst_fill_stream_params(cstream, ctx, &str_params, true);
  97. pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval);
  98. if (retval < 0)
  99. return retval;
  100. switch (params->codec.id) {
  101. case SND_AUDIOCODEC_MP3: {
  102. str_params.codec = SST_CODEC_TYPE_MP3;
  103. str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in;
  104. str_params.sparams.uc.mp3_params.pcm_wd_sz = 16;
  105. break;
  106. }
  107. case SND_AUDIOCODEC_AAC: {
  108. str_params.codec = SST_CODEC_TYPE_AAC;
  109. str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in;
  110. str_params.sparams.uc.aac_params.pcm_wd_sz = 16;
  111. if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)
  112. str_params.sparams.uc.aac_params.bs_format =
  113. AAC_BIT_STREAM_ADTS;
  114. else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW)
  115. str_params.sparams.uc.aac_params.bs_format =
  116. AAC_BIT_STREAM_RAW;
  117. else {
  118. pr_err("Undefined format%d\n", params->codec.format);
  119. return -EINVAL;
  120. }
  121. str_params.sparams.uc.aac_params.externalsr =
  122. params->codec.sample_rate;
  123. break;
  124. }
  125. default:
  126. pr_err("codec not supported, id =%d\n", params->codec.id);
  127. return -EINVAL;
  128. }
  129. str_params.aparams.ring_buf_info[0].addr =
  130. virt_to_phys(cstream->runtime->buffer);
  131. str_params.aparams.ring_buf_info[0].size =
  132. cstream->runtime->buffer_size;
  133. str_params.aparams.sg_count = 1;
  134. str_params.aparams.frag_size = cstream->runtime->fragment_size;
  135. cb.param = cstream;
  136. cb.compr_cb = sst_compr_fragment_elapsed;
  137. cb.drain_cb_param = cstream;
  138. cb.drain_notify = sst_drain_notify;
  139. retval = stream->compr_ops->open(sst->dev, &str_params, &cb);
  140. if (retval < 0) {
  141. pr_err("stream allocation failed %d\n", retval);
  142. return retval;
  143. }
  144. stream->id = retval;
  145. return 0;
  146. }
  147. static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd)
  148. {
  149. struct sst_runtime_stream *stream = cstream->runtime->private_data;
  150. switch (cmd) {
  151. case SNDRV_PCM_TRIGGER_START:
  152. if (stream->compr_ops->stream_start)
  153. return stream->compr_ops->stream_start(sst->dev, stream->id);
  154. case SNDRV_PCM_TRIGGER_STOP:
  155. if (stream->compr_ops->stream_drop)
  156. return stream->compr_ops->stream_drop(sst->dev, stream->id);
  157. case SND_COMPR_TRIGGER_DRAIN:
  158. if (stream->compr_ops->stream_drain)
  159. return stream->compr_ops->stream_drain(sst->dev, stream->id);
  160. case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
  161. if (stream->compr_ops->stream_partial_drain)
  162. return stream->compr_ops->stream_partial_drain(sst->dev, stream->id);
  163. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  164. if (stream->compr_ops->stream_pause)
  165. return stream->compr_ops->stream_pause(sst->dev, stream->id);
  166. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  167. if (stream->compr_ops->stream_pause_release)
  168. return stream->compr_ops->stream_pause_release(sst->dev, stream->id);
  169. default:
  170. return -EINVAL;
  171. }
  172. }
  173. static int sst_platform_compr_pointer(struct snd_compr_stream *cstream,
  174. struct snd_compr_tstamp *tstamp)
  175. {
  176. struct sst_runtime_stream *stream;
  177. stream = cstream->runtime->private_data;
  178. stream->compr_ops->tstamp(sst->dev, stream->id, tstamp);
  179. tstamp->byte_offset = tstamp->copied_total %
  180. (u32)cstream->runtime->buffer_size;
  181. pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset);
  182. return 0;
  183. }
  184. static int sst_platform_compr_ack(struct snd_compr_stream *cstream,
  185. size_t bytes)
  186. {
  187. struct sst_runtime_stream *stream;
  188. stream = cstream->runtime->private_data;
  189. stream->compr_ops->ack(sst->dev, stream->id, (unsigned long)bytes);
  190. stream->bytes_written += bytes;
  191. return 0;
  192. }
  193. static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream,
  194. struct snd_compr_caps *caps)
  195. {
  196. struct sst_runtime_stream *stream =
  197. cstream->runtime->private_data;
  198. return stream->compr_ops->get_caps(caps);
  199. }
  200. static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream,
  201. struct snd_compr_codec_caps *codec)
  202. {
  203. struct sst_runtime_stream *stream =
  204. cstream->runtime->private_data;
  205. return stream->compr_ops->get_codec_caps(codec);
  206. }
  207. static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream,
  208. struct snd_compr_metadata *metadata)
  209. {
  210. struct sst_runtime_stream *stream =
  211. cstream->runtime->private_data;
  212. return stream->compr_ops->set_metadata(sst->dev, stream->id, metadata);
  213. }
  214. struct snd_compr_ops sst_platform_compr_ops = {
  215. .open = sst_platform_compr_open,
  216. .free = sst_platform_compr_free,
  217. .set_params = sst_platform_compr_set_params,
  218. .set_metadata = sst_platform_compr_set_metadata,
  219. .trigger = sst_platform_compr_trigger,
  220. .pointer = sst_platform_compr_pointer,
  221. .ack = sst_platform_compr_ack,
  222. .get_caps = sst_platform_compr_get_caps,
  223. .get_codec_caps = sst_platform_compr_get_codec_caps,
  224. };