static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)
{
	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
		if (dev->txnumevt) {	/* flush and enable FIFO */
			if (dev->version == MCASP_VERSION_3) {
				mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL,
								FIFO_ENABLE);
				mcasp_set_bits(dev->base + MCASP_VER3_WFIFOCTL,
								FIFO_ENABLE);
			} else {
				mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
								FIFO_ENABLE);
				mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
								FIFO_ENABLE);
			}
		}
		mcasp_start_tx(dev);
	} else {
		if (dev->rxnumevt) {	/* flush and enable FIFO */
			if (dev->version == MCASP_VERSION_3) {
				mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL,
								FIFO_ENABLE);
				mcasp_set_bits(dev->base + MCASP_VER3_RFIFOCTL,
								FIFO_ENABLE);
			} else {
				mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
								FIFO_ENABLE);
				mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
								FIFO_ENABLE);
			}
		}
		mcasp_start_rx(dev);
	}
}
static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
{
	int i;
	u8 tx_ser = 0;
	u8 rx_ser = 0;

	/* Default configuration */
	mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);

	/* All PINS as McASP */
	mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000);

	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
		mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
		mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG,
				TXDATADMADIS);
	} else {
		mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
		mcasp_clr_bits(dev->base + DAVINCI_MCASP_REVTCTL_REG,
				RXDATADMADIS);
	}

	for (i = 0; i < dev->num_serializer; i++) {
		mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
					dev->serial_dir[i]);
		if (dev->serial_dir[i] == TX_MODE) {
			mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
					AXR(i));
			tx_ser++;
		} else if (dev->serial_dir[i] == RX_MODE) {
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
					AXR(i));
			rx_ser++;
		}
	}

	if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) {
		if (dev->txnumevt * tx_ser > 64)
			dev->txnumevt = 1;

		mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, tx_ser,
								NUMDMA_MASK);
		mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
				((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK);
		mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
	}

	if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) {
		if (dev->rxnumevt * rx_ser > 64)
			dev->rxnumevt = 1;

		mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, rx_ser,
								NUMDMA_MASK);
		mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
				((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
		mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
	}
}
Example #3
0
static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream)
{
	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
		if (dev->txnumevt)	/* disable FIFO */
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
								FIFO_ENABLE);
		mcasp_stop_tx(dev);
	} else {
		if (dev->rxnumevt)	/* disable FIFO */
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
								FIFO_ENABLE);
		mcasp_stop_rx(dev);
	}
}
Example #4
0
/* S/PDIF */
static void davinci_hw_dit_param(struct davinci_audio_dev *dev)
{
	/* Set the PDIR for Serialiser as output */
	mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX);

	/* TXMASK for 24 bits */
	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF);

	/* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
	   and LSB first */
	mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
						TXROT(6) | TXSSZ(15));

	/* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */
	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
						AFSXE | FSXMOD(0x180));

	/* Set the TX tdm : for all the slots */
	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);

	/* Set the TX clock controls : div = 1 and internal */
	mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
						ACLKXE | TX_ASYNC);

	mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);

	/* Only 44100 and 48000 are valid, both have the same setting */
	mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3));

	/* Enable the DIT */
	mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN);
}
Example #5
0
static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
{
	int i, active_slots;
	u32 mask = 0;

	active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots;
	for (i = 0; i < active_slots; i++)
		mask |= (1 << i);

	mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);

	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
		/* bit stream is MSB first  with no delay */
		/* DSP_B mode */
		mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
				AHCLKXE);
		mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
		mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);

		if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
			mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
					FSXMOD(dev->tdm_slots), FSXMOD(0x1FF));
		else
			printk(KERN_ERR "playback tdm slot %d not supported\n",
				dev->tdm_slots);

		mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
	} else {
		/* bit stream is MSB first with no delay */
		/* DSP_B mode */
		mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
		mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
				AHCLKRE);
		mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);

		if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
			mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
					FSRMOD(dev->tdm_slots), FSRMOD(0x1FF));
		else
			printk(KERN_ERR "capture tdm slot %d not supported\n",
				dev->tdm_slots);

		mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
	}
}
Example #6
0
static irqreturn_t mcasp_irq_handler(int irq, void *dev_id,
				struct pt_regs *regs)
{
	struct platform_device *pdev = dev_id;
	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
	struct snd_soc_machine *machine = socdev->machine;
	struct snd_soc_cpu_dai *cpu_dai;
	struct davinci_audio_dev *dev;
	int link_cnt;
	void __iomem *base;

