static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mask, int slots, int slot_width) { struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots)); regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA, ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask)); regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB, ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(tx_mask)); regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots)); regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA, ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask)); regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB, ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(rx_mask)); esai_priv->slot_width = slot_width; return 0; }
static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; u8 i, channels = substream->runtime->channels; u32 pins = DIV_ROUND_UP(channels, esai_priv->slots); u32 mask; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN); /* Write initial words reqiured by ESAI as normal procedure */ for (i = 0; tx && i < channels; i++) regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0); regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins)); mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask; regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask)); regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask)); break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0); regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), ESAI_xSMA_xS_MASK, 0); regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), ESAI_xSMB_xS_MASK, 0); /* Disable and reset FIFO */ regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR); regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), ESAI_xFCR_xFR, 0); break; default: return -EINVAL; } return 0; }