~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/arm/pxa2xx-pcm-lib.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 
  3 #include <linux/slab.h>
  4 #include <linux/module.h>
  5 #include <linux/dma-mapping.h>
  6 #include <linux/dmaengine.h>
  7 #include <linux/dma/pxa-dma.h>
  8 
  9 #include <sound/core.h>
 10 #include <sound/pcm.h>
 11 #include <sound/pcm_params.h>
 12 #include <sound/pxa2xx-lib.h>
 13 #include <sound/dmaengine_pcm.h>
 14 
 15 static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
 16         .info                   = SNDRV_PCM_INFO_MMAP |
 17                                   SNDRV_PCM_INFO_MMAP_VALID |
 18                                   SNDRV_PCM_INFO_INTERLEAVED |
 19                                   SNDRV_PCM_INFO_PAUSE |
 20                                   SNDRV_PCM_INFO_RESUME,
 21         .formats                = SNDRV_PCM_FMTBIT_S16_LE |
 22                                   SNDRV_PCM_FMTBIT_S24_LE |
 23                                   SNDRV_PCM_FMTBIT_S32_LE,
 24         .period_bytes_min       = 32,
 25         .period_bytes_max       = 8192 - 32,
 26         .periods_min            = 1,
 27         .periods_max            = 256,
 28         .buffer_bytes_max       = 128 * 1024,
 29         .fifo_size              = 32,
 30 };
 31 
 32 int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
 33                          struct snd_pcm_hw_params *params)
 34 {
 35         struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
 36         struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 37         struct snd_dmaengine_dai_dma_data *dma_params;
 38         struct dma_slave_config config;
 39         int ret;
 40 
 41         dma_params = snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream);
 42         if (!dma_params)
 43                 return 0;
 44 
 45         ret = snd_hwparams_to_dma_slave_config(substream, params, &config);
 46         if (ret)
 47                 return ret;
 48 
 49         snd_dmaengine_pcm_set_config_from_dai_data(substream,
 50                         snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream),
 51                         &config);
 52 
 53         ret = dmaengine_slave_config(chan, &config);
 54         if (ret)
 55                 return ret;
 56 
 57         return 0;
 58 }
 59 EXPORT_SYMBOL(pxa2xx_pcm_hw_params);
 60 
 61 int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 62 {
 63         return snd_dmaengine_pcm_trigger(substream, cmd);
 64 }
 65 EXPORT_SYMBOL(pxa2xx_pcm_trigger);
 66 
 67 snd_pcm_uframes_t
 68 pxa2xx_pcm_pointer(struct snd_pcm_substream *substream)
 69 {
 70         return snd_dmaengine_pcm_pointer(substream);
 71 }
 72 EXPORT_SYMBOL(pxa2xx_pcm_pointer);
 73 
 74 int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
 75 {
 76         return 0;
 77 }
 78 EXPORT_SYMBOL(pxa2xx_pcm_prepare);
 79 
 80 int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
 81 {
 82         struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 83         struct snd_pcm_runtime *runtime = substream->runtime;
 84         struct snd_dmaengine_dai_dma_data *dma_params;
 85         int ret;
 86 
 87         runtime->hw = pxa2xx_pcm_hardware;
 88 
 89         dma_params = snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream);
 90         if (!dma_params)
 91                 return 0;
 92 
 93         /*
 94          * For mysterious reasons (and despite what the manual says)
 95          * playback samples are lost if the DMA count is not a multiple
 96          * of the DMA burst size.  Let's add a rule to enforce that.
 97          */
 98         ret = snd_pcm_hw_constraint_step(runtime, 0,
 99                 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
100         if (ret)
101                 return ret;
102 
103         ret = snd_pcm_hw_constraint_step(runtime, 0,
104                 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
105         if (ret)
106                 return ret;
107 
108         ret = snd_pcm_hw_constraint_integer(runtime,
109                                             SNDRV_PCM_HW_PARAM_PERIODS);
110         if (ret < 0)
111                 return ret;
112 
113         return snd_dmaengine_pcm_open(
114                 substream, dma_request_slave_channel(snd_soc_rtd_to_cpu(rtd, 0)->dev,
115                                                      dma_params->chan_name));
116 }
117 EXPORT_SYMBOL(pxa2xx_pcm_open);
118 
119 int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
120 {
121         return snd_dmaengine_pcm_close_release_chan(substream);
122 }
123 EXPORT_SYMBOL(pxa2xx_pcm_close);
124 
125 int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm)
126 {
127         size_t size = pxa2xx_pcm_hardware.buffer_bytes_max;
128 
129         return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
130                                             pcm->card->dev, size);
131 }
132 EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer);
133 
134 int pxa2xx_soc_pcm_new(struct snd_soc_component *component,
135                        struct snd_soc_pcm_runtime *rtd)
136 {
137         struct snd_card *card = rtd->card->snd_card;
138         struct snd_pcm *pcm = rtd->pcm;
139         int ret;
140 
141         ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
142         if (ret)
143                 return ret;
144 
145         return pxa2xx_pcm_preallocate_dma_buffer(pcm);
146 }
147 EXPORT_SYMBOL(pxa2xx_soc_pcm_new);
148 
149 int pxa2xx_soc_pcm_open(struct snd_soc_component *component,
150                         struct snd_pcm_substream *substream)
151 {
152         return pxa2xx_pcm_open(substream);
153 }
154 EXPORT_SYMBOL(pxa2xx_soc_pcm_open);
155 
156 int pxa2xx_soc_pcm_close(struct snd_soc_component *component,
157                          struct snd_pcm_substream *substream)
158 {
159         return pxa2xx_pcm_close(substream);
160 }
161 EXPORT_SYMBOL(pxa2xx_soc_pcm_close);
162 
163 int pxa2xx_soc_pcm_hw_params(struct snd_soc_component *component,
164                              struct snd_pcm_substream *substream,
165                              struct snd_pcm_hw_params *params)
166 {
167         return pxa2xx_pcm_hw_params(substream, params);
168 }
169 EXPORT_SYMBOL(pxa2xx_soc_pcm_hw_params);
170 
171 int pxa2xx_soc_pcm_prepare(struct snd_soc_component *component,
172                            struct snd_pcm_substream *substream)
173 {
174         return pxa2xx_pcm_prepare(substream);
175 }
176 EXPORT_SYMBOL(pxa2xx_soc_pcm_prepare);
177 
178 int pxa2xx_soc_pcm_trigger(struct snd_soc_component *component,
179                            struct snd_pcm_substream *substream, int cmd)
180 {
181         return pxa2xx_pcm_trigger(substream, cmd);
182 }
183 EXPORT_SYMBOL(pxa2xx_soc_pcm_trigger);
184 
185 snd_pcm_uframes_t
186 pxa2xx_soc_pcm_pointer(struct snd_soc_component *component,
187                        struct snd_pcm_substream *substream)
188 {
189         return pxa2xx_pcm_pointer(substream);
190 }
191 EXPORT_SYMBOL(pxa2xx_soc_pcm_pointer);
192 
193 MODULE_AUTHOR("Nicolas Pitre");
194 MODULE_DESCRIPTION("Intel PXA2xx sound library");
195 MODULE_LICENSE("GPL");
196 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php