	for (link_cnt = 0; link_cnt < machine->num_links; link_cnt++) {
		cpu_dai = machine->dai_link[link_cnt].cpu_dai;
		dev = cpu_dai->private_data;
		base = dev->base;

		if (mcasp_get_reg(base + DAVINCI_MCASP_TXSTAT_REG) & 0x1) {
			mcasp_clr_bits(base + DAVINCI_MCASP_EVTCTLX_REG, 1);
			schedule_delayed_work(&dev->workq, HZ >> 4);
		}
	}
Example #7
0
static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
					 unsigned int fmt)
{
	struct davinci_audio_dev *dev = cpu_dai->private_data;
	void __iomem *base = dev->base;

	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
	case SND_SOC_DAIFMT_CBS_CFS:
		/* codec is clock and frame slave */
		mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
		mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);

		mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
		mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

		mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 26));
		break;
	case SND_SOC_DAIFMT_CBM_CFS:
		/* codec is clock master and frame slave */
		mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
		mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);

		mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
		mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

		mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x2d << 26));
		break;
	case SND_SOC_DAIFMT_CBM_CFM:
		/* codec is clock and frame master */
		mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
		mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);

		mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
		mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

		mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, (0x3f << 26));
		break;

	default:
		return -EINVAL;
	}

	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
	case SND_SOC_DAIFMT_IB_NF:
		mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
		mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);

		mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
		mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
		break;

	case SND_SOC_DAIFMT_NB_IF:
		mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
		mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);

		mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
		mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
		break;

	case SND_SOC_DAIFMT_IB_IF:
		mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
		mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);

		mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
		mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
		break;

	case SND_SOC_DAIFMT_NB_NF:
		mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
		mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);

		mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
		mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
		break;

	default:
		return -EINVAL;
	}

	return 0;
}
static int davinci_mcasp_set_dai_clkdiv(struct snd_soc_dai *dai, int div_id,
		int div)
{
	struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);

	switch (div_id) {
	case DAVINCI_MCASP_CLKXDIV:
		div--;
		if (div < 0) {
			dev_err(dev->dev, "tried to set invalid clkdiv\n");
			return -EINVAL;
		} else if (div/3 > 31) {
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
				AHCLKXDIV(0xfff));
			mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
				AHCLKXDIV(3));
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
				ACLKXDIV(0x1F));
			mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
				ACLKXDIV(div/4));
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
				AHCLKRDIV(0xfff));
			mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
				AHCLKRDIV(3));
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
				ACLKRDIV(0x1F));
			mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
				ACLKRDIV(div/4));
		} else if (div > 31) {
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
				AHCLKXDIV(0xfff));
			mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
				AHCLKXDIV(2));
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
				ACLKXDIV(0x1F));
			mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
				ACLKXDIV(div/3));
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
				AHCLKRDIV(0xfff));
			mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
				AHCLKRDIV(2));
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
				ACLKRDIV(0x1F));
			mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
				ACLKRDIV(div/3));
		} else {
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
				AHCLKXDIV(0xfff));
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
				ACLKXDIV(0x1F));
			mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
				ACLKXDIV(div));
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
				AHCLKRDIV(0xfff));
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
				ACLKRDIV(0x1F));
			mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
				ACLKRDIV(div));
		}
		break;
	default:
		dev_err(dev->dev, "tried to set unsupported clkdiv\n");
		return -EINVAL;
	}

	return 0;
}
static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
{
	int i, active_slots;
	u32 mask = 0, val;

	active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots;
	for (i = 0; i < active_slots; i++)
		mask |= (1 << i);

	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
		/* bit stream is MSB first with no delay */
		/* DSP_B mode or I2S mode */
		/* AHCLK from internal clk */
		mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
				AHCLKXE);
		/* in which tdm slots is the transmitter active */
		mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);

		/* MSB first (and 1 bit delay for I2S) */
		val = TXORD;
		if ((dev->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
			SND_SOC_DAIFMT_I2S)
			val |= FSXDLY(1);

		mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, val);

		if (((dev->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
				SND_SOC_DAIFMT_I2S) &&
			(dev->tdm_slots != 2))
			dev_err(dev->dev, "I2S should have 2 tdm_slots\n");

		if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
			mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
					FSXMOD(dev->tdm_slots), FSXMOD(0x1FF));
		else
			printk(KERN_ERR "playback tdm slot %d not supported\n",
				dev->tdm_slots);

		/* frame sync width */
		if ((dev->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
				SND_SOC_DAIFMT_I2S)
			mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
					FSXDUR);
		else
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
					FSXDUR);
	} else {
		/* bit stream is MSB first (and 1 bit delay for I2S) */
		/* DSP_B mode or I2S mode */
		val = TXORD;
		if ((dev->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
				SND_SOC_DAIFMT_I2S)
			val |= FSXDLY(1);
		mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, val);

		mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
				AHCLKXE);
		mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
				AHCLKRE);
		mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);

		if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32)) {
			mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
					FSRMOD(dev->tdm_slots), FSRMOD(0x1FF));
			mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
					FSRMOD(dev->tdm_slots), FSXMOD(0x1FF));
			}
		else
			printk(KERN_ERR "capture tdm slot %d not supported\n",
				dev->tdm_slots);

		/* frame sync width */
		if ((dev->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
				SND_SOC_DAIFMT_I2S) {
			mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
				FSXDUR);
			mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
				FSRDUR);
			}
		else {
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
				FSXDUR);
			mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
				FSRDUR);
			}
	}
}