Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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(&regs->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(&regs->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(&regs->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(&regs->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");