sst-mfld-platform-compress.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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. /* Turn on LPE */
  62. sst->compr_ops->power(sst->dev, true);
  63. sst_set_stream_status(stream, SST_PLATFORM_INIT);
  64. runtime->private_data = stream;
  65. return 0;
  66. out_ops:
  67. kfree(stream);
  68. return ret_val;
  69. }
  70. static int sst_platform_compr_free(struct snd_compr_stream *cstream)
  71. {
  72. struct sst_runtime_stream *stream;
  73. int ret_val = 0, str_id;
  74. stream = cstream->runtime->private_data;
  75. /* Turn off LPE */
  76. sst->compr_ops->power(sst->dev, false);
  77. /*need to check*/
  78. str_id = stream->id;
  79. if (str_id)
  80. ret_val = stream->compr_ops->close(sst->dev, str_id);
  81. module_put(sst->dev->driver->owner);
  82. kfree(stream);
  83. pr_debug("%s: %d\n", __func__, ret_val);
  84. return 0;
  85. }
  86. static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
  87. struct snd_compr_params *params)
  88. {
  89. struct sst_runtime_stream *stream;
  90. int retval;
  91. struct snd_sst_params str_params;
  92. struct sst_compress_cb cb;
  93. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  94. struct snd_soc_platform *platform = rtd->platform;
  95. struct sst_data *ctx = snd_soc_platform_get_drvdata(platform);
  96. stream = cstream->runtime->private_data;
  97. /* construct fw structure for this*/
  98. memset(&str_params, 0, sizeof(str_params));
  99. /* fill the device type and stream id to pass to SST driver */
  100. retval = sst_fill_stream_params(cstream, ctx, &str_params, true);
  101. pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval);
  102. if (retval < 0)
  103. return retval;
  104. switch (params->codec.id) {
  105. case SND_AUDIOCODEC_MP3: {
  106. str_params.codec = SST_CODEC_TYPE_MP3;
  107. str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in;
  108. str_params.sparams.uc.mp3_params.pcm_wd_sz = 16;
  109. break;
  110. }
  111. case SND_AUDIOCODEC_AAC: {
  112. str_params.codec = SST_CODEC_TYPE_AAC;
  113. str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in;
  114. str_params.sparams.uc.aac_params.pcm_wd_sz = 16;
  115. if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)
  116. str_params.sparams.uc.aac_params.bs_format =
  117. AAC_BIT_STREAM_ADTS;
  118. else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW)
  119. str_params.sparams.uc.aac_params.bs_format =
  120. AAC_BIT_STREAM_RAW;
  121. else {
  122. pr_err("Undefined format%d\n", params->codec.format);
  123. return -EINVAL;
  124. }
  125. str_params.sparams.uc.aac_params.externalsr =
  126. params->codec.sample_rate;
  127. break;
  128. }
  129. default:
  130. pr_err("codec not supported, id =%d\n", params->codec.id);
  131. return -EINVAL;
  132. }
  133. str_params.aparams.ring_buf_info[0].addr =
  134. virt_to_phys(cstream->runtime->buffer);
  135. str_params.aparams.ring_buf_info[0].size =
  136. cstream->runtime->buffer_size;
  137. str_params.aparams.sg_count = 1;
  138. str_params.aparams.frag_size = cstream->runtime->fragment_size;
  139. cb.param = cstream;
  140. cb.compr_cb = sst_compr_fragment_elapsed;
  141. cb.drain_cb_param = cstream;
  142. cb.drain_notify = sst_drain_notify;
  143. retval = stream->compr_ops->open(sst->dev, &str_params, &cb);
  144. if (retval < 0) {
  145. pr_err("stream allocation failed %d\n", retval);
  146. return retval;
  147. }
  148. stream->id = retval;
  149. return 0;
  150. }
  151. static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd)
  152. {
  153. struct sst_runtime_stream *stream = cstream->runtime->private_data;
  154. switch (cmd) {
  155. case SNDRV_PCM_TRIGGER_START:
  156. if (stream->compr_ops->stream_start)
  157. return stream->compr_ops->stream_start(sst->dev, stream->id);
  158. break;
  159. case SNDRV_PCM_TRIGGER_STOP:
  160. if (stream->compr_ops->stream_drop)
  161. return stream->compr_ops->stream_drop(sst->dev, stream->id);
  162. break;
  163. case SND_COMPR_TRIGGER_DRAIN:
  164. if (stream->compr_ops->stream_drain)
  165. return stream->compr_ops->stream_drain(sst->dev, stream->id);
  166. break;
  167. case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
  168. if (stream->compr_ops->stream_partial_drain)
  169. return stream->compr_ops->stream_partial_drain(sst->dev, stream->id);
  170. break;
  171. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  172. if (stream->compr_ops->stream_pause)
  173. return stream->compr_ops->stream_pause(sst->dev, stream->id);
  174. break;
  175. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  176. if (stream->compr_ops->stream_pause_release)
  177. return stream->compr_ops->stream_pause_release(sst->dev, stream->id);
  178. break;
  179. }
  180. return -EINVAL;
  181. }
  182. static int sst_platform_compr_pointer(struct snd_compr_stream *cstream,
  183. struct snd_compr_tstamp *tstamp)
  184. {
  185. struct sst_runtime_stream *stream;
  186. stream = cstream->runtime->private_data;
  187. stream->compr_ops->tstamp(sst->dev, stream->id, tstamp);
  188. tstamp->byte_offset = tstamp->copied_total %
  189. (u32)cstream->runtime->buffer_size;
  190. pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset);
  191. return 0;
  192. }
  193. static int sst_platform_compr_ack(struct snd_compr_stream *cstream,
  194. size_t bytes)
  195. {
  196. struct sst_runtime_stream *stream;
  197. stream = cstream->runtime->private_data;
  198. stream->compr_ops->ack(sst->dev, stream->id, (unsigned long)bytes);
  199. stream->bytes_written += bytes;
  200. return 0;
  201. }
  202. static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream,
  203. struct snd_compr_caps *caps)
  204. {
  205. struct sst_runtime_stream *stream =
  206. cstream->runtime->private_data;
  207. return stream->compr_ops->get_caps(caps);
  208. }
  209. static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream,
  210. struct snd_compr_codec_caps *codec)
  211. {
  212. struct sst_runtime_stream *stream =
  213. cstream->runtime->private_data;
  214. return stream->compr_ops->get_codec_caps(codec);
  215. }
  216. static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream,
  217. struct snd_compr_metadata *metadata)
  218. {
  219. struct sst_runtime_stream *stream =
  220. cstream->runtime->private_data;
  221. return stream->compr_ops->set_metadata(sst->dev, stream->id, metadata);
  222. }
  223. struct snd_compr_ops sst_platform_compr_ops = {
  224. .open = sst_platform_compr_open,
  225. .free = sst_platform_compr_free,
  226. .set_params = sst_platform_compr_set_params,
  227. .set_metadata = sst_platform_compr_set_metadata,
  228. .trigger = sst_platform_compr_trigger,
  229. .pointer = sst_platform_compr_pointer,
  230. .ack = sst_platform_compr_ack,
  231. .get_caps = sst_platform_compr_get_caps,
  232. .get_codec_caps = sst_platform_compr_get_codec_caps,
  233. };