0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/of_device.h>
0011 #include <linux/dma-mapping.h>
0012 #include <linux/slab.h>
0013 #include <linux/of_address.h>
0014 #include <linux/of_irq.h>
0015 #include <linux/of_platform.h>
0016
0017 #include <sound/soc.h>
0018
0019 #include <linux/fsl/bestcomm/bestcomm.h>
0020 #include <linux/fsl/bestcomm/gen_bd.h>
0021 #include <asm/mpc52xx_psc.h>
0022
0023 #include "mpc5200_dma.h"
0024
0025 #define DRV_NAME "mpc5200_dma"
0026
0027
0028
0029
0030 static irqreturn_t psc_dma_status_irq(int irq, void *_psc_dma)
0031 {
0032 struct psc_dma *psc_dma = _psc_dma;
0033 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
0034 u16 isr;
0035
0036 isr = in_be16(®s->mpc52xx_psc_isr);
0037
0038
0039 if (psc_dma->playback.active && (isr & MPC52xx_PSC_IMR_TXEMP))
0040 psc_dma->stats.underrun_count++;
0041
0042
0043 if (psc_dma->capture.active && (isr & MPC52xx_PSC_IMR_ORERR))
0044 psc_dma->stats.overrun_count++;
0045
0046 out_8(®s->command, MPC52xx_PSC_RST_ERR_STAT);
0047
0048 return IRQ_HANDLED;
0049 }
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 static void psc_dma_bcom_enqueue_next_buffer(struct psc_dma_stream *s)
0062 {
0063 struct bcom_bd *bd;
0064
0065
0066 bd = bcom_prepare_next_buffer(s->bcom_task);
0067 bd->status = s->period_bytes;
0068 bd->data[0] = s->runtime->dma_addr + (s->period_next * s->period_bytes);
0069 bcom_submit_next_buffer(s->bcom_task, NULL);
0070
0071
0072 s->period_next = (s->period_next + 1) % s->runtime->periods;
0073 }
0074
0075
0076 static irqreturn_t psc_dma_bcom_irq(int irq, void *_psc_dma_stream)
0077 {
0078 struct psc_dma_stream *s = _psc_dma_stream;
0079
0080 spin_lock(&s->psc_dma->lock);
0081
0082
0083 while (bcom_buffer_done(s->bcom_task)) {
0084 bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
0085
0086 s->period_current = (s->period_current+1) % s->runtime->periods;
0087 s->period_count++;
0088
0089 psc_dma_bcom_enqueue_next_buffer(s);
0090 }
0091 spin_unlock(&s->psc_dma->lock);
0092
0093
0094
0095 if (s->active)
0096 snd_pcm_period_elapsed(s->stream);
0097
0098 return IRQ_HANDLED;
0099 }
0100
0101
0102
0103
0104
0105
0106
0107 static int psc_dma_trigger(struct snd_soc_component *component,
0108 struct snd_pcm_substream *substream, int cmd)
0109 {
0110 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0111 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
0112 struct snd_pcm_runtime *runtime = substream->runtime;
0113 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
0114 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
0115 u16 imr;
0116 unsigned long flags;
0117 int i;
0118
0119 switch (cmd) {
0120 case SNDRV_PCM_TRIGGER_START:
0121 dev_dbg(psc_dma->dev, "START: stream=%i fbits=%u ps=%u #p=%u\n",
0122 substream->pstr->stream, runtime->frame_bits,
0123 (int)runtime->period_size, runtime->periods);
0124 s->period_bytes = frames_to_bytes(runtime,
0125 runtime->period_size);
0126 s->period_next = 0;
0127 s->period_current = 0;
0128 s->active = 1;
0129 s->period_count = 0;
0130 s->runtime = runtime;
0131
0132
0133
0134
0135 spin_lock_irqsave(&psc_dma->lock, flags);
0136
0137 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
0138 bcom_gen_bd_rx_reset(s->bcom_task);
0139 else
0140 bcom_gen_bd_tx_reset(s->bcom_task);
0141
0142 for (i = 0; i < runtime->periods; i++)
0143 if (!bcom_queue_full(s->bcom_task))
0144 psc_dma_bcom_enqueue_next_buffer(s);
0145
0146 bcom_enable(s->bcom_task);
0147 spin_unlock_irqrestore(&psc_dma->lock, flags);
0148
0149 out_8(®s->command, MPC52xx_PSC_RST_ERR_STAT);
0150
0151 break;
0152
0153 case SNDRV_PCM_TRIGGER_STOP:
0154 dev_dbg(psc_dma->dev, "STOP: stream=%i periods_count=%i\n",
0155 substream->pstr->stream, s->period_count);
0156 s->active = 0;
0157
0158 spin_lock_irqsave(&psc_dma->lock, flags);
0159 bcom_disable(s->bcom_task);
0160 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
0161 bcom_gen_bd_rx_reset(s->bcom_task);
0162 else
0163 bcom_gen_bd_tx_reset(s->bcom_task);
0164 spin_unlock_irqrestore(&psc_dma->lock, flags);
0165
0166 break;
0167
0168 default:
0169 dev_dbg(psc_dma->dev, "unhandled trigger: stream=%i cmd=%i\n",
0170 substream->pstr->stream, cmd);
0171 return -EINVAL;
0172 }
0173
0174
0175 imr = 0;
0176 if (psc_dma->playback.active)
0177 imr |= MPC52xx_PSC_IMR_TXEMP;
0178 if (psc_dma->capture.active)
0179 imr |= MPC52xx_PSC_IMR_ORERR;
0180 out_be16(®s->isr_imr.imr, psc_dma->imr | imr);
0181
0182 return 0;
0183 }
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194 static const struct snd_pcm_hardware psc_dma_hardware = {
0195 .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
0196 SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
0197 SNDRV_PCM_INFO_BATCH,
0198 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |
0199 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE,
0200 .period_bytes_max = 1024 * 1024,
0201 .period_bytes_min = 32,
0202 .periods_min = 2,
0203 .periods_max = 256,
0204 .buffer_bytes_max = 2 * 1024 * 1024,
0205 .fifo_size = 512,
0206 };
0207
0208 static int psc_dma_open(struct snd_soc_component *component,
0209 struct snd_pcm_substream *substream)
0210 {
0211 struct snd_pcm_runtime *runtime = substream->runtime;
0212 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0213 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
0214 struct psc_dma_stream *s;
0215 int rc;
0216
0217 dev_dbg(psc_dma->dev, "psc_dma_open(substream=%p)\n", substream);
0218
0219 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
0220 s = &psc_dma->capture;
0221 else
0222 s = &psc_dma->playback;
0223
0224 snd_soc_set_runtime_hwparams(substream, &psc_dma_hardware);
0225
0226 rc = snd_pcm_hw_constraint_integer(runtime,
0227 SNDRV_PCM_HW_PARAM_PERIODS);
0228 if (rc < 0) {
0229 dev_err(substream->pcm->card->dev, "invalid buffer size\n");
0230 return rc;
0231 }
0232
0233 s->stream = substream;
0234 return 0;
0235 }
0236
0237 static int psc_dma_close(struct snd_soc_component *component,
0238 struct snd_pcm_substream *substream)
0239 {
0240 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0241 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
0242 struct psc_dma_stream *s;
0243
0244 dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream);
0245
0246 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
0247 s = &psc_dma->capture;
0248 else
0249 s = &psc_dma->playback;
0250
0251 if (!psc_dma->playback.active &&
0252 !psc_dma->capture.active) {
0253
0254
0255 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr);
0256 out_8(&psc_dma->psc_regs->command, 4 << 4);
0257 }
0258 s->stream = NULL;
0259 return 0;
0260 }
0261
0262 static snd_pcm_uframes_t
0263 psc_dma_pointer(struct snd_soc_component *component,
0264 struct snd_pcm_substream *substream)
0265 {
0266 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0267 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
0268 struct psc_dma_stream *s;
0269 dma_addr_t count;
0270
0271 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
0272 s = &psc_dma->capture;
0273 else
0274 s = &psc_dma->playback;
0275
0276 count = s->period_current * s->period_bytes;
0277
0278 return bytes_to_frames(substream->runtime, count);
0279 }
0280
0281 static int psc_dma_new(struct snd_soc_component *component,
0282 struct snd_soc_pcm_runtime *rtd)
0283 {
0284 struct snd_card *card = rtd->card->snd_card;
0285 struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0);
0286 struct snd_pcm *pcm = rtd->pcm;
0287 size_t size = psc_dma_hardware.buffer_bytes_max;
0288 int rc;
0289
0290 dev_dbg(component->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n",
0291 card, dai, pcm);
0292
0293 rc = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
0294 if (rc)
0295 return rc;
0296
0297 return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, card->dev,
0298 size);
0299 }
0300
0301 static const struct snd_soc_component_driver mpc5200_audio_dma_component = {
0302 .name = DRV_NAME,
0303 .open = psc_dma_open,
0304 .close = psc_dma_close,
0305 .pointer = psc_dma_pointer,
0306 .trigger = psc_dma_trigger,
0307 .pcm_construct = psc_dma_new,
0308 };
0309
0310 int mpc5200_audio_dma_create(struct platform_device *op)
0311 {
0312 phys_addr_t fifo;
0313 struct psc_dma *psc_dma;
0314 struct resource res;
0315 int size, irq, rc;
0316 const __be32 *prop;
0317 void __iomem *regs;
0318 int ret;
0319
0320
0321 irq = irq_of_parse_and_map(op->dev.of_node, 0);
0322 if (of_address_to_resource(op->dev.of_node, 0, &res)) {
0323 dev_err(&op->dev, "Missing reg property\n");
0324 return -ENODEV;
0325 }
0326 regs = ioremap(res.start, resource_size(&res));
0327 if (!regs) {
0328 dev_err(&op->dev, "Could not map registers\n");
0329 return -ENODEV;
0330 }
0331
0332
0333 psc_dma = kzalloc(sizeof *psc_dma, GFP_KERNEL);
0334 if (!psc_dma) {
0335 ret = -ENOMEM;
0336 goto out_unmap;
0337 }
0338
0339
0340 prop = of_get_property(op->dev.of_node, "cell-index", &size);
0341 if (!prop || size < sizeof *prop) {
0342 ret = -ENODEV;
0343 goto out_free;
0344 }
0345
0346 spin_lock_init(&psc_dma->lock);
0347 mutex_init(&psc_dma->mutex);
0348 psc_dma->id = be32_to_cpu(*prop);
0349 psc_dma->irq = irq;
0350 psc_dma->psc_regs = regs;
0351 psc_dma->fifo_regs = regs + sizeof *psc_dma->psc_regs;
0352 psc_dma->dev = &op->dev;
0353 psc_dma->playback.psc_dma = psc_dma;
0354 psc_dma->capture.psc_dma = psc_dma;
0355 snprintf(psc_dma->name, sizeof(psc_dma->name), "PSC%d", psc_dma->id);
0356
0357
0358
0359 fifo = res.start + offsetof(struct mpc52xx_psc, buffer.buffer_32);
0360 psc_dma->capture.bcom_task =
0361 bcom_psc_gen_bd_rx_init(psc_dma->id, 10, fifo, 512);
0362 psc_dma->playback.bcom_task =
0363 bcom_psc_gen_bd_tx_init(psc_dma->id, 10, fifo);
0364 if (!psc_dma->capture.bcom_task ||
0365 !psc_dma->playback.bcom_task) {
0366 dev_err(&op->dev, "Could not allocate bestcomm tasks\n");
0367 ret = -ENODEV;
0368 goto out_free;
0369 }
0370
0371
0372 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr);
0373
0374 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_RX);
0375
0376 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_TX);
0377
0378 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_ERR_STAT);
0379
0380 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_SEL_MODE_REG_1);
0381
0382
0383
0384
0385
0386 out_8(&psc_dma->psc_regs->mode, 0);
0387 out_8(&psc_dma->psc_regs->mode, 0);
0388
0389
0390 out_be16(&psc_dma->fifo_regs->rfalarm, 0x100);
0391 out_8(&psc_dma->fifo_regs->rfcntl, 0x4);
0392 out_be16(&psc_dma->fifo_regs->tfalarm, 0x100);
0393 out_8(&psc_dma->fifo_regs->tfcntl, 0x7);
0394
0395
0396 psc_dma->playback.irq =
0397 bcom_get_task_irq(psc_dma->playback.bcom_task);
0398 psc_dma->capture.irq =
0399 bcom_get_task_irq(psc_dma->capture.bcom_task);
0400
0401 rc = request_irq(psc_dma->irq, &psc_dma_status_irq, IRQF_SHARED,
0402 "psc-dma-status", psc_dma);
0403 rc |= request_irq(psc_dma->capture.irq, &psc_dma_bcom_irq, IRQF_SHARED,
0404 "psc-dma-capture", &psc_dma->capture);
0405 rc |= request_irq(psc_dma->playback.irq, &psc_dma_bcom_irq, IRQF_SHARED,
0406 "psc-dma-playback", &psc_dma->playback);
0407 if (rc) {
0408 ret = -ENODEV;
0409 goto out_irq;
0410 }
0411
0412
0413 dev_set_drvdata(&op->dev, psc_dma);
0414
0415
0416 return devm_snd_soc_register_component(&op->dev,
0417 &mpc5200_audio_dma_component, NULL, 0);
0418 out_irq:
0419 free_irq(psc_dma->irq, psc_dma);
0420 free_irq(psc_dma->capture.irq, &psc_dma->capture);
0421 free_irq(psc_dma->playback.irq, &psc_dma->playback);
0422 out_free:
0423 kfree(psc_dma);
0424 out_unmap:
0425 iounmap(regs);
0426 return ret;
0427 }
0428 EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create);
0429
0430 int mpc5200_audio_dma_destroy(struct platform_device *op)
0431 {
0432 struct psc_dma *psc_dma = dev_get_drvdata(&op->dev);
0433
0434 dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n");
0435
0436 bcom_gen_bd_rx_release(psc_dma->capture.bcom_task);
0437 bcom_gen_bd_tx_release(psc_dma->playback.bcom_task);
0438
0439
0440 free_irq(psc_dma->irq, psc_dma);
0441 free_irq(psc_dma->capture.irq, &psc_dma->capture);
0442 free_irq(psc_dma->playback.irq, &psc_dma->playback);
0443
0444 iounmap(psc_dma->psc_regs);
0445 kfree(psc_dma);
0446 dev_set_drvdata(&op->dev, NULL);
0447
0448 return 0;
0449 }
0450 EXPORT_SYMBOL_GPL(mpc5200_audio_dma_destroy);
0451
0452 MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
0453 MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver");
0454 MODULE_LICENSE("GPL");