static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
{
	int i = 0;

	mcasp_set_bits(regs, val);

	/* programming GBLCTL needs to read back from GBLCTL and verfiy */
	/* loop count is to avoid the lock-up */
	for (i = 0; i < 1000; i++) {
		if ((mcasp_get_reg(regs) & val) == val)
			break;
	}

	if (i == 1000 && ((mcasp_get_reg(regs) & val) != val))
		printk(KERN_ERR "GBLCTL write error\n");
}
Пример #2
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);
			}
	}
}
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;

		if (dev->version == MCASP_VERSION_3) {
			mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, tx_ser,
								NUMDMA_MASK);
			mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL,
				((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK);
		} else {
			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);
		}
	}

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

		if (dev->version == MCASP_VERSION_3) {
			mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, rx_ser,
								NUMDMA_MASK);
			mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL,
					((dev->rxnumevt * rx_ser) << 8),
					NUMEVT_MASK);
		} else {
			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);
		}
	}
}
Пример #6
0
static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
{
	mcasp_set_bits(regs, val);
	while ((mcasp_get_reg(regs) & val) != val);
}