sprd-pcm-dma.c (12871B)
1// SPDX-License-Identifier: GPL-2.0 2// Copyright (C) 2019 Spreadtrum Communications Inc. 3 4#include <linux/dma-mapping.h> 5#include <linux/dmaengine.h> 6#include <linux/dma/sprd-dma.h> 7#include <linux/kernel.h> 8#include <linux/module.h> 9#include <linux/of_reserved_mem.h> 10#include <linux/platform_device.h> 11#include <sound/pcm.h> 12#include <sound/pcm_params.h> 13#include <sound/soc.h> 14 15#include "sprd-pcm-dma.h" 16 17#define SPRD_PCM_DMA_LINKLIST_SIZE 64 18#define SPRD_PCM_DMA_BRUST_LEN 640 19 20struct sprd_pcm_dma_data { 21 struct dma_chan *chan; 22 struct dma_async_tx_descriptor *desc; 23 dma_cookie_t cookie; 24 dma_addr_t phys; 25 void *virt; 26 int pre_pointer; 27}; 28 29struct sprd_pcm_dma_private { 30 struct snd_pcm_substream *substream; 31 struct sprd_pcm_dma_params *params; 32 struct sprd_pcm_dma_data data[SPRD_PCM_CHANNEL_MAX]; 33 int hw_chan; 34 int dma_addr_offset; 35}; 36 37static const struct snd_pcm_hardware sprd_pcm_hardware = { 38 .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 39 SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | 40 SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, 41 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, 42 .period_bytes_min = 1, 43 .period_bytes_max = 64 * 1024, 44 .periods_min = 1, 45 .periods_max = PAGE_SIZE / SPRD_PCM_DMA_LINKLIST_SIZE, 46 .buffer_bytes_max = 64 * 1024, 47}; 48 49static int sprd_pcm_open(struct snd_soc_component *component, 50 struct snd_pcm_substream *substream) 51{ 52 struct snd_pcm_runtime *runtime = substream->runtime; 53 struct device *dev = component->dev; 54 struct sprd_pcm_dma_private *dma_private; 55 int hw_chan = SPRD_PCM_CHANNEL_MAX; 56 int size, ret, i; 57 58 snd_soc_set_runtime_hwparams(substream, &sprd_pcm_hardware); 59 60 ret = snd_pcm_hw_constraint_step(runtime, 0, 61 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 62 SPRD_PCM_DMA_BRUST_LEN); 63 if (ret < 0) 64 return ret; 65 66 ret = snd_pcm_hw_constraint_step(runtime, 0, 67 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 68 SPRD_PCM_DMA_BRUST_LEN); 69 if (ret < 0) 70 return ret; 71 72 ret = snd_pcm_hw_constraint_integer(runtime, 73 SNDRV_PCM_HW_PARAM_PERIODS); 74 if (ret < 0) 75 return ret; 76 77 dma_private = devm_kzalloc(dev, sizeof(*dma_private), GFP_KERNEL); 78 if (!dma_private) 79 return -ENOMEM; 80 81 size = runtime->hw.periods_max * SPRD_PCM_DMA_LINKLIST_SIZE; 82 83 for (i = 0; i < hw_chan; i++) { 84 struct sprd_pcm_dma_data *data = &dma_private->data[i]; 85 86 data->virt = dmam_alloc_coherent(dev, size, &data->phys, 87 GFP_KERNEL); 88 if (!data->virt) { 89 ret = -ENOMEM; 90 goto error; 91 } 92 } 93 94 dma_private->hw_chan = hw_chan; 95 runtime->private_data = dma_private; 96 dma_private->substream = substream; 97 98 return 0; 99 100error: 101 for (i = 0; i < hw_chan; i++) { 102 struct sprd_pcm_dma_data *data = &dma_private->data[i]; 103 104 if (data->virt) 105 dmam_free_coherent(dev, size, data->virt, data->phys); 106 } 107 108 devm_kfree(dev, dma_private); 109 return ret; 110} 111 112static int sprd_pcm_close(struct snd_soc_component *component, 113 struct snd_pcm_substream *substream) 114{ 115 struct snd_pcm_runtime *runtime = substream->runtime; 116 struct sprd_pcm_dma_private *dma_private = runtime->private_data; 117 struct device *dev = component->dev; 118 int size = runtime->hw.periods_max * SPRD_PCM_DMA_LINKLIST_SIZE; 119 int i; 120 121 for (i = 0; i < dma_private->hw_chan; i++) { 122 struct sprd_pcm_dma_data *data = &dma_private->data[i]; 123 124 dmam_free_coherent(dev, size, data->virt, data->phys); 125 } 126 127 devm_kfree(dev, dma_private); 128 129 return 0; 130} 131 132static void sprd_pcm_dma_complete(void *data) 133{ 134 struct sprd_pcm_dma_private *dma_private = data; 135 struct snd_pcm_substream *substream = dma_private->substream; 136 137 snd_pcm_period_elapsed(substream); 138} 139 140static void sprd_pcm_release_dma_channel(struct snd_pcm_substream *substream) 141{ 142 struct snd_pcm_runtime *runtime = substream->runtime; 143 struct sprd_pcm_dma_private *dma_private = runtime->private_data; 144 int i; 145 146 for (i = 0; i < SPRD_PCM_CHANNEL_MAX; i++) { 147 struct sprd_pcm_dma_data *data = &dma_private->data[i]; 148 149 if (data->chan) { 150 dma_release_channel(data->chan); 151 data->chan = NULL; 152 } 153 } 154} 155 156static int sprd_pcm_request_dma_channel(struct snd_soc_component *component, 157 struct snd_pcm_substream *substream, 158 int channels) 159{ 160 struct snd_pcm_runtime *runtime = substream->runtime; 161 struct sprd_pcm_dma_private *dma_private = runtime->private_data; 162 struct device *dev = component->dev; 163 struct sprd_pcm_dma_params *dma_params = dma_private->params; 164 int i; 165 166 if (channels > SPRD_PCM_CHANNEL_MAX) { 167 dev_err(dev, "invalid dma channel number:%d\n", channels); 168 return -EINVAL; 169 } 170 171 for (i = 0; i < channels; i++) { 172 struct sprd_pcm_dma_data *data = &dma_private->data[i]; 173 174 data->chan = dma_request_slave_channel(dev, 175 dma_params->chan_name[i]); 176 if (!data->chan) { 177 dev_err(dev, "failed to request dma channel:%s\n", 178 dma_params->chan_name[i]); 179 sprd_pcm_release_dma_channel(substream); 180 return -ENODEV; 181 } 182 } 183 184 return 0; 185} 186 187static int sprd_pcm_hw_params(struct snd_soc_component *component, 188 struct snd_pcm_substream *substream, 189 struct snd_pcm_hw_params *params) 190{ 191 struct snd_pcm_runtime *runtime = substream->runtime; 192 struct sprd_pcm_dma_private *dma_private = runtime->private_data; 193 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 194 struct sprd_pcm_dma_params *dma_params; 195 size_t totsize = params_buffer_bytes(params); 196 size_t period = params_period_bytes(params); 197 int channels = params_channels(params); 198 int is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 199 struct scatterlist *sg; 200 unsigned long flags; 201 int ret, i, j, sg_num; 202 203 dma_params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); 204 if (!dma_params) { 205 dev_warn(component->dev, "no dma parameters setting\n"); 206 dma_private->params = NULL; 207 return 0; 208 } 209 210 if (!dma_private->params) { 211 dma_private->params = dma_params; 212 ret = sprd_pcm_request_dma_channel(component, 213 substream, channels); 214 if (ret) 215 return ret; 216 } 217 218 sg_num = totsize / period; 219 dma_private->dma_addr_offset = totsize / channels; 220 221 sg = devm_kcalloc(component->dev, sg_num, sizeof(*sg), GFP_KERNEL); 222 if (!sg) { 223 ret = -ENOMEM; 224 goto sg_err; 225 } 226 227 for (i = 0; i < channels; i++) { 228 struct sprd_pcm_dma_data *data = &dma_private->data[i]; 229 struct dma_chan *chan = data->chan; 230 struct dma_slave_config config = { }; 231 struct sprd_dma_linklist link = { }; 232 enum dma_transfer_direction dir; 233 struct scatterlist *sgt = sg; 234 235 config.src_maxburst = dma_params->fragment_len[i]; 236 config.src_addr_width = dma_params->datawidth[i]; 237 config.dst_addr_width = dma_params->datawidth[i]; 238 if (is_playback) { 239 config.src_addr = runtime->dma_addr + 240 i * dma_private->dma_addr_offset; 241 config.dst_addr = dma_params->dev_phys[i]; 242 dir = DMA_MEM_TO_DEV; 243 } else { 244 config.src_addr = dma_params->dev_phys[i]; 245 config.dst_addr = runtime->dma_addr + 246 i * dma_private->dma_addr_offset; 247 dir = DMA_DEV_TO_MEM; 248 } 249 250 sg_init_table(sgt, sg_num); 251 for (j = 0; j < sg_num; j++, sgt++) { 252 u32 sg_len = period / channels; 253 254 sg_dma_len(sgt) = sg_len; 255 sg_dma_address(sgt) = runtime->dma_addr + 256 i * dma_private->dma_addr_offset + sg_len * j; 257 } 258 259 /* 260 * Configure the link-list address for the DMA engine link-list 261 * mode. 262 */ 263 link.virt_addr = (unsigned long)data->virt; 264 link.phy_addr = data->phys; 265 266 ret = dmaengine_slave_config(chan, &config); 267 if (ret) { 268 dev_err(component->dev, 269 "failed to set slave configuration: %d\n", ret); 270 goto config_err; 271 } 272 273 /* 274 * We configure the DMA request mode, interrupt mode, channel 275 * mode and channel trigger mode by the flags. 276 */ 277 flags = SPRD_DMA_FLAGS(SPRD_DMA_CHN_MODE_NONE, SPRD_DMA_NO_TRG, 278 SPRD_DMA_FRAG_REQ, SPRD_DMA_TRANS_INT); 279 data->desc = chan->device->device_prep_slave_sg(chan, sg, 280 sg_num, dir, 281 flags, &link); 282 if (!data->desc) { 283 dev_err(component->dev, "failed to prepare slave sg\n"); 284 ret = -ENOMEM; 285 goto config_err; 286 } 287 288 if (!runtime->no_period_wakeup) { 289 data->desc->callback = sprd_pcm_dma_complete; 290 data->desc->callback_param = dma_private; 291 } 292 } 293 294 devm_kfree(component->dev, sg); 295 296 return 0; 297 298config_err: 299 devm_kfree(component->dev, sg); 300sg_err: 301 sprd_pcm_release_dma_channel(substream); 302 return ret; 303} 304 305static int sprd_pcm_hw_free(struct snd_soc_component *component, 306 struct snd_pcm_substream *substream) 307{ 308 sprd_pcm_release_dma_channel(substream); 309 310 return 0; 311} 312 313static int sprd_pcm_trigger(struct snd_soc_component *component, 314 struct snd_pcm_substream *substream, int cmd) 315{ 316 struct sprd_pcm_dma_private *dma_private = 317 substream->runtime->private_data; 318 int ret = 0, i; 319 320 switch (cmd) { 321 case SNDRV_PCM_TRIGGER_START: 322 for (i = 0; i < dma_private->hw_chan; i++) { 323 struct sprd_pcm_dma_data *data = &dma_private->data[i]; 324 325 if (!data->desc) 326 continue; 327 328 data->cookie = dmaengine_submit(data->desc); 329 ret = dma_submit_error(data->cookie); 330 if (ret) { 331 dev_err(component->dev, 332 "failed to submit dma request: %d\n", 333 ret); 334 return ret; 335 } 336 337 dma_async_issue_pending(data->chan); 338 } 339 340 break; 341 case SNDRV_PCM_TRIGGER_RESUME: 342 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 343 for (i = 0; i < dma_private->hw_chan; i++) { 344 struct sprd_pcm_dma_data *data = &dma_private->data[i]; 345 346 if (data->chan) 347 dmaengine_resume(data->chan); 348 } 349 350 break; 351 case SNDRV_PCM_TRIGGER_STOP: 352 for (i = 0; i < dma_private->hw_chan; i++) { 353 struct sprd_pcm_dma_data *data = &dma_private->data[i]; 354 355 if (data->chan) 356 dmaengine_terminate_async(data->chan); 357 } 358 359 break; 360 case SNDRV_PCM_TRIGGER_SUSPEND: 361 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 362 for (i = 0; i < dma_private->hw_chan; i++) { 363 struct sprd_pcm_dma_data *data = &dma_private->data[i]; 364 365 if (data->chan) 366 dmaengine_pause(data->chan); 367 } 368 369 break; 370 default: 371 ret = -EINVAL; 372 } 373 374 return ret; 375} 376 377static snd_pcm_uframes_t sprd_pcm_pointer(struct snd_soc_component *component, 378 struct snd_pcm_substream *substream) 379{ 380 struct snd_pcm_runtime *runtime = substream->runtime; 381 struct sprd_pcm_dma_private *dma_private = runtime->private_data; 382 int pointer[SPRD_PCM_CHANNEL_MAX]; 383 int bytes_of_pointer = 0, sel_max = 0, i; 384 snd_pcm_uframes_t x; 385 struct dma_tx_state state; 386 enum dma_status status; 387 388 for (i = 0; i < dma_private->hw_chan; i++) { 389 struct sprd_pcm_dma_data *data = &dma_private->data[i]; 390 391 if (!data->chan) 392 continue; 393 394 status = dmaengine_tx_status(data->chan, data->cookie, &state); 395 if (status == DMA_ERROR) { 396 dev_err(component->dev, 397 "failed to get dma channel %d status\n", i); 398 return 0; 399 } 400 401 /* 402 * We just get current transfer address from the DMA engine, so 403 * we need convert to current pointer. 404 */ 405 pointer[i] = state.residue - runtime->dma_addr - 406 i * dma_private->dma_addr_offset; 407 408 if (i == 0) { 409 bytes_of_pointer = pointer[i]; 410 sel_max = pointer[i] < data->pre_pointer ? 1 : 0; 411 } else { 412 sel_max ^= pointer[i] < data->pre_pointer ? 1 : 0; 413 414 if (sel_max) 415 bytes_of_pointer = 416 max(pointer[i], pointer[i - 1]) << 1; 417 else 418 bytes_of_pointer = 419 min(pointer[i], pointer[i - 1]) << 1; 420 } 421 422 data->pre_pointer = pointer[i]; 423 } 424 425 x = bytes_to_frames(runtime, bytes_of_pointer); 426 if (x == runtime->buffer_size) 427 x = 0; 428 429 return x; 430} 431 432static int sprd_pcm_new(struct snd_soc_component *component, 433 struct snd_soc_pcm_runtime *rtd) 434{ 435 struct snd_card *card = rtd->card->snd_card; 436 struct snd_pcm *pcm = rtd->pcm; 437 int ret; 438 439 ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); 440 if (ret) 441 return ret; 442 443 return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, 444 card->dev, 445 sprd_pcm_hardware.buffer_bytes_max); 446} 447 448static const struct snd_soc_component_driver sprd_soc_component = { 449 .name = DRV_NAME, 450 .open = sprd_pcm_open, 451 .close = sprd_pcm_close, 452 .hw_params = sprd_pcm_hw_params, 453 .hw_free = sprd_pcm_hw_free, 454 .trigger = sprd_pcm_trigger, 455 .pointer = sprd_pcm_pointer, 456 .pcm_construct = sprd_pcm_new, 457 .compress_ops = &sprd_platform_compress_ops, 458}; 459 460static int sprd_soc_platform_probe(struct platform_device *pdev) 461{ 462 struct device_node *np = pdev->dev.of_node; 463 int ret; 464 465 ret = of_reserved_mem_device_init_by_idx(&pdev->dev, np, 0); 466 if (ret) 467 dev_warn(&pdev->dev, 468 "no reserved DMA memory for audio platform device\n"); 469 470 ret = devm_snd_soc_register_component(&pdev->dev, &sprd_soc_component, 471 NULL, 0); 472 if (ret) 473 dev_err(&pdev->dev, "could not register platform:%d\n", ret); 474 475 return ret; 476} 477 478static const struct of_device_id sprd_pcm_of_match[] = { 479 { .compatible = "sprd,pcm-platform", }, 480 { }, 481}; 482MODULE_DEVICE_TABLE(of, sprd_pcm_of_match); 483 484static struct platform_driver sprd_pcm_driver = { 485 .driver = { 486 .name = "sprd-pcm-audio", 487 .of_match_table = sprd_pcm_of_match, 488 }, 489 490 .probe = sprd_soc_platform_probe, 491}; 492 493module_platform_driver(sprd_pcm_driver); 494 495MODULE_DESCRIPTION("Spreadtrum ASoC PCM DMA"); 496MODULE_LICENSE("GPL v2"); 497MODULE_ALIAS("platform:sprd-audio");