Lines Matching +full:playback +full:- +full:only
1 // SPDX-License-Identifier: GPL-2.0-only
10 #include <linux/dma-mapping.h>
33 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; in psc_dma_status_irq()
36 isr = in_be16(®s->mpc52xx_psc_isr); in psc_dma_status_irq()
38 /* Playback underrun error */ in psc_dma_status_irq()
39 if (psc_dma->playback.active && (isr & MPC52xx_PSC_IMR_TXEMP)) in psc_dma_status_irq()
40 psc_dma->stats.underrun_count++; in psc_dma_status_irq()
43 if (psc_dma->capture.active && (isr & MPC52xx_PSC_IMR_ORERR)) in psc_dma_status_irq()
44 psc_dma->stats.overrun_count++; in psc_dma_status_irq()
46 out_8(®s->command, MPC52xx_PSC_RST_ERR_STAT); in psc_dma_status_irq()
52 * psc_dma_bcom_enqueue_next_buffer - Enqueue another audio buffer
57 * Note: The routine must only be called when there is space available in
66 bd = bcom_prepare_next_buffer(s->bcom_task); in psc_dma_bcom_enqueue_next_buffer()
67 bd->status = s->period_bytes; in psc_dma_bcom_enqueue_next_buffer()
68 bd->data[0] = s->runtime->dma_addr + (s->period_next * s->period_bytes); in psc_dma_bcom_enqueue_next_buffer()
69 bcom_submit_next_buffer(s->bcom_task, NULL); in psc_dma_bcom_enqueue_next_buffer()
72 s->period_next = (s->period_next + 1) % s->runtime->periods; in psc_dma_bcom_enqueue_next_buffer()
80 spin_lock(&s->psc_dma->lock); in psc_dma_bcom_irq()
83 while (bcom_buffer_done(s->bcom_task)) { in psc_dma_bcom_irq()
84 bcom_retrieve_buffer(s->bcom_task, NULL, NULL); in psc_dma_bcom_irq()
86 s->period_current = (s->period_current+1) % s->runtime->periods; in psc_dma_bcom_irq()
87 s->period_count++; in psc_dma_bcom_irq()
91 spin_unlock(&s->psc_dma->lock); in psc_dma_bcom_irq()
95 if (s->active) in psc_dma_bcom_irq()
96 snd_pcm_period_elapsed(s->stream); in psc_dma_bcom_irq()
115 struct snd_pcm_runtime *runtime = substream->runtime; in psc_dma_trigger()
117 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; in psc_dma_trigger()
124 dev_dbg(psc_dma->dev, "START: stream=%i fbits=%u ps=%u #p=%u\n", in psc_dma_trigger()
125 substream->pstr->stream, runtime->frame_bits, in psc_dma_trigger()
126 (int)runtime->period_size, runtime->periods); in psc_dma_trigger()
127 s->period_bytes = frames_to_bytes(runtime, in psc_dma_trigger()
128 runtime->period_size); in psc_dma_trigger()
129 s->period_next = 0; in psc_dma_trigger()
130 s->period_current = 0; in psc_dma_trigger()
131 s->active = 1; in psc_dma_trigger()
132 s->period_count = 0; in psc_dma_trigger()
133 s->runtime = runtime; in psc_dma_trigger()
138 spin_lock_irqsave(&psc_dma->lock, flags); in psc_dma_trigger()
140 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) in psc_dma_trigger()
141 bcom_gen_bd_rx_reset(s->bcom_task); in psc_dma_trigger()
143 bcom_gen_bd_tx_reset(s->bcom_task); in psc_dma_trigger()
145 for (i = 0; i < runtime->periods; i++) in psc_dma_trigger()
146 if (!bcom_queue_full(s->bcom_task)) in psc_dma_trigger()
149 bcom_enable(s->bcom_task); in psc_dma_trigger()
150 spin_unlock_irqrestore(&psc_dma->lock, flags); in psc_dma_trigger()
152 out_8(®s->command, MPC52xx_PSC_RST_ERR_STAT); in psc_dma_trigger()
157 dev_dbg(psc_dma->dev, "STOP: stream=%i periods_count=%i\n", in psc_dma_trigger()
158 substream->pstr->stream, s->period_count); in psc_dma_trigger()
159 s->active = 0; in psc_dma_trigger()
161 spin_lock_irqsave(&psc_dma->lock, flags); in psc_dma_trigger()
162 bcom_disable(s->bcom_task); in psc_dma_trigger()
163 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) in psc_dma_trigger()
164 bcom_gen_bd_rx_reset(s->bcom_task); in psc_dma_trigger()
166 bcom_gen_bd_tx_reset(s->bcom_task); in psc_dma_trigger()
167 spin_unlock_irqrestore(&psc_dma->lock, flags); in psc_dma_trigger()
172 dev_dbg(psc_dma->dev, "unhandled trigger: stream=%i cmd=%i\n", in psc_dma_trigger()
173 substream->pstr->stream, cmd); in psc_dma_trigger()
174 return -EINVAL; in psc_dma_trigger()
179 if (psc_dma->playback.active) in psc_dma_trigger()
181 if (psc_dma->capture.active) in psc_dma_trigger()
183 out_be16(®s->isr_imr.imr, psc_dma->imr | imr); in psc_dma_trigger()
189 /* ---------------------------------------------------------------------
193 * This driver only deals with the audio bus; it doesn't have any
214 struct snd_pcm_runtime *runtime = substream->runtime; in psc_dma_open()
220 dev_dbg(psc_dma->dev, "psc_dma_open(substream=%p)\n", substream); in psc_dma_open()
222 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) in psc_dma_open()
223 s = &psc_dma->capture; in psc_dma_open()
225 s = &psc_dma->playback; in psc_dma_open()
232 dev_err(substream->pcm->card->dev, "invalid buffer size\n"); in psc_dma_open()
236 s->stream = substream; in psc_dma_open()
247 dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream); in psc_dma_close()
249 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) in psc_dma_close()
250 s = &psc_dma->capture; in psc_dma_close()
252 s = &psc_dma->playback; in psc_dma_close()
254 if (!psc_dma->playback.active && in psc_dma_close()
255 !psc_dma->capture.active) { in psc_dma_close()
258 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); in psc_dma_close()
259 out_8(&psc_dma->psc_regs->command, 4 << 4); /* reset error */ in psc_dma_close()
261 s->stream = NULL; in psc_dma_close()
274 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) in psc_dma_pointer()
275 s = &psc_dma->capture; in psc_dma_pointer()
277 s = &psc_dma->playback; in psc_dma_pointer()
279 count = s->period_current * s->period_bytes; in psc_dma_pointer()
281 return bytes_to_frames(substream->runtime, count); in psc_dma_pointer()
287 struct snd_card *card = rtd->card->snd_card; in psc_dma_new()
289 struct snd_pcm *pcm = rtd->pcm; in psc_dma_new()
293 dev_dbg(component->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n", in psc_dma_new()
296 rc = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); in psc_dma_new()
300 return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, card->dev, in psc_dma_new()
324 irq = irq_of_parse_and_map(op->dev.of_node, 0); in mpc5200_audio_dma_create()
325 if (of_address_to_resource(op->dev.of_node, 0, &res)) { in mpc5200_audio_dma_create()
326 dev_err(&op->dev, "Missing reg property\n"); in mpc5200_audio_dma_create()
327 return -ENODEV; in mpc5200_audio_dma_create()
331 dev_err(&op->dev, "Could not map registers\n"); in mpc5200_audio_dma_create()
332 return -ENODEV; in mpc5200_audio_dma_create()
338 ret = -ENOMEM; in mpc5200_audio_dma_create()
343 prop = of_get_property(op->dev.of_node, "cell-index", &size); in mpc5200_audio_dma_create()
345 ret = -ENODEV; in mpc5200_audio_dma_create()
349 spin_lock_init(&psc_dma->lock); in mpc5200_audio_dma_create()
350 mutex_init(&psc_dma->mutex); in mpc5200_audio_dma_create()
351 psc_dma->id = be32_to_cpu(*prop); in mpc5200_audio_dma_create()
352 psc_dma->irq = irq; in mpc5200_audio_dma_create()
353 psc_dma->psc_regs = regs; in mpc5200_audio_dma_create()
354 psc_dma->fifo_regs = regs + sizeof *psc_dma->psc_regs; in mpc5200_audio_dma_create()
355 psc_dma->dev = &op->dev; in mpc5200_audio_dma_create()
356 psc_dma->playback.psc_dma = psc_dma; in mpc5200_audio_dma_create()
357 psc_dma->capture.psc_dma = psc_dma; in mpc5200_audio_dma_create()
358 snprintf(psc_dma->name, sizeof(psc_dma->name), "PSC%d", psc_dma->id); in mpc5200_audio_dma_create()
363 psc_dma->capture.bcom_task = in mpc5200_audio_dma_create()
364 bcom_psc_gen_bd_rx_init(psc_dma->id, 10, fifo, 512); in mpc5200_audio_dma_create()
365 psc_dma->playback.bcom_task = in mpc5200_audio_dma_create()
366 bcom_psc_gen_bd_tx_init(psc_dma->id, 10, fifo); in mpc5200_audio_dma_create()
367 if (!psc_dma->capture.bcom_task || in mpc5200_audio_dma_create()
368 !psc_dma->playback.bcom_task) { in mpc5200_audio_dma_create()
369 dev_err(&op->dev, "Could not allocate bestcomm tasks\n"); in mpc5200_audio_dma_create()
370 ret = -ENODEV; in mpc5200_audio_dma_create()
375 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); in mpc5200_audio_dma_create()
377 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_RX); in mpc5200_audio_dma_create()
379 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_TX); in mpc5200_audio_dma_create()
381 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_ERR_STAT); in mpc5200_audio_dma_create()
383 out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_SEL_MODE_REG_1); in mpc5200_audio_dma_create()
389 out_8(&psc_dma->psc_regs->mode, 0); in mpc5200_audio_dma_create()
390 out_8(&psc_dma->psc_regs->mode, 0); in mpc5200_audio_dma_create()
393 out_be16(&psc_dma->fifo_regs->rfalarm, 0x100); in mpc5200_audio_dma_create()
394 out_8(&psc_dma->fifo_regs->rfcntl, 0x4); in mpc5200_audio_dma_create()
395 out_be16(&psc_dma->fifo_regs->tfalarm, 0x100); in mpc5200_audio_dma_create()
396 out_8(&psc_dma->fifo_regs->tfcntl, 0x7); in mpc5200_audio_dma_create()
399 psc_dma->playback.irq = in mpc5200_audio_dma_create()
400 bcom_get_task_irq(psc_dma->playback.bcom_task); in mpc5200_audio_dma_create()
401 psc_dma->capture.irq = in mpc5200_audio_dma_create()
402 bcom_get_task_irq(psc_dma->capture.bcom_task); in mpc5200_audio_dma_create()
404 rc = request_irq(psc_dma->irq, &psc_dma_status_irq, IRQF_SHARED, in mpc5200_audio_dma_create()
405 "psc-dma-status", psc_dma); in mpc5200_audio_dma_create()
406 rc |= request_irq(psc_dma->capture.irq, &psc_dma_bcom_irq, IRQF_SHARED, in mpc5200_audio_dma_create()
407 "psc-dma-capture", &psc_dma->capture); in mpc5200_audio_dma_create()
408 rc |= request_irq(psc_dma->playback.irq, &psc_dma_bcom_irq, IRQF_SHARED, in mpc5200_audio_dma_create()
409 "psc-dma-playback", &psc_dma->playback); in mpc5200_audio_dma_create()
411 ret = -ENODEV; in mpc5200_audio_dma_create()
416 dev_set_drvdata(&op->dev, psc_dma); in mpc5200_audio_dma_create()
419 return devm_snd_soc_register_component(&op->dev, in mpc5200_audio_dma_create()
422 free_irq(psc_dma->irq, psc_dma); in mpc5200_audio_dma_create()
423 free_irq(psc_dma->capture.irq, &psc_dma->capture); in mpc5200_audio_dma_create()
424 free_irq(psc_dma->playback.irq, &psc_dma->playback); in mpc5200_audio_dma_create()
435 struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); in mpc5200_audio_dma_destroy()
437 dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n"); in mpc5200_audio_dma_destroy()
439 bcom_gen_bd_rx_release(psc_dma->capture.bcom_task); in mpc5200_audio_dma_destroy()
440 bcom_gen_bd_tx_release(psc_dma->playback.bcom_task); in mpc5200_audio_dma_destroy()
443 free_irq(psc_dma->irq, psc_dma); in mpc5200_audio_dma_destroy()
444 free_irq(psc_dma->capture.irq, &psc_dma->capture); in mpc5200_audio_dma_destroy()
445 free_irq(psc_dma->playback.irq, &psc_dma->playback); in mpc5200_audio_dma_destroy()
447 iounmap(psc_dma->psc_regs); in mpc5200_audio_dma_destroy()
449 dev_set_drvdata(&op->dev, NULL); in mpc5200_audio_dma_destroy()