sst-mfld-platform-compress.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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(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. stream = cstream->runtime->private_data;
  90. /* construct fw structure for this*/
  91. memset(&str_params, 0, sizeof(str_params));
  92. str_params.ops = STREAM_OPS_PLAYBACK;
  93. str_params.stream_type = SST_STREAM_TYPE_MUSIC;
  94. str_params.device_type = SND_SST_DEVICE_COMPRESS;
  95. switch (params->codec.id) {
  96. case SND_AUDIOCODEC_MP3: {
  97. str_params.codec = SST_CODEC_TYPE_MP3;
  98. str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in;
  99. str_params.sparams.uc.mp3_params.pcm_wd_sz = 16;
  100. break;
  101. }
  102. case SND_AUDIOCODEC_AAC: {
  103. str_params.codec = SST_CODEC_TYPE_AAC;
  104. str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in;
  105. str_params.sparams.uc.aac_params.pcm_wd_sz = 16;
  106. if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)
  107. str_params.sparams.uc.aac_params.bs_format =
  108. AAC_BIT_STREAM_ADTS;
  109. else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW)
  110. str_params.sparams.uc.aac_params.bs_format =
  111. AAC_BIT_STREAM_RAW;
  112. else {
  113. pr_err("Undefined format%d\n", params->codec.format);
  114. return -EINVAL;
  115. }
  116. str_params.sparams.uc.aac_params.externalsr =
  117. params->codec.sample_rate;
  118. break;
  119. }
  120. default:
  121. pr_err("codec not supported, id =%d\n", params->codec.id);
  122. return -EINVAL;
  123. }
  124. str_params.aparams.ring_buf_info[0].addr =
  125. virt_to_phys(cstream->runtime->buffer);
  126. str_params.aparams.ring_buf_info[0].size =
  127. cstream->runtime->buffer_size;
  128. str_params.aparams.sg_count = 1;
  129. str_params.aparams.frag_size = cstream->runtime->fragment_size;
  130. cb.param = cstream;
  131. cb.compr_cb = sst_compr_fragment_elapsed;
  132. cb.drain_cb_param = cstream;
  133. cb.drain_notify = sst_drain_notify;
  134. retval = stream->compr_ops->open(&str_params, &cb);
  135. if (retval < 0) {
  136. pr_err("stream allocation failed %d\n", retval);
  137. return retval;
  138. }
  139. stream->id = retval;
  140. return 0;
  141. }
  142. static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd)
  143. {
  144. struct sst_runtime_stream *stream =
  145. cstream->runtime->private_data;
  146. return stream->compr_ops->control(cmd, stream->id);
  147. }
  148. static int sst_platform_compr_pointer(struct snd_compr_stream *cstream,
  149. struct snd_compr_tstamp *tstamp)
  150. {
  151. struct sst_runtime_stream *stream;
  152. stream = cstream->runtime->private_data;
  153. stream->compr_ops->tstamp(stream->id, tstamp);
  154. tstamp->byte_offset = tstamp->copied_total %
  155. (u32)cstream->runtime->buffer_size;
  156. pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset);
  157. return 0;
  158. }
  159. static int sst_platform_compr_ack(struct snd_compr_stream *cstream,
  160. size_t bytes)
  161. {
  162. struct sst_runtime_stream *stream;
  163. stream = cstream->runtime->private_data;
  164. stream->compr_ops->ack(stream->id, (unsigned long)bytes);
  165. stream->bytes_written += bytes;
  166. return 0;
  167. }
  168. static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream,
  169. struct snd_compr_caps *caps)
  170. {
  171. struct sst_runtime_stream *stream =
  172. cstream->runtime->private_data;
  173. return stream->compr_ops->get_caps(caps);
  174. }
  175. static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream,
  176. struct snd_compr_codec_caps *codec)
  177. {
  178. struct sst_runtime_stream *stream =
  179. cstream->runtime->private_data;
  180. return stream->compr_ops->get_codec_caps(codec);
  181. }
  182. static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream,
  183. struct snd_compr_metadata *metadata)
  184. {
  185. struct sst_runtime_stream *stream =
  186. cstream->runtime->private_data;
  187. return stream->compr_ops->set_metadata(stream->id, metadata);
  188. }
  189. struct snd_compr_ops sst_platform_compr_ops = {
  190. .open = sst_platform_compr_open,
  191. .free = sst_platform_compr_free,
  192. .set_params = sst_platform_compr_set_params,
  193. .set_metadata = sst_platform_compr_set_metadata,
  194. .trigger = sst_platform_compr_trigger,
  195. .pointer = sst_platform_compr_pointer,
  196. .ack = sst_platform_compr_ack,
  197. .get_caps = sst_platform_compr_get_caps,
  198. .get_codec_caps = sst_platform_compr_get_codec_caps,
  199. };