1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Freescale ASRC ALSA SoC Platform (DMA) driver 4 // 5 // Copyright (C) 2014 Freescale Semiconductor, Inc. 6 // 7 // Author: Nicolin Chen <nicoleotsuka@gmail.com> 8 9 #include <linux/dma-mapping.h> 10 #include <linux/module.h> 11 #include <linux/platform_data/dma-imx.h> 12 #include <sound/dmaengine_pcm.h> 13 #include <sound/pcm_params.h> 14 15 #include "fsl_asrc.h" 16 17 #define FSL_ASRC_DMABUF_SIZE (256 * 1024) 18 19 static const struct snd_pcm_hardware snd_imx_hardware = { 20 .info = SNDRV_PCM_INFO_INTERLEAVED | 21 SNDRV_PCM_INFO_BLOCK_TRANSFER | 22 SNDRV_PCM_INFO_MMAP | 23 SNDRV_PCM_INFO_MMAP_VALID | 24 SNDRV_PCM_INFO_PAUSE | 25 SNDRV_PCM_INFO_RESUME, 26 .buffer_bytes_max = FSL_ASRC_DMABUF_SIZE, 27 .period_bytes_min = 128, 28 .period_bytes_max = 65535, /* Limited by SDMA engine */ 29 .periods_min = 2, 30 .periods_max = 255, 31 .fifo_size = 0, 32 }; 33 34 static bool filter(struct dma_chan *chan, void *param) 35 { 36 if (!imx_dma_is_general_purpose(chan)) 37 return false; 38 39 chan->private = param; 40 41 return true; 42 } 43 44 static void fsl_asrc_dma_complete(void *arg) 45 { 46 struct snd_pcm_substream *substream = arg; 47 struct snd_pcm_runtime *runtime = substream->runtime; 48 struct fsl_asrc_pair *pair = runtime->private_data; 49 50 pair->pos += snd_pcm_lib_period_bytes(substream); 51 if (pair->pos >= snd_pcm_lib_buffer_bytes(substream)) 52 pair->pos = 0; 53 54 snd_pcm_period_elapsed(substream); 55 } 56 57 static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream *substream) 58 { 59 u8 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? OUT : IN; 60 struct snd_soc_pcm_runtime *rtd = substream->private_data; 61 struct snd_pcm_runtime *runtime = substream->runtime; 62 struct fsl_asrc_pair *pair = runtime->private_data; 63 struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); 64 struct device *dev = component->dev; 65 unsigned long flags = DMA_CTRL_ACK; 66 67 /* Prepare and submit Front-End DMA channel */ 68 if (!substream->runtime->no_period_wakeup) 69 flags |= DMA_PREP_INTERRUPT; 70 71 pair->pos = 0; 72 pair->desc[!dir] = dmaengine_prep_dma_cyclic( 73 pair->dma_chan[!dir], runtime->dma_addr, 74 snd_pcm_lib_buffer_bytes(substream), 75 snd_pcm_lib_period_bytes(substream), 76 dir == OUT ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, flags); 77 if (!pair->desc[!dir]) { 78 dev_err(dev, "failed to prepare slave DMA for Front-End\n"); 79 return -ENOMEM; 80 } 81 82 pair->desc[!dir]->callback = fsl_asrc_dma_complete; 83 pair->desc[!dir]->callback_param = substream; 84 85 dmaengine_submit(pair->desc[!dir]); 86 87 /* Prepare and submit Back-End DMA channel */ 88 pair->desc[dir] = dmaengine_prep_dma_cyclic( 89 pair->dma_chan[dir], 0xffff, 64, 64, DMA_DEV_TO_DEV, 0); 90 if (!pair->desc[dir]) { 91 dev_err(dev, "failed to prepare slave DMA for Back-End\n"); 92 return -ENOMEM; 93 } 94 95 dmaengine_submit(pair->desc[dir]); 96 97 return 0; 98 } 99 100 static int fsl_asrc_dma_trigger(struct snd_pcm_substream *substream, int cmd) 101 { 102 struct snd_pcm_runtime *runtime = substream->runtime; 103 struct fsl_asrc_pair *pair = runtime->private_data; 104 int ret; 105 106 switch (cmd) { 107 case SNDRV_PCM_TRIGGER_START: 108 case SNDRV_PCM_TRIGGER_RESUME: 109 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 110 ret = fsl_asrc_dma_prepare_and_submit(substream); 111 if (ret) 112 return ret; 113 dma_async_issue_pending(pair->dma_chan[IN]); 114 dma_async_issue_pending(pair->dma_chan[OUT]); 115 break; 116 case SNDRV_PCM_TRIGGER_STOP: 117 case SNDRV_PCM_TRIGGER_SUSPEND: 118 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 119 dmaengine_terminate_all(pair->dma_chan[OUT]); 120 dmaengine_terminate_all(pair->dma_chan[IN]); 121 break; 122 default: 123 return -EINVAL; 124 } 125 126 return 0; 127 } 128 129 static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream, 130 struct snd_pcm_hw_params *params) 131 { 132 enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; 133 struct snd_soc_pcm_runtime *rtd = substream->private_data; 134 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 135 struct snd_dmaengine_dai_dma_data *dma_params_fe = NULL; 136 struct snd_dmaengine_dai_dma_data *dma_params_be = NULL; 137 struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); 138 struct snd_pcm_runtime *runtime = substream->runtime; 139 struct fsl_asrc_pair *pair = runtime->private_data; 140 struct fsl_asrc *asrc_priv = pair->asrc_priv; 141 struct dma_slave_config config_fe, config_be; 142 enum asrc_pair_index index = pair->index; 143 struct device *dev = component->dev; 144 int stream = substream->stream; 145 struct imx_dma_data *tmp_data; 146 struct snd_soc_dpcm *dpcm; 147 struct dma_chan *tmp_chan; 148 struct device *dev_be; 149 u8 dir = tx ? OUT : IN; 150 dma_cap_mask_t mask; 151 int ret; 152 153 /* Fetch the Back-End dma_data from DPCM */ 154 list_for_each_entry(dpcm, &rtd->dpcm[stream].be_clients, list_be) { 155 struct snd_soc_pcm_runtime *be = dpcm->be; 156 struct snd_pcm_substream *substream_be; 157 struct snd_soc_dai *dai = be->cpu_dai; 158 159 if (dpcm->fe != rtd) 160 continue; 161 162 substream_be = snd_soc_dpcm_get_substream(be, stream); 163 dma_params_be = snd_soc_dai_get_dma_data(dai, substream_be); 164 dev_be = dai->dev; 165 break; 166 } 167 168 if (!dma_params_be) { 169 dev_err(dev, "failed to get the substream of Back-End\n"); 170 return -EINVAL; 171 } 172 173 /* Override dma_data of the Front-End and config its dmaengine */ 174 dma_params_fe = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 175 dma_params_fe->addr = asrc_priv->paddr + REG_ASRDx(!dir, index); 176 dma_params_fe->maxburst = dma_params_be->maxburst; 177 178 pair->dma_chan[!dir] = fsl_asrc_get_dma_channel(pair, !dir); 179 if (!pair->dma_chan[!dir]) { 180 dev_err(dev, "failed to request DMA channel\n"); 181 return -EINVAL; 182 } 183 184 memset(&config_fe, 0, sizeof(config_fe)); 185 ret = snd_dmaengine_pcm_prepare_slave_config(substream, params, &config_fe); 186 if (ret) { 187 dev_err(dev, "failed to prepare DMA config for Front-End\n"); 188 return ret; 189 } 190 191 ret = dmaengine_slave_config(pair->dma_chan[!dir], &config_fe); 192 if (ret) { 193 dev_err(dev, "failed to config DMA channel for Front-End\n"); 194 return ret; 195 } 196 197 /* Request and config DMA channel for Back-End */ 198 dma_cap_zero(mask); 199 dma_cap_set(DMA_SLAVE, mask); 200 dma_cap_set(DMA_CYCLIC, mask); 201 202 /* Get DMA request of Back-End */ 203 tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx"); 204 tmp_data = tmp_chan->private; 205 pair->dma_data.dma_request = tmp_data->dma_request; 206 dma_release_channel(tmp_chan); 207 208 /* Get DMA request of Front-End */ 209 tmp_chan = fsl_asrc_get_dma_channel(pair, dir); 210 tmp_data = tmp_chan->private; 211 pair->dma_data.dma_request2 = tmp_data->dma_request; 212 pair->dma_data.peripheral_type = tmp_data->peripheral_type; 213 pair->dma_data.priority = tmp_data->priority; 214 dma_release_channel(tmp_chan); 215 216 pair->dma_chan[dir] = dma_request_channel(mask, filter, &pair->dma_data); 217 if (!pair->dma_chan[dir]) { 218 dev_err(dev, "failed to request DMA channel for Back-End\n"); 219 return -EINVAL; 220 } 221 222 if (asrc_priv->asrc_width == 16) 223 buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; 224 else 225 buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; 226 227 config_be.direction = DMA_DEV_TO_DEV; 228 config_be.src_addr_width = buswidth; 229 config_be.src_maxburst = dma_params_be->maxburst; 230 config_be.dst_addr_width = buswidth; 231 config_be.dst_maxburst = dma_params_be->maxburst; 232 233 if (tx) { 234 config_be.src_addr = asrc_priv->paddr + REG_ASRDO(index); 235 config_be.dst_addr = dma_params_be->addr; 236 } else { 237 config_be.dst_addr = asrc_priv->paddr + REG_ASRDI(index); 238 config_be.src_addr = dma_params_be->addr; 239 } 240 241 ret = dmaengine_slave_config(pair->dma_chan[dir], &config_be); 242 if (ret) { 243 dev_err(dev, "failed to config DMA channel for Back-End\n"); 244 return ret; 245 } 246 247 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 248 249 return 0; 250 } 251 252 static int fsl_asrc_dma_hw_free(struct snd_pcm_substream *substream) 253 { 254 struct snd_pcm_runtime *runtime = substream->runtime; 255 struct fsl_asrc_pair *pair = runtime->private_data; 256 257 snd_pcm_set_runtime_buffer(substream, NULL); 258 259 if (pair->dma_chan[IN]) 260 dma_release_channel(pair->dma_chan[IN]); 261 262 if (pair->dma_chan[OUT]) 263 dma_release_channel(pair->dma_chan[OUT]); 264 265 pair->dma_chan[IN] = NULL; 266 pair->dma_chan[OUT] = NULL; 267 268 return 0; 269 } 270 271 static int fsl_asrc_dma_startup(struct snd_pcm_substream *substream) 272 { 273 struct snd_soc_pcm_runtime *rtd = substream->private_data; 274 struct snd_pcm_runtime *runtime = substream->runtime; 275 struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); 276 struct device *dev = component->dev; 277 struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); 278 struct fsl_asrc_pair *pair; 279 280 pair = kzalloc(sizeof(struct fsl_asrc_pair), GFP_KERNEL); 281 if (!pair) 282 return -ENOMEM; 283 284 pair->asrc_priv = asrc_priv; 285 286 runtime->private_data = pair; 287 288 snd_pcm_hw_constraint_integer(substream->runtime, 289 SNDRV_PCM_HW_PARAM_PERIODS); 290 snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); 291 292 return 0; 293 } 294 295 static int fsl_asrc_dma_shutdown(struct snd_pcm_substream *substream) 296 { 297 struct snd_pcm_runtime *runtime = substream->runtime; 298 struct fsl_asrc_pair *pair = runtime->private_data; 299 struct fsl_asrc *asrc_priv; 300 301 if (!pair) 302 return 0; 303 304 asrc_priv = pair->asrc_priv; 305 306 if (asrc_priv->pair[pair->index] == pair) 307 asrc_priv->pair[pair->index] = NULL; 308 309 kfree(pair); 310 311 return 0; 312 } 313 314 static snd_pcm_uframes_t fsl_asrc_dma_pcm_pointer(struct snd_pcm_substream *substream) 315 { 316 struct snd_pcm_runtime *runtime = substream->runtime; 317 struct fsl_asrc_pair *pair = runtime->private_data; 318 319 return bytes_to_frames(substream->runtime, pair->pos); 320 } 321 322 static const struct snd_pcm_ops fsl_asrc_dma_pcm_ops = { 323 .ioctl = snd_pcm_lib_ioctl, 324 .hw_params = fsl_asrc_dma_hw_params, 325 .hw_free = fsl_asrc_dma_hw_free, 326 .trigger = fsl_asrc_dma_trigger, 327 .open = fsl_asrc_dma_startup, 328 .close = fsl_asrc_dma_shutdown, 329 .pointer = fsl_asrc_dma_pcm_pointer, 330 }; 331 332 static int fsl_asrc_dma_pcm_new(struct snd_soc_pcm_runtime *rtd) 333 { 334 struct snd_card *card = rtd->card->snd_card; 335 struct snd_pcm_substream *substream; 336 struct snd_pcm *pcm = rtd->pcm; 337 int ret, i; 338 339 ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); 340 if (ret) { 341 dev_err(card->dev, "failed to set DMA mask\n"); 342 return ret; 343 } 344 345 for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) { 346 substream = pcm->streams[i].substream; 347 if (!substream) 348 continue; 349 350 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev, 351 FSL_ASRC_DMABUF_SIZE, &substream->dma_buffer); 352 if (ret) { 353 dev_err(card->dev, "failed to allocate DMA buffer\n"); 354 goto err; 355 } 356 } 357 358 return 0; 359 360 err: 361 if (--i == 0 && pcm->streams[i].substream) 362 snd_dma_free_pages(&pcm->streams[i].substream->dma_buffer); 363 364 return ret; 365 } 366 367 static void fsl_asrc_dma_pcm_free(struct snd_pcm *pcm) 368 { 369 struct snd_pcm_substream *substream; 370 int i; 371 372 for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) { 373 substream = pcm->streams[i].substream; 374 if (!substream) 375 continue; 376 377 snd_dma_free_pages(&substream->dma_buffer); 378 substream->dma_buffer.area = NULL; 379 substream->dma_buffer.addr = 0; 380 } 381 } 382 383 struct snd_soc_component_driver fsl_asrc_component = { 384 .name = DRV_NAME, 385 .ops = &fsl_asrc_dma_pcm_ops, 386 .pcm_new = fsl_asrc_dma_pcm_new, 387 .pcm_free = fsl_asrc_dma_pcm_free, 388 }; 389 EXPORT_SYMBOL_GPL(fsl_asrc_component); 390