dice-pcm.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /*
  2. * dice_pcm.c - a part of driver for DICE based devices
  3. *
  4. * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  5. * Copyright (c) 2014 Takashi Sakamoto <o-takashi@sakamocchi.jp>
  6. *
  7. * Licensed under the terms of the GNU General Public License, version 2.
  8. */
  9. #include "dice.h"
  10. static int limit_channels_and_rates(struct snd_dice *dice,
  11. struct snd_pcm_runtime *runtime,
  12. enum amdtp_stream_direction dir,
  13. unsigned int index, unsigned int size)
  14. {
  15. struct snd_pcm_hardware *hw = &runtime->hw;
  16. struct amdtp_stream *stream;
  17. unsigned int rate;
  18. __be32 reg;
  19. int err;
  20. /*
  21. * Retrieve current Multi Bit Linear Audio data channel and limit to
  22. * it.
  23. */
  24. if (dir == AMDTP_IN_STREAM) {
  25. stream = &dice->tx_stream[index];
  26. err = snd_dice_transaction_read_tx(dice,
  27. size * index + TX_NUMBER_AUDIO,
  28. &reg, sizeof(reg));
  29. } else {
  30. stream = &dice->rx_stream[index];
  31. err = snd_dice_transaction_read_rx(dice,
  32. size * index + RX_NUMBER_AUDIO,
  33. &reg, sizeof(reg));
  34. }
  35. if (err < 0)
  36. return err;
  37. hw->channels_min = hw->channels_max = be32_to_cpu(reg);
  38. /* Retrieve current sampling transfer frequency and limit to it. */
  39. err = snd_dice_transaction_get_rate(dice, &rate);
  40. if (err < 0)
  41. return err;
  42. hw->rates = snd_pcm_rate_to_rate_bit(rate);
  43. snd_pcm_limit_hw_rates(runtime);
  44. return 0;
  45. }
  46. static void limit_period_and_buffer(struct snd_pcm_hardware *hw)
  47. {
  48. hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */
  49. hw->periods_max = UINT_MAX;
  50. hw->period_bytes_min = 4 * hw->channels_max; /* byte for a frame */
  51. /* Just to prevent from allocating much pages. */
  52. hw->period_bytes_max = hw->period_bytes_min * 2048;
  53. hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min;
  54. }
  55. static int init_hw_info(struct snd_dice *dice,
  56. struct snd_pcm_substream *substream)
  57. {
  58. struct snd_pcm_runtime *runtime = substream->runtime;
  59. struct snd_pcm_hardware *hw = &runtime->hw;
  60. enum amdtp_stream_direction dir;
  61. struct amdtp_stream *stream;
  62. __be32 reg[2];
  63. unsigned int count, size;
  64. int err;
  65. hw->info = SNDRV_PCM_INFO_MMAP |
  66. SNDRV_PCM_INFO_MMAP_VALID |
  67. SNDRV_PCM_INFO_BATCH |
  68. SNDRV_PCM_INFO_INTERLEAVED |
  69. SNDRV_PCM_INFO_JOINT_DUPLEX |
  70. SNDRV_PCM_INFO_BLOCK_TRANSFER;
  71. if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
  72. hw->formats = AM824_IN_PCM_FORMAT_BITS;
  73. dir = AMDTP_IN_STREAM;
  74. stream = &dice->tx_stream[substream->pcm->device];
  75. err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg,
  76. sizeof(reg));
  77. } else {
  78. hw->formats = AM824_OUT_PCM_FORMAT_BITS;
  79. dir = AMDTP_OUT_STREAM;
  80. stream = &dice->rx_stream[substream->pcm->device];
  81. err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg,
  82. sizeof(reg));
  83. }
  84. if (err < 0)
  85. return err;
  86. count = min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
  87. if (substream->pcm->device >= count)
  88. return -ENXIO;
  89. size = be32_to_cpu(reg[1]) * 4;
  90. err = limit_channels_and_rates(dice, substream->runtime, dir,
  91. substream->pcm->device, size);
  92. if (err < 0)
  93. return err;
  94. limit_period_and_buffer(hw);
  95. return amdtp_am824_add_pcm_hw_constraints(stream, runtime);
  96. }
  97. static int pcm_open(struct snd_pcm_substream *substream)
  98. {
  99. struct snd_dice *dice = substream->private_data;
  100. int err;
  101. err = snd_dice_stream_lock_try(dice);
  102. if (err < 0)
  103. goto end;
  104. err = init_hw_info(dice, substream);
  105. if (err < 0)
  106. goto err_locked;
  107. snd_pcm_set_sync(substream);
  108. end:
  109. return err;
  110. err_locked:
  111. snd_dice_stream_lock_release(dice);
  112. return err;
  113. }
  114. static int pcm_close(struct snd_pcm_substream *substream)
  115. {
  116. struct snd_dice *dice = substream->private_data;
  117. snd_dice_stream_lock_release(dice);
  118. return 0;
  119. }
  120. static int capture_hw_params(struct snd_pcm_substream *substream,
  121. struct snd_pcm_hw_params *hw_params)
  122. {
  123. struct snd_dice *dice = substream->private_data;
  124. struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
  125. int err;
  126. err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
  127. params_buffer_bytes(hw_params));
  128. if (err < 0)
  129. return err;
  130. if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
  131. mutex_lock(&dice->mutex);
  132. dice->substreams_counter++;
  133. mutex_unlock(&dice->mutex);
  134. }
  135. amdtp_am824_set_pcm_format(stream, params_format(hw_params));
  136. return 0;
  137. }
  138. static int playback_hw_params(struct snd_pcm_substream *substream,
  139. struct snd_pcm_hw_params *hw_params)
  140. {
  141. struct snd_dice *dice = substream->private_data;
  142. struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
  143. int err;
  144. err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
  145. params_buffer_bytes(hw_params));
  146. if (err < 0)
  147. return err;
  148. if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
  149. mutex_lock(&dice->mutex);
  150. dice->substreams_counter++;
  151. mutex_unlock(&dice->mutex);
  152. }
  153. amdtp_am824_set_pcm_format(stream, params_format(hw_params));
  154. return 0;
  155. }
  156. static int capture_hw_free(struct snd_pcm_substream *substream)
  157. {
  158. struct snd_dice *dice = substream->private_data;
  159. mutex_lock(&dice->mutex);
  160. if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
  161. dice->substreams_counter--;
  162. snd_dice_stream_stop_duplex(dice);
  163. mutex_unlock(&dice->mutex);
  164. return snd_pcm_lib_free_vmalloc_buffer(substream);
  165. }
  166. static int playback_hw_free(struct snd_pcm_substream *substream)
  167. {
  168. struct snd_dice *dice = substream->private_data;
  169. mutex_lock(&dice->mutex);
  170. if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
  171. dice->substreams_counter--;
  172. snd_dice_stream_stop_duplex(dice);
  173. mutex_unlock(&dice->mutex);
  174. return snd_pcm_lib_free_vmalloc_buffer(substream);
  175. }
  176. static int capture_prepare(struct snd_pcm_substream *substream)
  177. {
  178. struct snd_dice *dice = substream->private_data;
  179. struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
  180. int err;
  181. mutex_lock(&dice->mutex);
  182. err = snd_dice_stream_start_duplex(dice, substream->runtime->rate);
  183. mutex_unlock(&dice->mutex);
  184. if (err >= 0)
  185. amdtp_stream_pcm_prepare(stream);
  186. return 0;
  187. }
  188. static int playback_prepare(struct snd_pcm_substream *substream)
  189. {
  190. struct snd_dice *dice = substream->private_data;
  191. struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
  192. int err;
  193. mutex_lock(&dice->mutex);
  194. err = snd_dice_stream_start_duplex(dice, substream->runtime->rate);
  195. mutex_unlock(&dice->mutex);
  196. if (err >= 0)
  197. amdtp_stream_pcm_prepare(stream);
  198. return err;
  199. }
  200. static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
  201. {
  202. struct snd_dice *dice = substream->private_data;
  203. struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
  204. switch (cmd) {
  205. case SNDRV_PCM_TRIGGER_START:
  206. amdtp_stream_pcm_trigger(stream, substream);
  207. break;
  208. case SNDRV_PCM_TRIGGER_STOP:
  209. amdtp_stream_pcm_trigger(stream, NULL);
  210. break;
  211. default:
  212. return -EINVAL;
  213. }
  214. return 0;
  215. }
  216. static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
  217. {
  218. struct snd_dice *dice = substream->private_data;
  219. struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
  220. switch (cmd) {
  221. case SNDRV_PCM_TRIGGER_START:
  222. amdtp_stream_pcm_trigger(stream, substream);
  223. break;
  224. case SNDRV_PCM_TRIGGER_STOP:
  225. amdtp_stream_pcm_trigger(stream, NULL);
  226. break;
  227. default:
  228. return -EINVAL;
  229. }
  230. return 0;
  231. }
  232. static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
  233. {
  234. struct snd_dice *dice = substream->private_data;
  235. struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
  236. return amdtp_stream_pcm_pointer(stream);
  237. }
  238. static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
  239. {
  240. struct snd_dice *dice = substream->private_data;
  241. struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
  242. return amdtp_stream_pcm_pointer(stream);
  243. }
  244. int snd_dice_create_pcm(struct snd_dice *dice)
  245. {
  246. static const struct snd_pcm_ops capture_ops = {
  247. .open = pcm_open,
  248. .close = pcm_close,
  249. .ioctl = snd_pcm_lib_ioctl,
  250. .hw_params = capture_hw_params,
  251. .hw_free = capture_hw_free,
  252. .prepare = capture_prepare,
  253. .trigger = capture_trigger,
  254. .pointer = capture_pointer,
  255. .page = snd_pcm_lib_get_vmalloc_page,
  256. .mmap = snd_pcm_lib_mmap_vmalloc,
  257. };
  258. static const struct snd_pcm_ops playback_ops = {
  259. .open = pcm_open,
  260. .close = pcm_close,
  261. .ioctl = snd_pcm_lib_ioctl,
  262. .hw_params = playback_hw_params,
  263. .hw_free = playback_hw_free,
  264. .prepare = playback_prepare,
  265. .trigger = playback_trigger,
  266. .pointer = playback_pointer,
  267. .page = snd_pcm_lib_get_vmalloc_page,
  268. .mmap = snd_pcm_lib_mmap_vmalloc,
  269. };
  270. __be32 reg;
  271. struct snd_pcm *pcm;
  272. unsigned int i, max_capture, max_playback, capture, playback;
  273. int err;
  274. /* Check whether PCM substreams are required. */
  275. if (dice->force_two_pcms) {
  276. max_capture = max_playback = 2;
  277. } else {
  278. max_capture = max_playback = 0;
  279. err = snd_dice_transaction_read_tx(dice, TX_NUMBER, &reg,
  280. sizeof(reg));
  281. if (err < 0)
  282. return err;
  283. max_capture = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS);
  284. err = snd_dice_transaction_read_rx(dice, RX_NUMBER, &reg,
  285. sizeof(reg));
  286. if (err < 0)
  287. return err;
  288. max_playback = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS);
  289. }
  290. for (i = 0; i < MAX_STREAMS; i++) {
  291. capture = playback = 0;
  292. if (i < max_capture)
  293. capture = 1;
  294. if (i < max_playback)
  295. playback = 1;
  296. if (capture == 0 && playback == 0)
  297. break;
  298. err = snd_pcm_new(dice->card, "DICE", i, playback, capture,
  299. &pcm);
  300. if (err < 0)
  301. return err;
  302. pcm->private_data = dice;
  303. strcpy(pcm->name, dice->card->shortname);
  304. if (capture > 0)
  305. snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
  306. &capture_ops);
  307. if (playback > 0)
  308. snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
  309. &playback_ops);
  310. }
  311. return 0;
  312. }