^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Freescale ESAI ALSA SoC Digital Audio Interface (DAI) driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // Copyright (C) 2014 Freescale Semiconductor, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/dmaengine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <sound/dmaengine_pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "fsl_esai.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "imx-pcm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define FSL_ESAI_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) SNDRV_PCM_FMTBIT_S16_LE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) SNDRV_PCM_FMTBIT_S20_3LE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) SNDRV_PCM_FMTBIT_S24_LE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * struct fsl_esai_soc_data - soc specific data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * @imx: for imx platform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * @reset_at_xrun: flags for enable reset operaton
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct fsl_esai_soc_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) bool imx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) bool reset_at_xrun;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * struct fsl_esai - ESAI private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * @dma_params_rx: DMA parameters for receive channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * @dma_params_tx: DMA parameters for transmit channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * @pdev: platform device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * @regmap: regmap handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * @coreclk: clock source to access register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * @extalclk: esai clock source to derive HCK, SCK and FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * @fsysclk: system clock source to derive HCK, SCK and FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * @spbaclk: SPBA clock (optional, depending on SoC design)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * @work: work to handle the reset operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * @soc: soc specific data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * @lock: spin lock between hw_reset() and trigger()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * @fifo_depth: depth of tx/rx FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * @slot_width: width of each DAI slot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * @slots: number of slots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * @tx_mask: slot mask for TX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * @rx_mask: slot mask for RX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * @channels: channel num for tx or rx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * @hck_rate: clock rate of desired HCKx clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * @sck_rate: clock rate of desired SCKx clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * @hck_dir: the direction of HCKx pads
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * @sck_div: if using PSR/PM dividers for SCKx clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * @slave_mode: if fully using DAI slave mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * @synchronous: if using tx/rx synchronous mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * @name: driver name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct fsl_esai {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct snd_dmaengine_dai_dma_data dma_params_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct snd_dmaengine_dai_dma_data dma_params_tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct clk *coreclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct clk *extalclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct clk *fsysclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct clk *spbaclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct work_struct work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) const struct fsl_esai_soc_data *soc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) spinlock_t lock; /* Protect hw_reset and trigger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) u32 fifo_depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u32 slot_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u32 slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u32 tx_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u32 rx_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u32 channels[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u32 hck_rate[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u32 sck_rate[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) bool hck_dir[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) bool sck_div[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) bool slave_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) bool synchronous;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) char name[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static struct fsl_esai_soc_data fsl_esai_vf610 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .imx = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .reset_at_xrun = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static struct fsl_esai_soc_data fsl_esai_imx35 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .imx = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .reset_at_xrun = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static struct fsl_esai_soc_data fsl_esai_imx6ull = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .imx = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .reset_at_xrun = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static irqreturn_t esai_isr(int irq, void *devid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct fsl_esai *esai_priv = (struct fsl_esai *)devid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct platform_device *pdev = esai_priv->pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u32 esr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u32 saisr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) regmap_read(esai_priv->regmap, REG_ESAI_ESR, &esr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) regmap_read(esai_priv->regmap, REG_ESAI_SAISR, &saisr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if ((saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) esai_priv->soc->reset_at_xrun) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) dev_dbg(&pdev->dev, "reset module for xrun\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ESAI_xCR_xEIE_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ESAI_xCR_xEIE_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) schedule_work(&esai_priv->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (esr & ESAI_ESR_TINIT_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) dev_dbg(&pdev->dev, "isr: Transmission Initialized\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (esr & ESAI_ESR_RFF_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) dev_warn(&pdev->dev, "isr: Receiving overrun\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (esr & ESAI_ESR_TFE_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) dev_warn(&pdev->dev, "isr: Transmission underrun\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (esr & ESAI_ESR_TLS_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) dev_dbg(&pdev->dev, "isr: Just transmitted the last slot\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (esr & ESAI_ESR_TDE_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) dev_dbg(&pdev->dev, "isr: Transmission data exception\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (esr & ESAI_ESR_TED_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) dev_dbg(&pdev->dev, "isr: Transmitting even slots\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (esr & ESAI_ESR_TD_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) dev_dbg(&pdev->dev, "isr: Transmitting data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (esr & ESAI_ESR_RLS_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) dev_dbg(&pdev->dev, "isr: Just received the last slot\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (esr & ESAI_ESR_RDE_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) dev_dbg(&pdev->dev, "isr: Receiving data exception\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (esr & ESAI_ESR_RED_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) dev_dbg(&pdev->dev, "isr: Receiving even slots\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (esr & ESAI_ESR_RD_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) dev_dbg(&pdev->dev, "isr: Receiving data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * fsl_esai_divisor_cal - This function is used to calculate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * divisors of psr, pm, fp and it is supposed to be called in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * set_dai_sysclk() and set_bclk().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * @dai: pointer to DAI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * @tx: current setting is for playback or capture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * @ratio: desired overall ratio for the paticipating dividers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * @usefp: for HCK setting, there is no need to set fp divider
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * @fp: bypass other dividers by setting fp directly if fp != 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static int fsl_esai_divisor_cal(struct snd_soc_dai *dai, bool tx, u32 ratio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) bool usefp, u32 fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) u32 psr, pm = 999, maxfp, prod, sub, savesub, i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) maxfp = usefp ? 16 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (usefp && fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) goto out_fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (ratio > 2 * 8 * 256 * maxfp || ratio < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) dev_err(dai->dev, "the ratio is out of range (2 ~ %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 2 * 8 * 256 * maxfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) } else if (ratio % 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) dev_err(dai->dev, "the raio must be even if using upper divider\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ratio /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) psr = ratio <= 256 * maxfp ? ESAI_xCCR_xPSR_BYPASS : ESAI_xCCR_xPSR_DIV8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* Do not loop-search if PM (1 ~ 256) alone can serve the ratio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (ratio <= 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) pm = ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) fp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /* Set the max fluctuation -- 0.1% of the max devisor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) savesub = (psr ? 1 : 8) * 256 * maxfp / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* Find the best value for PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) for (i = 1; i <= 256; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) for (j = 1; j <= maxfp; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* PSR (1 or 8) * PM (1 ~ 256) * FP (1 ~ 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) prod = (psr ? 1 : 8) * i * j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (prod == ratio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) sub = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) else if (prod / ratio == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) sub = prod - ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) else if (ratio / prod == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) sub = ratio - prod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* Calculate the fraction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) sub = sub * 1000 / ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (sub < savesub) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) savesub = sub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) pm = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) fp = j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /* We are lucky */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (savesub == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (pm == 999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) dev_err(dai->dev, "failed to calculate proper divisors\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ESAI_xCCR_xPSR_MASK | ESAI_xCCR_xPM_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) psr | ESAI_xCCR_xPM(pm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) out_fp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* Bypass fp if not being required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (maxfp <= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) ESAI_xCCR_xFP_MASK, ESAI_xCCR_xFP(fp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * fsl_esai_set_dai_sysclk - configure the clock frequency of MCLK (HCKT/HCKR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * @dai: pointer to DAI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * @clk_id: The clock source of HCKT/HCKR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * (Input from outside; output from inside, FSYS or EXTAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * @freq: The required clock rate of HCKT/HCKR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * @dir: The clock direction of HCKT/HCKR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * Note: If the direction is input, we do not care about clk_id.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) unsigned int freq, int dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct clk *clksrc = esai_priv->extalclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) bool tx = (clk_id <= ESAI_HCKT_EXTAL || esai_priv->synchronous);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) bool in = dir == SND_SOC_CLOCK_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) u32 ratio, ecr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) unsigned long clk_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (freq == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dev_err(dai->dev, "%sput freq of HCK%c should not be 0Hz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) in ? "in" : "out", tx ? 'T' : 'R');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /* Bypass divider settings if the requirement doesn't change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (freq == esai_priv->hck_rate[tx] && dir == esai_priv->hck_dir[tx])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* sck_div can be only bypassed if ETO/ERO=0 and SNC_SOC_CLOCK_OUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) esai_priv->sck_div[tx] = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /* Set the direction of HCKT/HCKR pins */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ESAI_xCCR_xHCKD, in ? 0 : ESAI_xCCR_xHCKD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) switch (clk_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) case ESAI_HCKT_FSYS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) case ESAI_HCKR_FSYS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) clksrc = esai_priv->fsysclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) case ESAI_HCKT_EXTAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) ecr |= ESAI_ECR_ETI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) case ESAI_HCKR_EXTAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ecr |= esai_priv->synchronous ? ESAI_ECR_ETI : ESAI_ECR_ERI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (IS_ERR(clksrc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) dev_err(dai->dev, "no assigned %s clock\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) clk_id % 2 ? "extal" : "fsys");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return PTR_ERR(clksrc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) clk_rate = clk_get_rate(clksrc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) ratio = clk_rate / freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (ratio * freq > clk_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) ret = ratio * freq - clk_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) else if (ratio * freq < clk_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ret = clk_rate - ratio * freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /* Block if clock source can not be divided into the required rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (ret != 0 && clk_rate / ret < 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) dev_err(dai->dev, "failed to derive required HCK%c rate\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) tx ? 'T' : 'R');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /* Only EXTAL source can be output directly without using PSR and PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (ratio == 1 && clksrc == esai_priv->extalclk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* Bypass all the dividers if not being needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) } else if (ratio < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /* The ratio should be no less than 2 if using other sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) dev_err(dai->dev, "failed to derive required HCK%c rate\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) tx ? 'T' : 'R');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) ret = fsl_esai_divisor_cal(dai, tx, ratio, false, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) esai_priv->sck_div[tx] = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) esai_priv->hck_dir[tx] = dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) esai_priv->hck_rate[tx] = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) tx ? ESAI_ECR_ETI | ESAI_ECR_ETO :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) ESAI_ECR_ERI | ESAI_ECR_ERO, ecr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * fsl_esai_set_bclk - configure the related dividers according to the bclk rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * @dai: pointer to DAI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * @tx: direction boolean
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * @freq: bclk freq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) u32 hck_rate = esai_priv->hck_rate[tx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) u32 sub, ratio = hck_rate / freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /* Don't apply for fully slave mode or unchanged bclk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (esai_priv->slave_mode || esai_priv->sck_rate[tx] == freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (ratio * freq > hck_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) sub = ratio * freq - hck_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) else if (ratio * freq < hck_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) sub = hck_rate - ratio * freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) sub = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /* Block if clock source can not be divided into the required rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (sub != 0 && hck_rate / sub < 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) dev_err(dai->dev, "failed to derive required SCK%c rate\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) tx ? 'T' : 'R');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /* The ratio should be contented by FP alone if bypassing PM and PSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!esai_priv->sck_div[tx] && (ratio > 16 || ratio == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) dev_err(dai->dev, "the ratio is out of range (1 ~ 16)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ret = fsl_esai_divisor_cal(dai, tx, ratio, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) esai_priv->sck_div[tx] ? 0 : ratio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /* Save current bclk rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) esai_priv->sck_rate[tx] = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) u32 rx_mask, int slots, int slot_width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) esai_priv->slot_width = slot_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) esai_priv->slots = slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) esai_priv->tx_mask = tx_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) esai_priv->rx_mask = rx_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) u32 xcr = 0, xccr = 0, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) /* DAI mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) case SND_SOC_DAIFMT_I2S:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /* Data on rising edge of bclk, frame low, 1clk before data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) xcr |= ESAI_xCR_xFSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) xccr |= ESAI_xCCR_xFSP | ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) case SND_SOC_DAIFMT_LEFT_J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* Data on rising edge of bclk, frame high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) case SND_SOC_DAIFMT_RIGHT_J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* Data on rising edge of bclk, frame high, right aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) xcr |= ESAI_xCR_xWA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) case SND_SOC_DAIFMT_DSP_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /* Data on rising edge of bclk, frame high, 1clk before data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) xcr |= ESAI_xCR_xFSL | ESAI_xCR_xFSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) case SND_SOC_DAIFMT_DSP_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* Data on rising edge of bclk, frame high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) xcr |= ESAI_xCR_xFSL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /* DAI clock inversion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) case SND_SOC_DAIFMT_NB_NF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /* Nothing to do for both normal cases */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) case SND_SOC_DAIFMT_IB_NF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /* Invert bit clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) case SND_SOC_DAIFMT_NB_IF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /* Invert frame clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) xccr ^= ESAI_xCCR_xFSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) case SND_SOC_DAIFMT_IB_IF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /* Invert both clocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) esai_priv->slave_mode = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /* DAI clock master masks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) case SND_SOC_DAIFMT_CBM_CFM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) esai_priv->slave_mode = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) case SND_SOC_DAIFMT_CBS_CFM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) xccr |= ESAI_xCCR_xCKD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) case SND_SOC_DAIFMT_CBM_CFS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) xccr |= ESAI_xCCR_xFSD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) case SND_SOC_DAIFMT_CBS_CFS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) xccr |= ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) mask = ESAI_xCR_xFSL | ESAI_xCR_xFSR | ESAI_xCR_xWA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, mask, xcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, mask, xcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) mask = ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, mask, xccr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, mask, xccr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static int fsl_esai_startup(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (!snd_soc_dai_active(dai)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* Set synchronous mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) regmap_update_bits(esai_priv->regmap, REG_ESAI_SAICR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) ESAI_SAICR_SYNC, esai_priv->synchronous ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) ESAI_SAICR_SYNC : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) /* Set slots count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) ESAI_xCCR_xDC_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) ESAI_xCCR_xDC(esai_priv->slots));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) ESAI_xCCR_xDC_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ESAI_xCCR_xDC(esai_priv->slots));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) u32 width = params_width(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) u32 channels = params_channels(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) u32 pins = DIV_ROUND_UP(channels, esai_priv->slots);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) u32 slot_width = width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) u32 bclk, mask, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /* Override slot_width if being specifically set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (esai_priv->slot_width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) slot_width = esai_priv->slot_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) bclk = params_rate(params) * slot_width * esai_priv->slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) ret = fsl_esai_set_bclk(dai, esai_priv->synchronous || tx, bclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) mask = ESAI_xCR_xSWS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) val = ESAI_xCR_xSWS(slot_width, width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) /* Recording in synchronous mode needs to set TCR also */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (!tx && esai_priv->synchronous)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, mask, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /* Use Normal mode to support monaural audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) ESAI_xCR_xMOD_MASK, params_channels(params) > 1 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) ESAI_xCR_xMOD_NETWORK : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) ESAI_xFCR_xFR_MASK, ESAI_xFCR_xFR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) mask = ESAI_xFCR_xFR_MASK | ESAI_xFCR_xWA_MASK | ESAI_xFCR_xFWM_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) (tx ? ESAI_xFCR_TE_MASK | ESAI_xFCR_TIEN : ESAI_xFCR_RE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) val = ESAI_xFCR_xWA(width) | ESAI_xFCR_xFWM(esai_priv->fifo_depth) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) (tx ? ESAI_xFCR_TE(pins) | ESAI_xFCR_TIEN : ESAI_xFCR_RE(pins));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) ESAI_xCR_PADC, ESAI_xCR_PADC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /* Remove ESAI personal reset by configuring ESAI_PCRC and ESAI_PRRC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) static int fsl_esai_hw_init(struct fsl_esai *esai_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct platform_device *pdev = esai_priv->pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) /* Reset ESAI unit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) ret = regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) ESAI_ECR_ESAIEN | ESAI_ECR_ERST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * We need to enable ESAI so as to access some of its registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * Otherwise, we would fail to dump regmap from user space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) ret = regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) ESAI_ECR_ESAIEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) ESAI_PRRC_PDC_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) ESAI_PCRC_PC_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) static int fsl_esai_register_restore(struct fsl_esai *esai_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /* FIFO reset for safety */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) ESAI_xFCR_xFR, ESAI_xFCR_xFR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) ESAI_xFCR_xFR, ESAI_xFCR_xFR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) regcache_mark_dirty(esai_priv->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) ret = regcache_sync(esai_priv->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) /* FIFO reset done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) static void fsl_esai_trigger_start(struct fsl_esai *esai_priv, bool tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) u8 i, channels = esai_priv->channels[tx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) u32 pins = DIV_ROUND_UP(channels, esai_priv->slots);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) /* Write initial words reqiured by ESAI as normal procedure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) for (i = 0; tx && i < channels; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * When set the TE/RE in the end of enablement flow, there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * will be channel swap issue for multi data line case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * In order to workaround this issue, we switch the bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * enablement sequence to below sequence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * 1) clear the xSMB & xSMA: which is done in probe and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * stop state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * 2) set TE/RE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * 3) set xSMB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * 4) set xSMA: xSMA is the last one in this flow, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * will trigger esai to start.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) /* Enable Exception interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) ESAI_xCR_xEIE_MASK, ESAI_xCR_xEIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) static void fsl_esai_trigger_stop(struct fsl_esai *esai_priv, bool tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) ESAI_xCR_xEIE_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) ESAI_xSMA_xS_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) ESAI_xSMB_xS_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) /* Disable and reset FIFO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) ESAI_xFCR_xFR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) static void fsl_esai_hw_reset(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct fsl_esai *esai_priv = container_of(work, struct fsl_esai, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) bool tx = true, rx = false, enabled[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) unsigned long lock_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) u32 tfcr, rfcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) spin_lock_irqsave(&esai_priv->lock, lock_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) /* Save the registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) regmap_read(esai_priv->regmap, REG_ESAI_TFCR, &tfcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) regmap_read(esai_priv->regmap, REG_ESAI_RFCR, &rfcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) enabled[tx] = tfcr & ESAI_xFCR_xFEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) enabled[rx] = rfcr & ESAI_xFCR_xFEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) /* Stop the tx & rx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) fsl_esai_trigger_stop(esai_priv, tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) fsl_esai_trigger_stop(esai_priv, rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /* Reset the esai, and ignore return value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) fsl_esai_hw_init(esai_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) /* Enforce ESAI personal resets for both TX and RX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) ESAI_xCR_xPR_MASK, ESAI_xCR_xPR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) ESAI_xCR_xPR_MASK, ESAI_xCR_xPR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) /* Restore registers by regcache_sync, and ignore return value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) fsl_esai_register_restore(esai_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) /* Remove ESAI personal resets by configuring PCRC and PRRC also */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) ESAI_xCR_xPR_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) ESAI_xCR_xPR_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /* Restart tx / rx, if they already enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (enabled[tx])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) fsl_esai_trigger_start(esai_priv, tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (enabled[rx])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) fsl_esai_trigger_start(esai_priv, rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) spin_unlock_irqrestore(&esai_priv->lock, lock_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) unsigned long lock_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) esai_priv->channels[tx] = substream->runtime->channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) spin_lock_irqsave(&esai_priv->lock, lock_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) fsl_esai_trigger_start(esai_priv, tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) spin_unlock_irqrestore(&esai_priv->lock, lock_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) spin_lock_irqsave(&esai_priv->lock, lock_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) fsl_esai_trigger_stop(esai_priv, tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) spin_unlock_irqrestore(&esai_priv->lock, lock_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) static const struct snd_soc_dai_ops fsl_esai_dai_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) .startup = fsl_esai_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) .trigger = fsl_esai_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) .hw_params = fsl_esai_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) .set_sysclk = fsl_esai_set_dai_sysclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) .set_fmt = fsl_esai_set_dai_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .set_tdm_slot = fsl_esai_set_dai_tdm_slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) static int fsl_esai_dai_probe(struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) snd_soc_dai_init_dma_data(dai, &esai_priv->dma_params_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) &esai_priv->dma_params_rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) static struct snd_soc_dai_driver fsl_esai_dai = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) .probe = fsl_esai_dai_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) .playback = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) .stream_name = "CPU-Playback",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) .channels_max = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) .rates = SNDRV_PCM_RATE_8000_192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) .formats = FSL_ESAI_FORMATS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) .capture = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) .stream_name = "CPU-Capture",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) .channels_max = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) .rates = SNDRV_PCM_RATE_8000_192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) .formats = FSL_ESAI_FORMATS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) .ops = &fsl_esai_dai_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) static const struct snd_soc_component_driver fsl_esai_component = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) .name = "fsl-esai",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) static const struct reg_default fsl_esai_reg_defaults[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {REG_ESAI_ETDR, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) {REG_ESAI_ECR, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {REG_ESAI_TFCR, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) {REG_ESAI_RFCR, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) {REG_ESAI_TX0, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) {REG_ESAI_TX1, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) {REG_ESAI_TX2, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) {REG_ESAI_TX3, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) {REG_ESAI_TX4, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) {REG_ESAI_TX5, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) {REG_ESAI_TSR, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) {REG_ESAI_SAICR, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) {REG_ESAI_TCR, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) {REG_ESAI_TCCR, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {REG_ESAI_RCR, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) {REG_ESAI_RCCR, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) {REG_ESAI_TSMA, 0x0000ffff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) {REG_ESAI_TSMB, 0x0000ffff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) {REG_ESAI_RSMA, 0x0000ffff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) {REG_ESAI_RSMB, 0x0000ffff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) {REG_ESAI_PRRC, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) {REG_ESAI_PCRC, 0x00000000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) static bool fsl_esai_readable_reg(struct device *dev, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) case REG_ESAI_ERDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) case REG_ESAI_ECR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) case REG_ESAI_ESR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) case REG_ESAI_TFCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) case REG_ESAI_TFSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) case REG_ESAI_RFCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) case REG_ESAI_RFSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) case REG_ESAI_RX0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) case REG_ESAI_RX1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) case REG_ESAI_RX2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) case REG_ESAI_RX3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) case REG_ESAI_SAISR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) case REG_ESAI_SAICR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) case REG_ESAI_TCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) case REG_ESAI_TCCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) case REG_ESAI_RCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) case REG_ESAI_RCCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) case REG_ESAI_TSMA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) case REG_ESAI_TSMB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) case REG_ESAI_RSMA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) case REG_ESAI_RSMB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) case REG_ESAI_PRRC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) case REG_ESAI_PCRC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) static bool fsl_esai_volatile_reg(struct device *dev, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) case REG_ESAI_ERDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) case REG_ESAI_ESR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) case REG_ESAI_TFSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) case REG_ESAI_RFSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) case REG_ESAI_RX0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) case REG_ESAI_RX1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) case REG_ESAI_RX2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) case REG_ESAI_RX3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) case REG_ESAI_SAISR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static bool fsl_esai_writeable_reg(struct device *dev, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) case REG_ESAI_ETDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) case REG_ESAI_ECR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) case REG_ESAI_TFCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) case REG_ESAI_RFCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) case REG_ESAI_TX0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) case REG_ESAI_TX1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) case REG_ESAI_TX2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) case REG_ESAI_TX3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) case REG_ESAI_TX4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) case REG_ESAI_TX5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) case REG_ESAI_TSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) case REG_ESAI_SAICR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) case REG_ESAI_TCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) case REG_ESAI_TCCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) case REG_ESAI_RCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) case REG_ESAI_RCCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) case REG_ESAI_TSMA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) case REG_ESAI_TSMB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) case REG_ESAI_RSMA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) case REG_ESAI_RSMB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) case REG_ESAI_PRRC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) case REG_ESAI_PCRC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static const struct regmap_config fsl_esai_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) .reg_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) .reg_stride = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) .val_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) .max_register = REG_ESAI_PCRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) .reg_defaults = fsl_esai_reg_defaults,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) .num_reg_defaults = ARRAY_SIZE(fsl_esai_reg_defaults),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) .readable_reg = fsl_esai_readable_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) .volatile_reg = fsl_esai_volatile_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) .writeable_reg = fsl_esai_writeable_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) .cache_type = REGCACHE_FLAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) static int fsl_esai_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) struct fsl_esai *esai_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) const __be32 *iprop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) int irq, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) esai_priv = devm_kzalloc(&pdev->dev, sizeof(*esai_priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (!esai_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) esai_priv->pdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) snprintf(esai_priv->name, sizeof(esai_priv->name), "%pOFn", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) esai_priv->soc = of_device_get_match_data(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if (!esai_priv->soc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) dev_err(&pdev->dev, "failed to get soc data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) /* Get the addresses and IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) regs = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (IS_ERR(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return PTR_ERR(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) esai_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) "core", regs, &fsl_esai_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (IS_ERR(esai_priv->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) dev_err(&pdev->dev, "failed to init regmap: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) PTR_ERR(esai_priv->regmap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) return PTR_ERR(esai_priv->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) esai_priv->coreclk = devm_clk_get(&pdev->dev, "core");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) if (IS_ERR(esai_priv->coreclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) dev_err(&pdev->dev, "failed to get core clock: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) PTR_ERR(esai_priv->coreclk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return PTR_ERR(esai_priv->coreclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) esai_priv->extalclk = devm_clk_get(&pdev->dev, "extal");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (IS_ERR(esai_priv->extalclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) dev_warn(&pdev->dev, "failed to get extal clock: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) PTR_ERR(esai_priv->extalclk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) esai_priv->fsysclk = devm_clk_get(&pdev->dev, "fsys");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (IS_ERR(esai_priv->fsysclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) dev_warn(&pdev->dev, "failed to get fsys clock: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) PTR_ERR(esai_priv->fsysclk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) esai_priv->spbaclk = devm_clk_get(&pdev->dev, "spba");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (IS_ERR(esai_priv->spbaclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) dev_warn(&pdev->dev, "failed to get spba clock: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) PTR_ERR(esai_priv->spbaclk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) ret = devm_request_irq(&pdev->dev, irq, esai_isr, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) esai_priv->name, esai_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) /* Set a default slot number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) esai_priv->slots = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) /* Set a default master/slave state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) esai_priv->slave_mode = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) /* Determine the FIFO depth */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) iprop = of_get_property(np, "fsl,fifo-depth", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (iprop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) esai_priv->fifo_depth = be32_to_cpup(iprop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) esai_priv->fifo_depth = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) esai_priv->dma_params_tx.maxburst = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) esai_priv->dma_params_rx.maxburst = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) esai_priv->dma_params_tx.addr = res->start + REG_ESAI_ETDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) esai_priv->dma_params_rx.addr = res->start + REG_ESAI_ERDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) esai_priv->synchronous =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) of_property_read_bool(np, "fsl,esai-synchronous");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) /* Implement full symmetry for synchronous mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if (esai_priv->synchronous) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) fsl_esai_dai.symmetric_rates = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) fsl_esai_dai.symmetric_channels = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) fsl_esai_dai.symmetric_samplebits = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) dev_set_drvdata(&pdev->dev, esai_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) spin_lock_init(&esai_priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) ret = fsl_esai_hw_init(esai_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) esai_priv->tx_mask = 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) esai_priv->rx_mask = 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) /* Clear the TSMA, TSMB, RSMA, RSMB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) regmap_write(esai_priv->regmap, REG_ESAI_TSMA, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) regmap_write(esai_priv->regmap, REG_ESAI_TSMB, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) regmap_write(esai_priv->regmap, REG_ESAI_RSMA, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) regmap_write(esai_priv->regmap, REG_ESAI_RSMB, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) &fsl_esai_dai, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) INIT_WORK(&esai_priv->work, fsl_esai_hw_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) pm_runtime_enable(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) regcache_cache_only(esai_priv->regmap, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) ret = imx_pcm_dma_init(pdev, IMX_ESAI_DMABUF_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) static int fsl_esai_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) struct fsl_esai *esai_priv = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) pm_runtime_disable(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) cancel_work_sync(&esai_priv->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) static const struct of_device_id fsl_esai_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) { .compatible = "fsl,imx35-esai", .data = &fsl_esai_imx35 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) { .compatible = "fsl,vf610-esai", .data = &fsl_esai_vf610 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) { .compatible = "fsl,imx6ull-esai", .data = &fsl_esai_imx6ull },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) static int fsl_esai_runtime_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) struct fsl_esai *esai = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) * Some platforms might use the same bit to gate all three or two of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) * clocks, so keep all clocks open/close at the same time for safety
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) ret = clk_prepare_enable(esai->coreclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (!IS_ERR(esai->spbaclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) ret = clk_prepare_enable(esai->spbaclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) goto err_spbaclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (!IS_ERR(esai->extalclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) ret = clk_prepare_enable(esai->extalclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) goto err_extalclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (!IS_ERR(esai->fsysclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) ret = clk_prepare_enable(esai->fsysclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) goto err_fsysclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) regcache_cache_only(esai->regmap, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) ret = fsl_esai_register_restore(esai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) goto err_regcache_sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) err_regcache_sync:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (!IS_ERR(esai->fsysclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) clk_disable_unprepare(esai->fsysclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) err_fsysclk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (!IS_ERR(esai->extalclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) clk_disable_unprepare(esai->extalclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) err_extalclk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) if (!IS_ERR(esai->spbaclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) clk_disable_unprepare(esai->spbaclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) err_spbaclk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) clk_disable_unprepare(esai->coreclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) static int fsl_esai_runtime_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) struct fsl_esai *esai = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) regcache_cache_only(esai->regmap, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (!IS_ERR(esai->fsysclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) clk_disable_unprepare(esai->fsysclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (!IS_ERR(esai->extalclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) clk_disable_unprepare(esai->extalclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) if (!IS_ERR(esai->spbaclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) clk_disable_unprepare(esai->spbaclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) clk_disable_unprepare(esai->coreclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) #endif /* CONFIG_PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) static const struct dev_pm_ops fsl_esai_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) SET_RUNTIME_PM_OPS(fsl_esai_runtime_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) fsl_esai_runtime_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) pm_runtime_force_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) static struct platform_driver fsl_esai_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) .probe = fsl_esai_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) .remove = fsl_esai_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) .name = "fsl-esai-dai",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) .pm = &fsl_esai_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) .of_match_table = fsl_esai_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) module_platform_driver(fsl_esai_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) MODULE_AUTHOR("Freescale Semiconductor, Inc.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) MODULE_DESCRIPTION("Freescale ESAI CPU DAI driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) MODULE_ALIAS("platform:fsl-esai-dai");