0001
0002
0003
0004 #include <linux/dma-mapping.h>
0005 #include <linux/dmaengine.h>
0006 #include <linux/dma/sprd-dma.h>
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 #include <sound/pcm.h>
0010 #include <sound/pcm_params.h>
0011 #include <sound/soc.h>
0012 #include <sound/compress_driver.h>
0013
0014 #include "sprd-pcm-dma.h"
0015
0016 #define SPRD_COMPR_DMA_CHANS 2
0017
0018
0019 #define SPRD_COMPR_MIN_FRAGMENT_SIZE SZ_8K
0020 #define SPRD_COMPR_MAX_FRAGMENT_SIZE SZ_128K
0021 #define SPRD_COMPR_MIN_NUM_FRAGMENTS 4
0022 #define SPRD_COMPR_MAX_NUM_FRAGMENTS 64
0023
0024
0025 #define SPRD_COMPR_MCDT_EMPTY_WMK 0
0026 #define SPRD_COMPR_MCDT_FIFO_SIZE 512
0027
0028
0029 #define SPRD_COMPR_IRAM_BUF_SIZE SZ_32K
0030 #define SPRD_COMPR_IRAM_INFO_SIZE (sizeof(struct sprd_compr_playinfo))
0031 #define SPRD_COMPR_IRAM_LINKLIST_SIZE (1024 - SPRD_COMPR_IRAM_INFO_SIZE)
0032 #define SPRD_COMPR_IRAM_SIZE (SPRD_COMPR_IRAM_BUF_SIZE + \
0033 SPRD_COMPR_IRAM_INFO_SIZE + \
0034 SPRD_COMPR_IRAM_LINKLIST_SIZE)
0035
0036
0037 #define SPRD_COMPR_AREA_BUF_SIZE SZ_2M
0038 #define SPRD_COMPR_AREA_LINKLIST_SIZE 1024
0039 #define SPRD_COMPR_AREA_SIZE (SPRD_COMPR_AREA_BUF_SIZE + \
0040 SPRD_COMPR_AREA_LINKLIST_SIZE)
0041
0042 struct sprd_compr_dma {
0043 struct dma_chan *chan;
0044 struct dma_async_tx_descriptor *desc;
0045 dma_cookie_t cookie;
0046 dma_addr_t phys;
0047 void *virt;
0048 int trans_len;
0049 };
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 struct sprd_compr_stream {
0070 struct snd_compr_stream *cstream;
0071 struct sprd_compr_ops *compr_ops;
0072 struct sprd_compr_dma dma[SPRD_COMPR_DMA_CHANS];
0073
0074
0075 int num_channels;
0076
0077
0078 struct snd_dma_buffer iram_buffer;
0079
0080 struct snd_dma_buffer compr_buffer;
0081
0082
0083 dma_addr_t info_phys;
0084 void *info_area;
0085 int info_size;
0086
0087
0088 int copied_total;
0089
0090 int received_total;
0091
0092 int received_stage0;
0093
0094 int received_stage1;
0095
0096 int stage1_pointer;
0097 };
0098
0099 static int sprd_platform_compr_trigger(struct snd_soc_component *component,
0100 struct snd_compr_stream *cstream,
0101 int cmd);
0102
0103 static void sprd_platform_compr_drain_notify(void *arg)
0104 {
0105 struct snd_compr_stream *cstream = arg;
0106 struct snd_compr_runtime *runtime = cstream->runtime;
0107 struct sprd_compr_stream *stream = runtime->private_data;
0108
0109 memset(stream->info_area, 0, sizeof(struct sprd_compr_playinfo));
0110
0111 snd_compr_drain_notify(cstream);
0112 }
0113
0114 static void sprd_platform_compr_dma_complete(void *data)
0115 {
0116 struct snd_compr_stream *cstream = data;
0117 struct snd_compr_runtime *runtime = cstream->runtime;
0118 struct sprd_compr_stream *stream = runtime->private_data;
0119 struct sprd_compr_dma *dma = &stream->dma[1];
0120
0121
0122 stream->copied_total += dma->trans_len;
0123 if (stream->copied_total > stream->received_total)
0124 stream->copied_total = stream->received_total;
0125
0126 snd_compr_fragment_elapsed(cstream);
0127 }
0128
0129 static int sprd_platform_compr_dma_config(struct snd_soc_component *component,
0130 struct snd_compr_stream *cstream,
0131 struct snd_compr_params *params,
0132 int channel)
0133 {
0134 struct snd_compr_runtime *runtime = cstream->runtime;
0135 struct sprd_compr_stream *stream = runtime->private_data;
0136 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0137 struct device *dev = component->dev;
0138 struct sprd_compr_data *data = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
0139 struct sprd_pcm_dma_params *dma_params = data->dma_params;
0140 struct sprd_compr_dma *dma = &stream->dma[channel];
0141 struct dma_slave_config config = { };
0142 struct sprd_dma_linklist link = { };
0143 enum dma_transfer_direction dir;
0144 struct scatterlist *sg, *sgt;
0145 enum dma_slave_buswidth bus_width;
0146 int period, period_cnt, sg_num = 2;
0147 dma_addr_t src_addr, dst_addr;
0148 unsigned long flags;
0149 int ret, j;
0150
0151 if (!dma_params) {
0152 dev_err(dev, "no dma parameters setting\n");
0153 return -EINVAL;
0154 }
0155
0156 dma->chan = dma_request_slave_channel(dev,
0157 dma_params->chan_name[channel]);
0158 if (!dma->chan) {
0159 dev_err(dev, "failed to request dma channel\n");
0160 return -ENODEV;
0161 }
0162
0163 sgt = sg = devm_kcalloc(dev, sg_num, sizeof(*sg), GFP_KERNEL);
0164 if (!sg) {
0165 ret = -ENOMEM;
0166 goto sg_err;
0167 }
0168
0169 switch (channel) {
0170 case 0:
0171 bus_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
0172 period = (SPRD_COMPR_MCDT_FIFO_SIZE - SPRD_COMPR_MCDT_EMPTY_WMK) * 4;
0173 period_cnt = params->buffer.fragment_size / period;
0174 src_addr = stream->iram_buffer.addr;
0175 dst_addr = dma_params->dev_phys[channel];
0176 flags = SPRD_DMA_FLAGS(SPRD_DMA_SRC_CHN1,
0177 SPRD_DMA_TRANS_DONE_TRG,
0178 SPRD_DMA_FRAG_REQ,
0179 SPRD_DMA_TRANS_INT);
0180 break;
0181
0182 case 1:
0183 bus_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
0184 period = params->buffer.fragment_size;
0185 period_cnt = params->buffer.fragments;
0186 src_addr = stream->compr_buffer.addr;
0187 dst_addr = stream->iram_buffer.addr;
0188 flags = SPRD_DMA_FLAGS(SPRD_DMA_DST_CHN1,
0189 SPRD_DMA_TRANS_DONE_TRG,
0190 SPRD_DMA_FRAG_REQ,
0191 SPRD_DMA_TRANS_INT);
0192 break;
0193
0194 default:
0195 ret = -EINVAL;
0196 goto config_err;
0197 }
0198
0199 dma->trans_len = period * period_cnt;
0200
0201 config.src_maxburst = period;
0202 config.src_addr_width = bus_width;
0203 config.dst_addr_width = bus_width;
0204 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
0205 config.src_addr = src_addr;
0206 config.dst_addr = dst_addr;
0207 dir = DMA_MEM_TO_DEV;
0208 } else {
0209 config.src_addr = dst_addr;
0210 config.dst_addr = src_addr;
0211 dir = DMA_DEV_TO_MEM;
0212 }
0213
0214 sg_init_table(sgt, sg_num);
0215 for (j = 0; j < sg_num; j++, sgt++) {
0216 sg_dma_len(sgt) = dma->trans_len;
0217 sg_dma_address(sgt) = dst_addr;
0218 }
0219
0220
0221
0222
0223
0224 link.virt_addr = (unsigned long)dma->virt;
0225 link.phy_addr = dma->phys;
0226
0227 ret = dmaengine_slave_config(dma->chan, &config);
0228 if (ret) {
0229 dev_err(dev,
0230 "failed to set slave configuration: %d\n", ret);
0231 goto config_err;
0232 }
0233
0234
0235
0236
0237
0238 dma->desc = dma->chan->device->device_prep_slave_sg(dma->chan, sg,
0239 sg_num, dir,
0240 flags, &link);
0241 if (!dma->desc) {
0242 dev_err(dev, "failed to prepare slave sg\n");
0243 ret = -ENOMEM;
0244 goto config_err;
0245 }
0246
0247
0248 if (!params->no_wake_mode && channel == 1) {
0249 dma->desc->callback = sprd_platform_compr_dma_complete;
0250 dma->desc->callback_param = cstream;
0251 }
0252
0253 devm_kfree(dev, sg);
0254
0255 return 0;
0256
0257 config_err:
0258 devm_kfree(dev, sg);
0259 sg_err:
0260 dma_release_channel(dma->chan);
0261 return ret;
0262 }
0263
0264 static int sprd_platform_compr_set_params(struct snd_soc_component *component,
0265 struct snd_compr_stream *cstream,
0266 struct snd_compr_params *params)
0267 {
0268 struct snd_compr_runtime *runtime = cstream->runtime;
0269 struct sprd_compr_stream *stream = runtime->private_data;
0270 struct device *dev = component->dev;
0271 struct sprd_compr_params compr_params = { };
0272 int ret;
0273
0274
0275
0276
0277
0278
0279
0280 ret = sprd_platform_compr_dma_config(component, cstream, params, 1);
0281 if (ret) {
0282 dev_err(dev, "failed to config stage 1 DMA: %d\n", ret);
0283 return ret;
0284 }
0285
0286 ret = sprd_platform_compr_dma_config(component, cstream, params, 0);
0287 if (ret) {
0288 dev_err(dev, "failed to config stage 0 DMA: %d\n", ret);
0289 goto config_err;
0290 }
0291
0292 compr_params.direction = cstream->direction;
0293 compr_params.sample_rate = params->codec.sample_rate;
0294 compr_params.channels = stream->num_channels;
0295 compr_params.info_phys = stream->info_phys;
0296 compr_params.info_size = stream->info_size;
0297 compr_params.rate = params->codec.bit_rate;
0298 compr_params.format = params->codec.id;
0299
0300 ret = stream->compr_ops->set_params(cstream->direction, &compr_params);
0301 if (ret) {
0302 dev_err(dev, "failed to set parameters: %d\n", ret);
0303 goto params_err;
0304 }
0305
0306 return 0;
0307
0308 params_err:
0309 dma_release_channel(stream->dma[0].chan);
0310 config_err:
0311 dma_release_channel(stream->dma[1].chan);
0312 return ret;
0313 }
0314
0315 static int sprd_platform_compr_open(struct snd_soc_component *component,
0316 struct snd_compr_stream *cstream)
0317 {
0318 struct snd_compr_runtime *runtime = cstream->runtime;
0319 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0320 struct device *dev = component->dev;
0321 struct sprd_compr_data *data = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
0322 struct sprd_compr_stream *stream;
0323 struct sprd_compr_callback cb;
0324 int stream_id = cstream->direction, ret;
0325
0326 ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
0327 if (ret)
0328 return ret;
0329
0330 stream = devm_kzalloc(dev, sizeof(*stream), GFP_KERNEL);
0331 if (!stream)
0332 return -ENOMEM;
0333
0334 stream->cstream = cstream;
0335 stream->num_channels = 2;
0336 stream->compr_ops = data->ops;
0337
0338
0339
0340
0341
0342 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_IRAM, dev,
0343 SPRD_COMPR_IRAM_SIZE, &stream->iram_buffer);
0344 if (ret < 0)
0345 goto err_iram;
0346
0347
0348 stream->dma[0].virt = stream->iram_buffer.area + SPRD_COMPR_IRAM_SIZE;
0349 stream->dma[0].phys = stream->iram_buffer.addr + SPRD_COMPR_IRAM_SIZE;
0350
0351
0352 stream->info_phys = stream->iram_buffer.addr + SPRD_COMPR_IRAM_SIZE +
0353 SPRD_COMPR_IRAM_LINKLIST_SIZE;
0354 stream->info_area = stream->iram_buffer.area + SPRD_COMPR_IRAM_SIZE +
0355 SPRD_COMPR_IRAM_LINKLIST_SIZE;
0356 stream->info_size = SPRD_COMPR_IRAM_INFO_SIZE;
0357
0358
0359
0360
0361
0362 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev,
0363 SPRD_COMPR_AREA_SIZE, &stream->compr_buffer);
0364 if (ret < 0)
0365 goto err_compr;
0366
0367
0368 stream->dma[1].virt = stream->compr_buffer.area + SPRD_COMPR_AREA_SIZE;
0369 stream->dma[1].phys = stream->compr_buffer.addr + SPRD_COMPR_AREA_SIZE;
0370
0371 cb.drain_notify = sprd_platform_compr_drain_notify;
0372 cb.drain_data = cstream;
0373 ret = stream->compr_ops->open(stream_id, &cb);
0374 if (ret) {
0375 dev_err(dev, "failed to open compress platform: %d\n", ret);
0376 goto err_open;
0377 }
0378
0379 runtime->private_data = stream;
0380 return 0;
0381
0382 err_open:
0383 snd_dma_free_pages(&stream->compr_buffer);
0384 err_compr:
0385 snd_dma_free_pages(&stream->iram_buffer);
0386 err_iram:
0387 devm_kfree(dev, stream);
0388
0389 return ret;
0390 }
0391
0392 static int sprd_platform_compr_free(struct snd_soc_component *component,
0393 struct snd_compr_stream *cstream)
0394 {
0395 struct snd_compr_runtime *runtime = cstream->runtime;
0396 struct sprd_compr_stream *stream = runtime->private_data;
0397 struct device *dev = component->dev;
0398 int stream_id = cstream->direction, i;
0399
0400 for (i = 0; i < stream->num_channels; i++) {
0401 struct sprd_compr_dma *dma = &stream->dma[i];
0402
0403 if (dma->chan) {
0404 dma_release_channel(dma->chan);
0405 dma->chan = NULL;
0406 }
0407 }
0408
0409 snd_dma_free_pages(&stream->compr_buffer);
0410 snd_dma_free_pages(&stream->iram_buffer);
0411
0412 stream->compr_ops->close(stream_id);
0413
0414 devm_kfree(dev, stream);
0415 return 0;
0416 }
0417
0418 static int sprd_platform_compr_trigger(struct snd_soc_component *component,
0419 struct snd_compr_stream *cstream,
0420 int cmd)
0421 {
0422 struct snd_compr_runtime *runtime = cstream->runtime;
0423 struct sprd_compr_stream *stream = runtime->private_data;
0424 struct device *dev = component->dev;
0425 int channels = stream->num_channels, ret = 0, i;
0426 int stream_id = cstream->direction;
0427
0428 if (cstream->direction != SND_COMPRESS_PLAYBACK) {
0429 dev_err(dev, "unsupported compress direction\n");
0430 return -EINVAL;
0431 }
0432
0433 switch (cmd) {
0434 case SNDRV_PCM_TRIGGER_START:
0435 for (i = channels - 1; i >= 0; i--) {
0436 struct sprd_compr_dma *dma = &stream->dma[i];
0437
0438 if (!dma->desc)
0439 continue;
0440
0441 dma->cookie = dmaengine_submit(dma->desc);
0442 ret = dma_submit_error(dma->cookie);
0443 if (ret) {
0444 dev_err(dev, "failed to submit request: %d\n",
0445 ret);
0446 return ret;
0447 }
0448 }
0449
0450 for (i = channels - 1; i >= 0; i--) {
0451 struct sprd_compr_dma *dma = &stream->dma[i];
0452
0453 if (dma->chan)
0454 dma_async_issue_pending(dma->chan);
0455 }
0456
0457 ret = stream->compr_ops->start(stream_id);
0458 break;
0459
0460 case SNDRV_PCM_TRIGGER_STOP:
0461 for (i = channels - 1; i >= 0; i--) {
0462 struct sprd_compr_dma *dma = &stream->dma[i];
0463
0464 if (dma->chan)
0465 dmaengine_terminate_async(dma->chan);
0466 }
0467
0468 stream->copied_total = 0;
0469 stream->stage1_pointer = 0;
0470 stream->received_total = 0;
0471 stream->received_stage0 = 0;
0472 stream->received_stage1 = 0;
0473
0474 ret = stream->compr_ops->stop(stream_id);
0475 break;
0476
0477 case SNDRV_PCM_TRIGGER_SUSPEND:
0478 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0479 for (i = channels - 1; i >= 0; i--) {
0480 struct sprd_compr_dma *dma = &stream->dma[i];
0481
0482 if (dma->chan)
0483 dmaengine_pause(dma->chan);
0484 }
0485
0486 ret = stream->compr_ops->pause(stream_id);
0487 break;
0488
0489 case SNDRV_PCM_TRIGGER_RESUME:
0490 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0491 for (i = channels - 1; i >= 0; i--) {
0492 struct sprd_compr_dma *dma = &stream->dma[i];
0493
0494 if (dma->chan)
0495 dmaengine_resume(dma->chan);
0496 }
0497
0498 ret = stream->compr_ops->pause_release(stream_id);
0499 break;
0500
0501 case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
0502 case SND_COMPR_TRIGGER_DRAIN:
0503 ret = stream->compr_ops->drain(stream->received_total);
0504 break;
0505
0506 default:
0507 ret = -EINVAL;
0508 break;
0509 }
0510
0511 return ret;
0512 }
0513
0514 static int sprd_platform_compr_pointer(struct snd_soc_component *component,
0515 struct snd_compr_stream *cstream,
0516 struct snd_compr_tstamp *tstamp)
0517 {
0518 struct snd_compr_runtime *runtime = cstream->runtime;
0519 struct sprd_compr_stream *stream = runtime->private_data;
0520 struct sprd_compr_playinfo *info =
0521 (struct sprd_compr_playinfo *)stream->info_area;
0522
0523 tstamp->copied_total = stream->copied_total;
0524 tstamp->pcm_io_frames = info->current_data_offset;
0525
0526 return 0;
0527 }
0528
0529 static int sprd_platform_compr_copy(struct snd_soc_component *component,
0530 struct snd_compr_stream *cstream,
0531 char __user *buf, size_t count)
0532 {
0533 struct snd_compr_runtime *runtime = cstream->runtime;
0534 struct sprd_compr_stream *stream = runtime->private_data;
0535 int avail_bytes, data_count = count;
0536 void *dst;
0537
0538
0539
0540
0541
0542
0543
0544 if (stream->received_stage0 < runtime->fragment_size) {
0545 avail_bytes = runtime->fragment_size - stream->received_stage0;
0546 dst = stream->iram_buffer.area + stream->received_stage0;
0547
0548 if (avail_bytes >= data_count) {
0549
0550
0551
0552
0553 if (copy_from_user(dst, buf, data_count))
0554 return -EFAULT;
0555
0556 stream->received_stage0 += data_count;
0557 stream->copied_total += data_count;
0558 goto copy_done;
0559 } else {
0560
0561
0562
0563
0564
0565
0566 if (copy_from_user(dst, buf, avail_bytes))
0567 return -EFAULT;
0568
0569 data_count -= avail_bytes;
0570 stream->received_stage0 += avail_bytes;
0571 stream->copied_total += avail_bytes;
0572 buf += avail_bytes;
0573 }
0574 }
0575
0576
0577
0578
0579
0580 dst = stream->compr_buffer.area + stream->stage1_pointer;
0581 if (data_count < stream->compr_buffer.bytes - stream->stage1_pointer) {
0582 if (copy_from_user(dst, buf, data_count))
0583 return -EFAULT;
0584
0585 stream->stage1_pointer += data_count;
0586 } else {
0587 avail_bytes = stream->compr_buffer.bytes - stream->stage1_pointer;
0588
0589 if (copy_from_user(dst, buf, avail_bytes))
0590 return -EFAULT;
0591
0592 if (copy_from_user(stream->compr_buffer.area, buf + avail_bytes,
0593 data_count - avail_bytes))
0594 return -EFAULT;
0595
0596 stream->stage1_pointer = data_count - avail_bytes;
0597 }
0598
0599 stream->received_stage1 += data_count;
0600
0601 copy_done:
0602
0603 stream->received_total += count;
0604 return count;
0605 }
0606
0607 static int sprd_platform_compr_get_caps(struct snd_soc_component *component,
0608 struct snd_compr_stream *cstream,
0609 struct snd_compr_caps *caps)
0610 {
0611 caps->direction = cstream->direction;
0612 caps->min_fragment_size = SPRD_COMPR_MIN_FRAGMENT_SIZE;
0613 caps->max_fragment_size = SPRD_COMPR_MAX_FRAGMENT_SIZE;
0614 caps->min_fragments = SPRD_COMPR_MIN_NUM_FRAGMENTS;
0615 caps->max_fragments = SPRD_COMPR_MAX_NUM_FRAGMENTS;
0616 caps->num_codecs = 2;
0617 caps->codecs[0] = SND_AUDIOCODEC_MP3;
0618 caps->codecs[1] = SND_AUDIOCODEC_AAC;
0619
0620 return 0;
0621 }
0622
0623 static int
0624 sprd_platform_compr_get_codec_caps(struct snd_soc_component *component,
0625 struct snd_compr_stream *cstream,
0626 struct snd_compr_codec_caps *codec)
0627 {
0628 switch (codec->codec) {
0629 case SND_AUDIOCODEC_MP3:
0630 codec->num_descriptors = 2;
0631 codec->descriptor[0].max_ch = 2;
0632 codec->descriptor[0].bit_rate[0] = 320;
0633 codec->descriptor[0].bit_rate[1] = 128;
0634 codec->descriptor[0].num_bitrates = 2;
0635 codec->descriptor[0].profiles = 0;
0636 codec->descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO;
0637 codec->descriptor[0].formats = 0;
0638 break;
0639
0640 case SND_AUDIOCODEC_AAC:
0641 codec->num_descriptors = 2;
0642 codec->descriptor[1].max_ch = 2;
0643 codec->descriptor[1].bit_rate[0] = 320;
0644 codec->descriptor[1].bit_rate[1] = 128;
0645 codec->descriptor[1].num_bitrates = 2;
0646 codec->descriptor[1].profiles = 0;
0647 codec->descriptor[1].modes = 0;
0648 codec->descriptor[1].formats = 0;
0649 break;
0650
0651 default:
0652 return -EINVAL;
0653 }
0654
0655 return 0;
0656 }
0657
0658 const struct snd_compress_ops sprd_platform_compress_ops = {
0659 .open = sprd_platform_compr_open,
0660 .free = sprd_platform_compr_free,
0661 .set_params = sprd_platform_compr_set_params,
0662 .trigger = sprd_platform_compr_trigger,
0663 .pointer = sprd_platform_compr_pointer,
0664 .copy = sprd_platform_compr_copy,
0665 .get_caps = sprd_platform_compr_get_caps,
0666 .get_codec_caps = sprd_platform_compr_get_codec_caps,
0667 };
0668
0669 MODULE_DESCRIPTION("Spreadtrum ASoC Compress Platform Driver");
0670 MODULE_LICENSE("GPL v2");
0671 MODULE_ALIAS("platform:compress-platform");