^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Freescale MPC5200 PSC DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) // ALSA SoC Platform driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) // Copyright (C) 2008 Secret Lab Technologies Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) // Copyright (C) 2009 Jon Smirl, Digispeaker
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/fsl/bestcomm/bestcomm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/fsl/bestcomm/gen_bd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/mpc52xx_psc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "mpc5200_dma.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define DRV_NAME "mpc5200_dma"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Interrupt handlers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static irqreturn_t psc_dma_status_irq(int irq, void *_psc_dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct psc_dma *psc_dma = _psc_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) u16 isr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) isr = in_be16(®s->mpc52xx_psc_isr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* Playback underrun error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (psc_dma->playback.active && (isr & MPC52xx_PSC_IMR_TXEMP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) psc_dma->stats.underrun_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* Capture overrun error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (psc_dma->capture.active && (isr & MPC52xx_PSC_IMR_ORERR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) psc_dma->stats.overrun_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) out_8(®s->command, MPC52xx_PSC_RST_ERR_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * psc_dma_bcom_enqueue_next_buffer - Enqueue another audio buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * @s: pointer to stream private data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * Enqueues another audio period buffer into the bestcomm queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * Note: The routine must only be called when there is space available in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * the queue. Otherwise the enqueue will fail and the audio ring buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * will get out of sync
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static void psc_dma_bcom_enqueue_next_buffer(struct psc_dma_stream *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct bcom_bd *bd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* Prepare and enqueue the next buffer descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) bd = bcom_prepare_next_buffer(s->bcom_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) bd->status = s->period_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) bd->data[0] = s->runtime->dma_addr + (s->period_next * s->period_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) bcom_submit_next_buffer(s->bcom_task, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* Update for next period */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) s->period_next = (s->period_next + 1) % s->runtime->periods;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* Bestcomm DMA irq handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static irqreturn_t psc_dma_bcom_irq(int irq, void *_psc_dma_stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct psc_dma_stream *s = _psc_dma_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) spin_lock(&s->psc_dma->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* For each finished period, dequeue the completed period buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * and enqueue a new one in it's place. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) while (bcom_buffer_done(s->bcom_task)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) s->period_current = (s->period_current+1) % s->runtime->periods;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) s->period_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) psc_dma_bcom_enqueue_next_buffer(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) spin_unlock(&s->psc_dma->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* If the stream is active, then also inform the PCM middle layer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * of the period finished event. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (s->active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) snd_pcm_period_elapsed(s->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static int psc_dma_hw_free(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) snd_pcm_set_runtime_buffer(substream, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * psc_dma_trigger: start and stop the DMA transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * This function is called by ALSA to start, stop, pause, and resume the DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * transfer of data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static int psc_dma_trigger(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u16 imr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) dev_dbg(psc_dma->dev, "START: stream=%i fbits=%u ps=%u #p=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) substream->pstr->stream, runtime->frame_bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) (int)runtime->period_size, runtime->periods);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) s->period_bytes = frames_to_bytes(runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) runtime->period_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) s->period_next = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) s->period_current = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) s->active = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) s->period_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) s->runtime = runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* Fill up the bestcomm bd queue and enable DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * This will begin filling the PSC's fifo.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) spin_lock_irqsave(&psc_dma->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) bcom_gen_bd_rx_reset(s->bcom_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) bcom_gen_bd_tx_reset(s->bcom_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) for (i = 0; i < runtime->periods; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (!bcom_queue_full(s->bcom_task))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) psc_dma_bcom_enqueue_next_buffer(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) bcom_enable(s->bcom_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) spin_unlock_irqrestore(&psc_dma->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) out_8(®s->command, MPC52xx_PSC_RST_ERR_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) dev_dbg(psc_dma->dev, "STOP: stream=%i periods_count=%i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) substream->pstr->stream, s->period_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) s->active = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) spin_lock_irqsave(&psc_dma->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) bcom_disable(s->bcom_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) bcom_gen_bd_rx_reset(s->bcom_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) bcom_gen_bd_tx_reset(s->bcom_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) spin_unlock_irqrestore(&psc_dma->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) dev_dbg(psc_dma->dev, "unhandled trigger: stream=%i cmd=%i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) substream->pstr->stream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /* Update interrupt enable settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) imr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (psc_dma->playback.active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) imr |= MPC52xx_PSC_IMR_TXEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (psc_dma->capture.active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) imr |= MPC52xx_PSC_IMR_ORERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) out_be16(®s->isr_imr.imr, psc_dma->imr | imr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /* ---------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * The PSC DMA 'ASoC platform' driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * Can be referenced by an 'ASoC machine' driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * This driver only deals with the audio bus; it doesn't have any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * interaction with the attached codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static const struct snd_pcm_hardware psc_dma_hardware = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) SNDRV_PCM_INFO_BATCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .period_bytes_max = 1024 * 1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .period_bytes_min = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .periods_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .periods_max = 256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .buffer_bytes_max = 2 * 1024 * 1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .fifo_size = 512,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static int psc_dma_open(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct psc_dma_stream *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) dev_dbg(psc_dma->dev, "psc_dma_open(substream=%p)\n", substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) s = &psc_dma->capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) s = &psc_dma->playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) snd_soc_set_runtime_hwparams(substream, &psc_dma_hardware);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) rc = snd_pcm_hw_constraint_integer(runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) SNDRV_PCM_HW_PARAM_PERIODS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) dev_err(substream->pcm->card->dev, "invalid buffer size\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) s->stream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static int psc_dma_close(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct psc_dma_stream *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) s = &psc_dma->capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) s = &psc_dma->playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (!psc_dma->playback.active &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) !psc_dma->capture.active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* Disable all interrupts and reset the PSC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) out_8(&psc_dma->psc_regs->command, 4 << 4); /* reset error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) s->stream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static snd_pcm_uframes_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) psc_dma_pointer(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct psc_dma_stream *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dma_addr_t count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) s = &psc_dma->capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) s = &psc_dma->playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) count = s->period_current * s->period_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return bytes_to_frames(substream->runtime, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static int psc_dma_hw_params(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static int psc_dma_new(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct snd_soc_pcm_runtime *rtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct snd_card *card = rtd->card->snd_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) struct snd_pcm *pcm = rtd->pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) size_t size = psc_dma_hardware.buffer_bytes_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) dev_dbg(component->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) card, dai, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) rc = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) size, &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) goto playback_alloc_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) size, &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) goto capture_alloc_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) capture_alloc_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) playback_alloc_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) dev_err(card->dev, "Cannot allocate buffer(s)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static void psc_dma_free(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct snd_pcm *pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) dev_dbg(component->dev, "psc_dma_free(pcm=%p)\n", pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) for (stream = 0; stream < 2; stream++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) substream = pcm->streams[stream].substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) snd_dma_free_pages(&substream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) substream->dma_buffer.area = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) substream->dma_buffer.addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static const struct snd_soc_component_driver mpc5200_audio_dma_component = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) .name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) .open = psc_dma_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) .close = psc_dma_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) .hw_free = psc_dma_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) .pointer = psc_dma_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) .trigger = psc_dma_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) .hw_params = psc_dma_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) .pcm_construct = psc_dma_new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) .pcm_destruct = psc_dma_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) int mpc5200_audio_dma_create(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) phys_addr_t fifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct psc_dma *psc_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) int size, irq, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) const __be32 *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /* Fetch the registers and IRQ of the PSC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) irq = irq_of_parse_and_map(op->dev.of_node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (of_address_to_resource(op->dev.of_node, 0, &res)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) dev_err(&op->dev, "Missing reg property\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) regs = ioremap(res.start, resource_size(&res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (!regs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) dev_err(&op->dev, "Could not map registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /* Allocate and initialize the driver private data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) psc_dma = kzalloc(sizeof *psc_dma, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!psc_dma) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) goto out_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /* Get the PSC ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) prop = of_get_property(op->dev.of_node, "cell-index", &size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (!prop || size < sizeof *prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) spin_lock_init(&psc_dma->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) mutex_init(&psc_dma->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) psc_dma->id = be32_to_cpu(*prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) psc_dma->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) psc_dma->psc_regs = regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) psc_dma->fifo_regs = regs + sizeof *psc_dma->psc_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) psc_dma->dev = &op->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) psc_dma->playback.psc_dma = psc_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) psc_dma->capture.psc_dma = psc_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) snprintf(psc_dma->name, sizeof psc_dma->name, "PSC%u", psc_dma->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /* Find the address of the fifo data registers and setup the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * DMA tasks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) fifo = res.start + offsetof(struct mpc52xx_psc, buffer.buffer_32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) psc_dma->capture.bcom_task =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) bcom_psc_gen_bd_rx_init(psc_dma->id, 10, fifo, 512);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) psc_dma->playback.bcom_task =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) bcom_psc_gen_bd_tx_init(psc_dma->id, 10, fifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (!psc_dma->capture.bcom_task ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) !psc_dma->playback.bcom_task) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) dev_err(&op->dev, "Could not allocate bestcomm tasks\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) /* Disable all interrupts and reset the PSC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /* reset receiver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_RX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) /* reset transmitter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_TX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /* reset error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_ERR_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* reset mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_SEL_MODE_REG_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* Set up mode register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * First write: RxRdy (FIFO Alarm) generates rx FIFO irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * Second write: register Normal mode for non loopback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) out_8(&psc_dma->psc_regs->mode, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) out_8(&psc_dma->psc_regs->mode, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* Set the TX and RX fifo alarm thresholds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) out_be16(&psc_dma->fifo_regs->rfalarm, 0x100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) out_8(&psc_dma->fifo_regs->rfcntl, 0x4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) out_be16(&psc_dma->fifo_regs->tfalarm, 0x100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) out_8(&psc_dma->fifo_regs->tfcntl, 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* Lookup the IRQ numbers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) psc_dma->playback.irq =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) bcom_get_task_irq(psc_dma->playback.bcom_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) psc_dma->capture.irq =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) bcom_get_task_irq(psc_dma->capture.bcom_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) rc = request_irq(psc_dma->irq, &psc_dma_status_irq, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) "psc-dma-status", psc_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) rc |= request_irq(psc_dma->capture.irq, &psc_dma_bcom_irq, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) "psc-dma-capture", &psc_dma->capture);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) rc |= request_irq(psc_dma->playback.irq, &psc_dma_bcom_irq, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) "psc-dma-playback", &psc_dma->playback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) goto out_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /* Save what we've done so it can be found again later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) dev_set_drvdata(&op->dev, psc_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* Tell the ASoC OF helpers about it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return devm_snd_soc_register_component(&op->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) &mpc5200_audio_dma_component, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) out_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) free_irq(psc_dma->irq, psc_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) free_irq(psc_dma->capture.irq, &psc_dma->capture);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) free_irq(psc_dma->playback.irq, &psc_dma->playback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) kfree(psc_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) out_unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) iounmap(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) int mpc5200_audio_dma_destroy(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) struct psc_dma *psc_dma = dev_get_drvdata(&op->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) bcom_gen_bd_rx_release(psc_dma->capture.bcom_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) bcom_gen_bd_tx_release(psc_dma->playback.bcom_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /* Release irqs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) free_irq(psc_dma->irq, psc_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) free_irq(psc_dma->capture.irq, &psc_dma->capture);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) free_irq(psc_dma->playback.irq, &psc_dma->playback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) iounmap(psc_dma->psc_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) kfree(psc_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) dev_set_drvdata(&op->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) EXPORT_SYMBOL_GPL(mpc5200_audio_dma_destroy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) MODULE_LICENSE("GPL");