dmaengine_pcm.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /* SPDX-License-Identifier: GPL-2.0+
  2. *
  3. * Copyright (C) 2012, Analog Devices Inc.
  4. * Author: Lars-Peter Clausen <lars@metafoo.de>
  5. */
  6. #ifndef __SOUND_DMAENGINE_PCM_H__
  7. #define __SOUND_DMAENGINE_PCM_H__
  8. #include <sound/pcm.h>
  9. #include <sound/soc.h>
  10. #include <linux/dmaengine.h>
  11. /**
  12. * snd_pcm_substream_to_dma_direction - Get dma_transfer_direction for a PCM
  13. * substream
  14. * @substream: PCM substream
  15. *
  16. * Return: DMA transfer direction
  17. */
  18. static inline enum dma_transfer_direction
  19. snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream)
  20. {
  21. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  22. return DMA_MEM_TO_DEV;
  23. else
  24. return DMA_DEV_TO_MEM;
  25. }
  26. int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
  27. const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config);
  28. int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
  29. snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream);
  30. snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream);
  31. int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
  32. struct dma_chan *chan);
  33. int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream);
  34. int snd_dmaengine_pcm_sync_stop(struct snd_pcm_substream *substream);
  35. int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
  36. dma_filter_fn filter_fn, void *filter_data);
  37. int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream);
  38. struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn,
  39. void *filter_data);
  40. struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream);
  41. /*
  42. * The DAI supports packed transfers, eg 2 16-bit samples in a 32-bit word.
  43. * If this flag is set the dmaengine driver won't put any restriction on
  44. * the supported sample formats and set the DMA transfer size to undefined.
  45. * The DAI driver is responsible to disable any unsupported formats in it's
  46. * configuration and catch corner cases that are not already handled in
  47. * the ALSA core.
  48. */
  49. #define SND_DMAENGINE_PCM_DAI_FLAG_PACK BIT(0)
  50. /**
  51. * struct snd_dmaengine_dai_dma_data - DAI DMA configuration data
  52. * @addr: Address of the DAI data source or destination register.
  53. * @addr_width: Width of the DAI data source or destination register.
  54. * @maxburst: Maximum number of words(note: words, as in units of the
  55. * src_addr_width member, not bytes) that can be send to or received from the
  56. * DAI in one burst.
  57. * @filter_data: Custom DMA channel filter data, this will usually be used when
  58. * requesting the DMA channel.
  59. * @chan_name: Custom channel name to use when requesting DMA channel.
  60. * @fifo_size: FIFO size of the DAI controller in bytes
  61. * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now
  62. * @peripheral_config: peripheral configuration for programming peripheral
  63. * for dmaengine transfer
  64. * @peripheral_size: peripheral configuration buffer size
  65. */
  66. struct snd_dmaengine_dai_dma_data {
  67. dma_addr_t addr;
  68. enum dma_slave_buswidth addr_width;
  69. u32 maxburst;
  70. void *filter_data;
  71. const char *chan_name;
  72. unsigned int fifo_size;
  73. unsigned int flags;
  74. void *peripheral_config;
  75. size_t peripheral_size;
  76. };
  77. void snd_dmaengine_pcm_set_config_from_dai_data(
  78. const struct snd_pcm_substream *substream,
  79. const struct snd_dmaengine_dai_dma_data *dma_data,
  80. struct dma_slave_config *config);
  81. int snd_dmaengine_pcm_refine_runtime_hwparams(
  82. struct snd_pcm_substream *substream,
  83. struct snd_dmaengine_dai_dma_data *dma_data,
  84. struct snd_pcm_hardware *hw,
  85. struct dma_chan *chan);
  86. /*
  87. * Try to request the DMA channel using compat_request_channel or
  88. * compat_filter_fn if it couldn't be requested through devicetree.
  89. */
  90. #define SND_DMAENGINE_PCM_FLAG_COMPAT BIT(0)
  91. /*
  92. * Don't try to request the DMA channels through devicetree. This flag only
  93. * makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well.
  94. */
  95. #define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1)
  96. /*
  97. * The PCM is half duplex and the DMA channel is shared between capture and
  98. * playback.
  99. */
  100. #define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3)
  101. /**
  102. * struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM
  103. * @prepare_slave_config: Callback used to fill in the DMA slave_config for a
  104. * PCM substream. Will be called from the PCM drivers hwparams callback.
  105. * @compat_request_channel: Callback to request a DMA channel for platforms
  106. * which do not use devicetree.
  107. * @process: Callback used to apply processing on samples transferred from/to
  108. * user space.
  109. * @name: Component name. If null, dev_name will be used.
  110. * @compat_filter_fn: Will be used as the filter function when requesting a
  111. * channel for platforms which do not use devicetree. The filter parameter
  112. * will be the DAI's DMA data.
  113. * @dma_dev: If set, request DMA channel on this device rather than the DAI
  114. * device.
  115. * @chan_names: If set, these custom DMA channel names will be requested at
  116. * registration time.
  117. * @pcm_hardware: snd_pcm_hardware struct to be used for the PCM.
  118. * @prealloc_buffer_size: Size of the preallocated audio buffer.
  119. *
  120. * Note: If both compat_request_channel and compat_filter_fn are set
  121. * compat_request_channel will be used to request the channel and
  122. * compat_filter_fn will be ignored. Otherwise the channel will be requested
  123. * using dma_request_channel with compat_filter_fn as the filter function.
  124. */
  125. struct snd_dmaengine_pcm_config {
  126. int (*prepare_slave_config)(struct snd_pcm_substream *substream,
  127. struct snd_pcm_hw_params *params,
  128. struct dma_slave_config *slave_config);
  129. struct dma_chan *(*compat_request_channel)(
  130. struct snd_soc_pcm_runtime *rtd,
  131. struct snd_pcm_substream *substream);
  132. int (*process)(struct snd_pcm_substream *substream,
  133. int channel, unsigned long hwoff,
  134. unsigned long bytes);
  135. const char *name;
  136. dma_filter_fn compat_filter_fn;
  137. struct device *dma_dev;
  138. const char *chan_names[SNDRV_PCM_STREAM_LAST + 1];
  139. const struct snd_pcm_hardware *pcm_hardware;
  140. unsigned int prealloc_buffer_size;
  141. };
  142. int snd_dmaengine_pcm_register(struct device *dev,
  143. const struct snd_dmaengine_pcm_config *config,
  144. unsigned int flags);
  145. void snd_dmaengine_pcm_unregister(struct device *dev);
  146. int devm_snd_dmaengine_pcm_register(struct device *dev,
  147. const struct snd_dmaengine_pcm_config *config,
  148. unsigned int flags);
  149. int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
  150. struct snd_pcm_hw_params *params,
  151. struct dma_slave_config *slave_config);
  152. #define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm"
  153. struct dmaengine_pcm {
  154. struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1];
  155. const struct snd_dmaengine_pcm_config *config;
  156. struct snd_soc_component component;
  157. unsigned int flags;
  158. };
  159. static inline struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p)
  160. {
  161. return container_of(p, struct dmaengine_pcm, component);
  162. }
  163. #endif