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