static void mcasp_start_tx(struct davinci_audio_dev *dev) { u8 offset = 0, i; u32 cnt; mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); for (i = 0; i < dev->num_serializer; i++) { if (dev->serial_dir[i] == TX_MODE) { offset = i; break; } } /* wait for TX ready */ cnt = 0; while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) & TXSTATE) && (cnt < 100000)) cnt++; mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 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); }
static void mcasp_stop_rx(struct davinci_audio_dev *dev) { mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0); mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0); mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); }
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); } }
static void mcasp_start_rx(struct davinci_audio_dev *dev) { mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); }
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); } }
static int davinci_config_channel_size(struct davinci_audio_dev *dev, int channel_size) { u32 fmt = 0; u32 mask, rotate; switch (channel_size) { case DAVINCI_AUDIO_WORD_8: fmt = 0x03; rotate = 6; mask = 0x000000ff; break; case DAVINCI_AUDIO_WORD_12: fmt = 0x05; rotate = 5; mask = 0x00000fff; break; case DAVINCI_AUDIO_WORD_16: fmt = 0x07; rotate = 4; mask = 0x0000ffff; break; case DAVINCI_AUDIO_WORD_20: fmt = 0x09; rotate = 3; mask = 0x000fffff; break; case DAVINCI_AUDIO_WORD_24: fmt = 0x0B; rotate = 2; mask = 0x00ffffff; break; case DAVINCI_AUDIO_WORD_28: fmt = 0x0D; rotate = 1; mask = 0x0fffffff; break; case DAVINCI_AUDIO_WORD_32: fmt = 0x0F; rotate = 0; mask = 0xffffffff; break; default: return -EINVAL; } mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt), RXSSZ(0x0F)); mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt), TXSSZ(0x0F)); mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXROT(rotate), TXROT(7)); mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXROT(rotate), RXROT(7)); mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask); mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, mask); 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 int davinci_mcasp_resume(struct platform_device *pdev) { int ret = 0, idx; struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) dev_err(&pdev->dev, "failed to get runtime pm\n"); if (dev->version == MCASP_VERSION_3) { mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, dev->gblctlx); mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, dev->txmask); mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMT_REG, dev->txfmt); mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG, dev->txfmctl); mcasp_set_reg(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, dev->aclkxctl); mcasp_set_reg(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, dev->ahclkxctl); mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, dev->txtdm); mcasp_set_reg(dev->base + MCASP_VER3_WFIFOCTL, dev->wfifoctl); mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, dev->gblctlr); mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, dev->rxmask); mcasp_set_reg(dev->base + DAVINCI_MCASP_RXFMT_REG, dev->rxfmt); mcasp_set_reg(dev->base + DAVINCI_MCASP_RXFMCTL_REG, dev->rxfmctl); mcasp_set_reg(dev->base + DAVINCI_MCASP_ACLKRCTL_REG, dev->aclkrctl); mcasp_set_reg(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, dev->ahclkrctl); mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, dev->rxtdm); mcasp_set_reg(dev->base + MCASP_VER3_RFIFOCTL, dev->rfifoctl); for (idx = 0; idx < dev->num_serializer; idx++) { mcasp_set_reg((dev->base + DAVINCI_MCASP_XRSRCTL_REG(idx)), dev->xrsrctl[idx]); } mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, dev->pfunc); mcasp_set_reg(dev->base + DAVINCI_MCASP_PDIR_REG, dev->pdir); } /* only values < 0 indicate errors */ return IS_ERR_VALUE(ret) ? ret : 0; }