summaryrefslogtreecommitdiffstats
path: root/sound/soc/davinci/davinci-mcasp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/davinci/davinci-mcasp.c')
-rw-r--r--sound/soc/davinci/davinci-mcasp.c79
1 files changed, 40 insertions, 39 deletions
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 0eed9b1b24e1..ea3ad747d092 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -154,9 +154,9 @@ static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp)
static void mcasp_start_rx(struct davinci_mcasp *mcasp)
{
+ /* Start clocks */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
-
/*
* When ASYNC == 0 the transmit and receive sections operate
* synchronously from the transmit clock and frame sync. We need to make
@@ -167,47 +167,36 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp)
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
}
+ /* Activate serializer(s) */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
- mcasp_set_reg(mcasp, DAVINCI_MCASP_RXBUF_REG, 0);
-
- mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
- mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
- mcasp_set_reg(mcasp, DAVINCI_MCASP_RXBUF_REG, 0);
-
+ /* Release RX state machine */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
+ /* Release Frame Sync generator */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
-
if (mcasp_is_synchronous(mcasp))
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
}
static void mcasp_start_tx(struct davinci_mcasp *mcasp)
{
- u8 offset = 0, i;
u32 cnt;
+ /* Start clocks */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
+ /* Activate serializer(s) */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
- mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0);
- mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
- mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
- mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0);
- for (i = 0; i < mcasp->num_serializer; i++) {
- if (mcasp->serial_dir[i] == TX_MODE) {
- offset = i;
- break;
- }
- }
-
- /* wait for TX ready */
+ /* wait for XDATA to be cleared */
cnt = 0;
- while (!(mcasp_get_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(offset)) &
- TXSTATE) && (cnt < 100000))
+ while (!(mcasp_get_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG) &
+ ~XRDATA) && (cnt < 100000))
cnt++;
- mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0);
+ /* Release TX state machine */
+ mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
+ /* Release Frame Sync generator */
+ mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
}
static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream)
@@ -244,6 +233,12 @@ static void mcasp_stop_rx(struct davinci_mcasp *mcasp)
mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0);
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
+
+ if (mcasp->rxnumevt) { /* disable FIFO */
+ u32 reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
+
+ mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
+ }
}
static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
@@ -259,27 +254,22 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val);
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
+
+ if (mcasp->txnumevt) { /* disable FIFO */
+ u32 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
+
+ mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
+ }
}
static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream)
{
- u32 reg;
-
mcasp->streams--;
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- if (mcasp->txnumevt) { /* disable FIFO */
- reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
- mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
- }
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
mcasp_stop_tx(mcasp);
- } else {
- if (mcasp->rxnumevt) { /* disable FIFO */
- reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
- mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
- }
+ else
mcasp_stop_rx(mcasp);
- }
}
static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
@@ -500,8 +490,17 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
* both left and right channels), so it has to be divided by number of
* tdm-slots (for I2S - divided by 2).
*/
- if (mcasp->bclk_lrclk_ratio)
- word_length = mcasp->bclk_lrclk_ratio / mcasp->tdm_slots;
+ if (mcasp->bclk_lrclk_ratio) {
+ u32 slot_length = mcasp->bclk_lrclk_ratio / mcasp->tdm_slots;
+
+ /*
+ * When we have more bclk then it is needed for the data, we
+ * need to use the rotation to move the received samples to have
+ * correct alignment.
+ */
+ rx_rotate = (slot_length - word_length) / 4;
+ word_length = slot_length;
+ }
/* mapping of the XSSZ bit-field as described in the datasheet */
fmt = (word_length >> 1) - 1;
@@ -971,6 +970,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
},
.ops = &davinci_mcasp_dai_ops,
+ .symmetric_samplebits = 1,
},
{
.name = "davinci-mcasp.1",
@@ -1235,6 +1235,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
ret = pm_runtime_get_sync(&pdev->dev);
if (IS_ERR_VALUE(ret)) {
dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
+ pm_runtime_disable(&pdev->dev);
return ret;
}
OpenPOWER on IntegriCloud