| .. | .. |
|---|
| 25 | 25 | */ |
|---|
| 26 | 26 | #define SND_DMAENGINE_PCM_FLAG_NO_RESIDUE BIT(31) |
|---|
| 27 | 27 | |
|---|
| 28 | | -struct dmaengine_pcm { |
|---|
| 29 | | - struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1]; |
|---|
| 30 | | - const struct snd_dmaengine_pcm_config *config; |
|---|
| 31 | | - struct snd_soc_component component; |
|---|
| 32 | | - unsigned int flags; |
|---|
| 33 | | -}; |
|---|
| 34 | | - |
|---|
| 35 | | -static struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p) |
|---|
| 36 | | -{ |
|---|
| 37 | | - return container_of(p, struct dmaengine_pcm, component); |
|---|
| 38 | | -} |
|---|
| 39 | | - |
|---|
| 40 | 28 | static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm, |
|---|
| 41 | 29 | struct snd_pcm_substream *substream) |
|---|
| 42 | 30 | { |
|---|
| .. | .. |
|---|
| 62 | 50 | int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, |
|---|
| 63 | 51 | struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) |
|---|
| 64 | 52 | { |
|---|
| 65 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 53 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
|---|
| 66 | 54 | struct snd_dmaengine_dai_dma_data *dma_data; |
|---|
| 67 | 55 | int ret; |
|---|
| 68 | 56 | |
|---|
| 69 | | - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
|---|
| 57 | + if (rtd->num_cpus > 1) { |
|---|
| 58 | + dev_err(rtd->dev, |
|---|
| 59 | + "%s doesn't support Multi CPU yet\n", __func__); |
|---|
| 60 | + return -EINVAL; |
|---|
| 61 | + } |
|---|
| 62 | + |
|---|
| 63 | + dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); |
|---|
| 70 | 64 | |
|---|
| 71 | 65 | ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config); |
|---|
| 72 | 66 | if (ret) |
|---|
| .. | .. |
|---|
| 79 | 73 | } |
|---|
| 80 | 74 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_prepare_slave_config); |
|---|
| 81 | 75 | |
|---|
| 82 | | -static int dmaengine_pcm_hw_params(struct snd_pcm_substream *substream, |
|---|
| 83 | | - struct snd_pcm_hw_params *params) |
|---|
| 76 | +static int dmaengine_pcm_hw_params(struct snd_soc_component *component, |
|---|
| 77 | + struct snd_pcm_substream *substream, |
|---|
| 78 | + struct snd_pcm_hw_params *params) |
|---|
| 84 | 79 | { |
|---|
| 85 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 86 | | - struct snd_soc_component *component = |
|---|
| 87 | | - snd_soc_rtdcom_lookup(rtd, SND_DMAENGINE_PCM_DRV_NAME); |
|---|
| 88 | 80 | struct dmaengine_pcm *pcm = soc_component_to_pcm(component); |
|---|
| 89 | 81 | struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); |
|---|
| 90 | 82 | int (*prepare_slave_config)(struct snd_pcm_substream *substream, |
|---|
| .. | .. |
|---|
| 110 | 102 | return ret; |
|---|
| 111 | 103 | } |
|---|
| 112 | 104 | |
|---|
| 113 | | - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); |
|---|
| 105 | + return 0; |
|---|
| 114 | 106 | } |
|---|
| 115 | 107 | |
|---|
| 116 | | -static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substream) |
|---|
| 108 | +static int |
|---|
| 109 | +dmaengine_pcm_set_runtime_hwparams(struct snd_soc_component *component, |
|---|
| 110 | + struct snd_pcm_substream *substream) |
|---|
| 117 | 111 | { |
|---|
| 118 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 119 | | - struct snd_soc_component *component = |
|---|
| 120 | | - snd_soc_rtdcom_lookup(rtd, SND_DMAENGINE_PCM_DRV_NAME); |
|---|
| 112 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
|---|
| 121 | 113 | struct dmaengine_pcm *pcm = soc_component_to_pcm(component); |
|---|
| 122 | 114 | struct device *dma_dev = dmaengine_dma_dev(pcm, substream); |
|---|
| 123 | 115 | struct dma_chan *chan = pcm->chan[substream->stream]; |
|---|
| 124 | 116 | struct snd_dmaengine_dai_dma_data *dma_data; |
|---|
| 125 | | - struct dma_slave_caps dma_caps; |
|---|
| 126 | 117 | struct snd_pcm_hardware hw; |
|---|
| 127 | | - u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | |
|---|
| 128 | | - BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | |
|---|
| 129 | | - BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); |
|---|
| 130 | | - snd_pcm_format_t i; |
|---|
| 131 | | - int ret; |
|---|
| 118 | + |
|---|
| 119 | + if (rtd->num_cpus > 1) { |
|---|
| 120 | + dev_err(rtd->dev, |
|---|
| 121 | + "%s doesn't support Multi CPU yet\n", __func__); |
|---|
| 122 | + return -EINVAL; |
|---|
| 123 | + } |
|---|
| 132 | 124 | |
|---|
| 133 | 125 | if (pcm->config && pcm->config->pcm_hardware) |
|---|
| 134 | 126 | return snd_soc_set_runtime_hwparams(substream, |
|---|
| 135 | 127 | pcm->config->pcm_hardware); |
|---|
| 136 | 128 | |
|---|
| 137 | | - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
|---|
| 129 | + dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); |
|---|
| 138 | 130 | |
|---|
| 139 | 131 | memset(&hw, 0, sizeof(hw)); |
|---|
| 140 | 132 | hw.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | |
|---|
| .. | .. |
|---|
| 149 | 141 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) |
|---|
| 150 | 142 | hw.info |= SNDRV_PCM_INFO_BATCH; |
|---|
| 151 | 143 | |
|---|
| 152 | | - ret = dma_get_slave_caps(chan, &dma_caps); |
|---|
| 153 | | - if (ret == 0) { |
|---|
| 154 | | - if (dma_caps.cmd_pause && dma_caps.cmd_resume) |
|---|
| 155 | | - hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; |
|---|
| 156 | | - if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT) |
|---|
| 157 | | - hw.info |= SNDRV_PCM_INFO_BATCH; |
|---|
| 158 | | - |
|---|
| 159 | | - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
|---|
| 160 | | - addr_widths = dma_caps.dst_addr_widths; |
|---|
| 161 | | - else |
|---|
| 162 | | - addr_widths = dma_caps.src_addr_widths; |
|---|
| 163 | | - } |
|---|
| 164 | | - |
|---|
| 165 | | - /* |
|---|
| 166 | | - * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep |
|---|
| 167 | | - * hw.formats set to 0, meaning no restrictions are in place. |
|---|
| 168 | | - * In this case it's the responsibility of the DAI driver to |
|---|
| 169 | | - * provide the supported format information. |
|---|
| 144 | + /** |
|---|
| 145 | + * FIXME: Remove the return value check to align with the code |
|---|
| 146 | + * before adding snd_dmaengine_pcm_refine_runtime_hwparams |
|---|
| 147 | + * function. |
|---|
| 170 | 148 | */ |
|---|
| 171 | | - if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)) |
|---|
| 172 | | - /* |
|---|
| 173 | | - * Prepare formats mask for valid/allowed sample types. If the |
|---|
| 174 | | - * dma does not have support for the given physical word size, |
|---|
| 175 | | - * it needs to be masked out so user space can not use the |
|---|
| 176 | | - * format which produces corrupted audio. |
|---|
| 177 | | - * In case the dma driver does not implement the slave_caps the |
|---|
| 178 | | - * default assumption is that it supports 1, 2 and 4 bytes |
|---|
| 179 | | - * widths. |
|---|
| 180 | | - */ |
|---|
| 181 | | - for (i = SNDRV_PCM_FORMAT_FIRST; i <= SNDRV_PCM_FORMAT_LAST; i++) { |
|---|
| 182 | | - int bits = snd_pcm_format_physical_width(i); |
|---|
| 183 | | - |
|---|
| 184 | | - /* |
|---|
| 185 | | - * Enable only samples with DMA supported physical |
|---|
| 186 | | - * widths |
|---|
| 187 | | - */ |
|---|
| 188 | | - switch (bits) { |
|---|
| 189 | | - case 8: |
|---|
| 190 | | - case 16: |
|---|
| 191 | | - case 24: |
|---|
| 192 | | - case 32: |
|---|
| 193 | | - case 64: |
|---|
| 194 | | - if (addr_widths & (1 << (bits / 8))) |
|---|
| 195 | | - hw.formats |= pcm_format_to_bits(i); |
|---|
| 196 | | - break; |
|---|
| 197 | | - default: |
|---|
| 198 | | - /* Unsupported types */ |
|---|
| 199 | | - break; |
|---|
| 200 | | - } |
|---|
| 201 | | - } |
|---|
| 149 | + snd_dmaengine_pcm_refine_runtime_hwparams(substream, |
|---|
| 150 | + dma_data, |
|---|
| 151 | + &hw, |
|---|
| 152 | + chan); |
|---|
| 202 | 153 | |
|---|
| 203 | 154 | return snd_soc_set_runtime_hwparams(substream, &hw); |
|---|
| 204 | 155 | } |
|---|
| 205 | 156 | |
|---|
| 206 | | -static int dmaengine_pcm_open(struct snd_pcm_substream *substream) |
|---|
| 157 | +static int dmaengine_pcm_open(struct snd_soc_component *component, |
|---|
| 158 | + struct snd_pcm_substream *substream) |
|---|
| 207 | 159 | { |
|---|
| 208 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 209 | | - struct snd_soc_component *component = |
|---|
| 210 | | - snd_soc_rtdcom_lookup(rtd, SND_DMAENGINE_PCM_DRV_NAME); |
|---|
| 211 | 160 | struct dmaengine_pcm *pcm = soc_component_to_pcm(component); |
|---|
| 212 | 161 | struct dma_chan *chan = pcm->chan[substream->stream]; |
|---|
| 213 | 162 | int ret; |
|---|
| 214 | 163 | |
|---|
| 215 | | - ret = dmaengine_pcm_set_runtime_hwparams(substream); |
|---|
| 164 | + ret = dmaengine_pcm_set_runtime_hwparams(component, substream); |
|---|
| 216 | 165 | if (ret) |
|---|
| 217 | 166 | return ret; |
|---|
| 218 | 167 | |
|---|
| 219 | 168 | return snd_dmaengine_pcm_open(substream, chan); |
|---|
| 220 | 169 | } |
|---|
| 221 | 170 | |
|---|
| 171 | +static int dmaengine_pcm_close(struct snd_soc_component *component, |
|---|
| 172 | + struct snd_pcm_substream *substream) |
|---|
| 173 | +{ |
|---|
| 174 | + return snd_dmaengine_pcm_close(substream); |
|---|
| 175 | +} |
|---|
| 176 | + |
|---|
| 177 | +static int dmaengine_pcm_trigger(struct snd_soc_component *component, |
|---|
| 178 | + struct snd_pcm_substream *substream, int cmd) |
|---|
| 179 | +{ |
|---|
| 180 | + return snd_dmaengine_pcm_trigger(substream, cmd); |
|---|
| 181 | +} |
|---|
| 182 | + |
|---|
| 222 | 183 | static struct dma_chan *dmaengine_pcm_compat_request_channel( |
|---|
| 184 | + struct snd_soc_component *component, |
|---|
| 223 | 185 | struct snd_soc_pcm_runtime *rtd, |
|---|
| 224 | 186 | struct snd_pcm_substream *substream) |
|---|
| 225 | 187 | { |
|---|
| 226 | | - struct snd_soc_component *component = |
|---|
| 227 | | - snd_soc_rtdcom_lookup(rtd, SND_DMAENGINE_PCM_DRV_NAME); |
|---|
| 228 | 188 | struct dmaengine_pcm *pcm = soc_component_to_pcm(component); |
|---|
| 229 | 189 | struct snd_dmaengine_dai_dma_data *dma_data; |
|---|
| 230 | 190 | dma_filter_fn fn = NULL; |
|---|
| 231 | 191 | |
|---|
| 232 | | - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
|---|
| 192 | + if (rtd->num_cpus > 1) { |
|---|
| 193 | + dev_err(rtd->dev, |
|---|
| 194 | + "%s doesn't support Multi CPU yet\n", __func__); |
|---|
| 195 | + return NULL; |
|---|
| 196 | + } |
|---|
| 197 | + |
|---|
| 198 | + dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); |
|---|
| 233 | 199 | |
|---|
| 234 | 200 | if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) && pcm->chan[0]) |
|---|
| 235 | 201 | return pcm->chan[0]; |
|---|
| .. | .. |
|---|
| 262 | 228 | return true; |
|---|
| 263 | 229 | } |
|---|
| 264 | 230 | |
|---|
| 265 | | -static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) |
|---|
| 231 | +static int dmaengine_pcm_new(struct snd_soc_component *component, |
|---|
| 232 | + struct snd_soc_pcm_runtime *rtd) |
|---|
| 266 | 233 | { |
|---|
| 267 | | - struct snd_soc_component *component = |
|---|
| 268 | | - snd_soc_rtdcom_lookup(rtd, SND_DMAENGINE_PCM_DRV_NAME); |
|---|
| 269 | 234 | struct dmaengine_pcm *pcm = soc_component_to_pcm(component); |
|---|
| 270 | 235 | const struct snd_dmaengine_pcm_config *config = pcm->config; |
|---|
| 271 | 236 | struct device *dev = component->dev; |
|---|
| 272 | | - struct snd_dmaengine_dai_dma_data *dma_data; |
|---|
| 273 | 237 | struct snd_pcm_substream *substream; |
|---|
| 274 | 238 | size_t prealloc_buffer_size; |
|---|
| 275 | 239 | size_t max_buffer_size; |
|---|
| 276 | 240 | unsigned int i; |
|---|
| 277 | | - int ret; |
|---|
| 278 | 241 | |
|---|
| 279 | 242 | if (config && config->prealloc_buffer_size) { |
|---|
| 280 | 243 | prealloc_buffer_size = config->prealloc_buffer_size; |
|---|
| .. | .. |
|---|
| 284 | 247 | max_buffer_size = SIZE_MAX; |
|---|
| 285 | 248 | } |
|---|
| 286 | 249 | |
|---|
| 287 | | - for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { |
|---|
| 250 | + for_each_pcm_streams(i) { |
|---|
| 288 | 251 | substream = rtd->pcm->streams[i].substream; |
|---|
| 289 | 252 | if (!substream) |
|---|
| 290 | 253 | continue; |
|---|
| 291 | 254 | |
|---|
| 292 | | - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
|---|
| 293 | | - |
|---|
| 294 | | - if (!pcm->chan[i] && |
|---|
| 295 | | - (pcm->flags & SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) |
|---|
| 255 | + if (!pcm->chan[i] && config && config->chan_names[i]) |
|---|
| 296 | 256 | pcm->chan[i] = dma_request_slave_channel(dev, |
|---|
| 297 | | - dma_data->chan_name); |
|---|
| 257 | + config->chan_names[i]); |
|---|
| 298 | 258 | |
|---|
| 299 | 259 | if (!pcm->chan[i] && (pcm->flags & SND_DMAENGINE_PCM_FLAG_COMPAT)) { |
|---|
| 300 | | - pcm->chan[i] = dmaengine_pcm_compat_request_channel(rtd, |
|---|
| 301 | | - substream); |
|---|
| 260 | + pcm->chan[i] = dmaengine_pcm_compat_request_channel( |
|---|
| 261 | + component, rtd, substream); |
|---|
| 302 | 262 | } |
|---|
| 303 | 263 | |
|---|
| 304 | 264 | if (!pcm->chan[i]) { |
|---|
| .. | .. |
|---|
| 307 | 267 | return -EINVAL; |
|---|
| 308 | 268 | } |
|---|
| 309 | 269 | |
|---|
| 310 | | - ret = snd_pcm_lib_preallocate_pages(substream, |
|---|
| 270 | + snd_pcm_set_managed_buffer(substream, |
|---|
| 311 | 271 | SNDRV_DMA_TYPE_DEV_IRAM, |
|---|
| 312 | 272 | dmaengine_dma_dev(pcm, substream), |
|---|
| 313 | 273 | prealloc_buffer_size, |
|---|
| 314 | 274 | max_buffer_size); |
|---|
| 315 | | - if (ret) |
|---|
| 316 | | - return ret; |
|---|
| 317 | 275 | |
|---|
| 318 | 276 | if (!dmaengine_pcm_can_report_residue(dev, pcm->chan[i])) |
|---|
| 319 | 277 | pcm->flags |= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE; |
|---|
| 320 | 278 | |
|---|
| 321 | 279 | if (rtd->pcm->streams[i].pcm->name[0] == '\0') { |
|---|
| 322 | | - strncpy(rtd->pcm->streams[i].pcm->name, |
|---|
| 323 | | - rtd->pcm->streams[i].pcm->id, |
|---|
| 324 | | - sizeof(rtd->pcm->streams[i].pcm->name)); |
|---|
| 280 | + strscpy_pad(rtd->pcm->streams[i].pcm->name, |
|---|
| 281 | + rtd->pcm->streams[i].pcm->id, |
|---|
| 282 | + sizeof(rtd->pcm->streams[i].pcm->name)); |
|---|
| 325 | 283 | } |
|---|
| 326 | 284 | } |
|---|
| 327 | 285 | |
|---|
| .. | .. |
|---|
| 329 | 287 | } |
|---|
| 330 | 288 | |
|---|
| 331 | 289 | static snd_pcm_uframes_t dmaengine_pcm_pointer( |
|---|
| 290 | + struct snd_soc_component *component, |
|---|
| 332 | 291 | struct snd_pcm_substream *substream) |
|---|
| 333 | 292 | { |
|---|
| 334 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 335 | | - struct snd_soc_component *component = |
|---|
| 336 | | - snd_soc_rtdcom_lookup(rtd, SND_DMAENGINE_PCM_DRV_NAME); |
|---|
| 337 | 293 | struct dmaengine_pcm *pcm = soc_component_to_pcm(component); |
|---|
| 338 | 294 | |
|---|
| 339 | 295 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) |
|---|
| .. | .. |
|---|
| 342 | 298 | return snd_dmaengine_pcm_pointer(substream); |
|---|
| 343 | 299 | } |
|---|
| 344 | 300 | |
|---|
| 345 | | -static int dmaengine_copy_user(struct snd_pcm_substream *substream, |
|---|
| 301 | +static int dmaengine_copy_user(struct snd_soc_component *component, |
|---|
| 302 | + struct snd_pcm_substream *substream, |
|---|
| 346 | 303 | int channel, unsigned long hwoff, |
|---|
| 347 | 304 | void __user *buf, unsigned long bytes) |
|---|
| 348 | 305 | { |
|---|
| 349 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 350 | | - struct snd_soc_component *component = |
|---|
| 351 | | - snd_soc_rtdcom_lookup(rtd, SND_DMAENGINE_PCM_DRV_NAME); |
|---|
| 352 | 306 | struct snd_pcm_runtime *runtime = substream->runtime; |
|---|
| 353 | 307 | struct dmaengine_pcm *pcm = soc_component_to_pcm(component); |
|---|
| 354 | 308 | int (*process)(struct snd_pcm_substream *substream, |
|---|
| .. | .. |
|---|
| 376 | 330 | return 0; |
|---|
| 377 | 331 | } |
|---|
| 378 | 332 | |
|---|
| 379 | | -static const struct snd_pcm_ops dmaengine_pcm_ops = { |
|---|
| 380 | | - .open = dmaengine_pcm_open, |
|---|
| 381 | | - .close = snd_dmaengine_pcm_close, |
|---|
| 382 | | - .ioctl = snd_pcm_lib_ioctl, |
|---|
| 383 | | - .hw_params = dmaengine_pcm_hw_params, |
|---|
| 384 | | - .hw_free = snd_pcm_lib_free_pages, |
|---|
| 385 | | - .trigger = snd_dmaengine_pcm_trigger, |
|---|
| 386 | | - .pointer = dmaengine_pcm_pointer, |
|---|
| 387 | | -}; |
|---|
| 388 | | - |
|---|
| 389 | | -static const struct snd_pcm_ops dmaengine_pcm_process_ops = { |
|---|
| 390 | | - .open = dmaengine_pcm_open, |
|---|
| 391 | | - .close = snd_dmaengine_pcm_close, |
|---|
| 392 | | - .ioctl = snd_pcm_lib_ioctl, |
|---|
| 393 | | - .hw_params = dmaengine_pcm_hw_params, |
|---|
| 394 | | - .hw_free = snd_pcm_lib_free_pages, |
|---|
| 395 | | - .trigger = snd_dmaengine_pcm_trigger, |
|---|
| 396 | | - .pointer = dmaengine_pcm_pointer, |
|---|
| 397 | | - .copy_user = dmaengine_copy_user, |
|---|
| 398 | | -}; |
|---|
| 399 | | - |
|---|
| 400 | 333 | static const struct snd_soc_component_driver dmaengine_pcm_component = { |
|---|
| 401 | 334 | .name = SND_DMAENGINE_PCM_DRV_NAME, |
|---|
| 402 | 335 | .probe_order = SND_SOC_COMP_ORDER_LATE, |
|---|
| 403 | | - .ops = &dmaengine_pcm_ops, |
|---|
| 404 | | - .pcm_new = dmaengine_pcm_new, |
|---|
| 336 | + .open = dmaengine_pcm_open, |
|---|
| 337 | + .close = dmaengine_pcm_close, |
|---|
| 338 | + .hw_params = dmaengine_pcm_hw_params, |
|---|
| 339 | + .trigger = dmaengine_pcm_trigger, |
|---|
| 340 | + .pointer = dmaengine_pcm_pointer, |
|---|
| 341 | + .pcm_construct = dmaengine_pcm_new, |
|---|
| 405 | 342 | }; |
|---|
| 406 | 343 | |
|---|
| 407 | 344 | static const struct snd_soc_component_driver dmaengine_pcm_component_process = { |
|---|
| 408 | 345 | .name = SND_DMAENGINE_PCM_DRV_NAME, |
|---|
| 409 | 346 | .probe_order = SND_SOC_COMP_ORDER_LATE, |
|---|
| 410 | | - .ops = &dmaengine_pcm_process_ops, |
|---|
| 411 | | - .pcm_new = dmaengine_pcm_new, |
|---|
| 347 | + .open = dmaengine_pcm_open, |
|---|
| 348 | + .close = dmaengine_pcm_close, |
|---|
| 349 | + .hw_params = dmaengine_pcm_hw_params, |
|---|
| 350 | + .trigger = dmaengine_pcm_trigger, |
|---|
| 351 | + .pointer = dmaengine_pcm_pointer, |
|---|
| 352 | + .copy_user = dmaengine_copy_user, |
|---|
| 353 | + .pcm_construct = dmaengine_pcm_new, |
|---|
| 412 | 354 | }; |
|---|
| 413 | 355 | |
|---|
| 414 | 356 | static const char * const dmaengine_pcm_dma_channel_names[] = { |
|---|
| .. | .. |
|---|
| 423 | 365 | const char *name; |
|---|
| 424 | 366 | struct dma_chan *chan; |
|---|
| 425 | 367 | |
|---|
| 426 | | - if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT | |
|---|
| 427 | | - SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) || |
|---|
| 428 | | - !dev->of_node) |
|---|
| 368 | + if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_DT) || (!dev->of_node && |
|---|
| 369 | + !(config && config->dma_dev && config->dma_dev->of_node))) |
|---|
| 429 | 370 | return 0; |
|---|
| 430 | 371 | |
|---|
| 431 | 372 | if (config && config->dma_dev) { |
|---|
| .. | .. |
|---|
| 440 | 381 | dev = config->dma_dev; |
|---|
| 441 | 382 | } |
|---|
| 442 | 383 | |
|---|
| 443 | | - for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; |
|---|
| 444 | | - i++) { |
|---|
| 384 | + for_each_pcm_streams(i) { |
|---|
| 445 | 385 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) |
|---|
| 446 | 386 | name = "rx-tx"; |
|---|
| 447 | 387 | else |
|---|
| 448 | 388 | name = dmaengine_pcm_dma_channel_names[i]; |
|---|
| 449 | 389 | if (config && config->chan_names[i]) |
|---|
| 450 | 390 | name = config->chan_names[i]; |
|---|
| 451 | | - chan = dma_request_slave_channel_reason(dev, name); |
|---|
| 391 | + chan = dma_request_chan(dev, name); |
|---|
| 452 | 392 | if (IS_ERR(chan)) { |
|---|
| 393 | + /* |
|---|
| 394 | + * Only report probe deferral errors, channels |
|---|
| 395 | + * might not be present for devices that |
|---|
| 396 | + * support only TX or only RX. |
|---|
| 397 | + */ |
|---|
| 453 | 398 | if (PTR_ERR(chan) == -EPROBE_DEFER) |
|---|
| 454 | 399 | return -EPROBE_DEFER; |
|---|
| 455 | 400 | pcm->chan[i] = NULL; |
|---|
| .. | .. |
|---|
| 470 | 415 | { |
|---|
| 471 | 416 | unsigned int i; |
|---|
| 472 | 417 | |
|---|
| 473 | | - for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; |
|---|
| 474 | | - i++) { |
|---|
| 418 | + for_each_pcm_streams(i) { |
|---|
| 475 | 419 | if (!pcm->chan[i]) |
|---|
| 476 | 420 | continue; |
|---|
| 477 | 421 | dma_release_channel(pcm->chan[i]); |
|---|
| .. | .. |
|---|
| 489 | 433 | int snd_dmaengine_pcm_register(struct device *dev, |
|---|
| 490 | 434 | const struct snd_dmaengine_pcm_config *config, unsigned int flags) |
|---|
| 491 | 435 | { |
|---|
| 436 | + const struct snd_soc_component_driver *driver; |
|---|
| 492 | 437 | struct dmaengine_pcm *pcm; |
|---|
| 493 | 438 | int ret; |
|---|
| 494 | 439 | |
|---|
| .. | .. |
|---|
| 507 | 452 | goto err_free_dma; |
|---|
| 508 | 453 | |
|---|
| 509 | 454 | if (config && config->process) |
|---|
| 510 | | - ret = snd_soc_add_component(dev, &pcm->component, |
|---|
| 511 | | - &dmaengine_pcm_component_process, |
|---|
| 512 | | - NULL, 0); |
|---|
| 455 | + driver = &dmaengine_pcm_component_process; |
|---|
| 513 | 456 | else |
|---|
| 514 | | - ret = snd_soc_add_component(dev, &pcm->component, |
|---|
| 515 | | - &dmaengine_pcm_component, NULL, 0); |
|---|
| 457 | + driver = &dmaengine_pcm_component; |
|---|
| 458 | + |
|---|
| 459 | + ret = snd_soc_component_initialize(&pcm->component, driver, dev); |
|---|
| 460 | + if (ret) |
|---|
| 461 | + goto err_free_dma; |
|---|
| 462 | + |
|---|
| 463 | + ret = snd_soc_add_component(&pcm->component, NULL, 0); |
|---|
| 516 | 464 | if (ret) |
|---|
| 517 | 465 | goto err_free_dma; |
|---|
| 518 | 466 | |
|---|
| .. | .. |
|---|
| 543 | 491 | |
|---|
| 544 | 492 | pcm = soc_component_to_pcm(component); |
|---|
| 545 | 493 | |
|---|
| 546 | | - snd_soc_unregister_component(dev); |
|---|
| 494 | + snd_soc_unregister_component_by_driver(dev, component->driver); |
|---|
| 547 | 495 | dmaengine_pcm_release_chan(pcm); |
|---|
| 548 | 496 | kfree(pcm); |
|---|
| 549 | 497 | } |
|---|