aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorShengjiu Wang <b02247@freescale.com>2014-04-27 22:40:10 -0400
committerShengjiu Wang <b02247@freescale.com>2014-04-29 00:43:02 -0400
commit22d1bec44929e5fb6fa8316c4687d493c7d264b4 (patch)
tree93c47078d636f776b5ef78063fe76f5941b5dcba /sound/soc/fsl
parent0673acf93a40e5b26b667b627dc62b81b377cc70 (diff)
ENGR00310878-2 ASoC: fsl_esai: cherry-pick from upstream and merge to mainline
cherry-picked commit is 43d24e76b69826ce32292f47060ad78cdd0197fa Header of this commit is "ASoC: fsl_esai: Add ESAI CPU DAI driver", use upstream driver to replace current one. Merged feature is: 1. Move setting of PRRC and PCRC to the end of hw_params, and disable it in shutdown function. 2. Merged the xrun handler with this commit. 3. Use dma init with NO_RESIDUE|NO_DT|COMPAT. 4. Add spba clock for ESAI Signed-off-by: Shengjiu Wang <b02247@freescale.com>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/fsl_esai.c1278
-rw-r--r--sound/soc/fsl/fsl_esai.h667
-rw-r--r--sound/soc/fsl/imx-cs42888.c75
3 files changed, 1028 insertions, 992 deletions
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index 0f9282cc5acf..5a230707da16 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -1,226 +1,381 @@
1/* 1/*
2 * Copyright 2008-2014 Freescale Semiconductor, Inc. All Rights Reserved. 2 * Freescale ESAI ALSA SoC Digital Audio Interface (DAI) driver
3 */
4
5/*
6 * The code contained herein is licensed under the GNU General Public
7 * License. You may obtain a copy of the GNU General Public License
8 * Version 2 or later at the following locations:
9 * 3 *
10 * http://www.opensource.org/licenses/gpl-license.html 4 * Copyright (C) 2014 Freescale Semiconductor, Inc.
11 * http://www.gnu.org/copyleft/gpl.html 5 *
6 * This file is licensed under the terms of the GNU General Public License
7 * version 2. This program is licensed "as is" without any warranty of any
8 * kind, whether express or implied.
12 */ 9 */
13 10
14 /*! 11#include <linux/clk.h>
15 * @file fsl-esai.c 12#include <linux/dmaengine.h>
16 * @brief this file implements the esai interface
17 * in according to ASoC architeture
18 */
19
20#include <linux/module.h> 13#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/of_address.h>
23#include <linux/of_irq.h> 14#include <linux/of_irq.h>
24#include <linux/of_platform.h> 15#include <linux/of_platform.h>
25#include <linux/clk.h> 16#include <sound/dmaengine_pcm.h>
26
27#include <sound/core.h>
28#include <sound/pcm.h>
29#include <sound/pcm_params.h> 17#include <sound/pcm_params.h>
30#include <sound/soc.h>
31 18
32#include "fsl_esai.h" 19#include "fsl_esai.h"
33#include "imx-pcm.h" 20#include "imx-pcm.h"
34 21
35#define IMX_ESAI_NET (1 << 0) 22#define FSL_ESAI_RATES SNDRV_PCM_RATE_8000_192000
36#define IMX_ESAI_SYN (1 << 1) 23#define FSL_ESAI_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
24 SNDRV_PCM_FMTBIT_S16_LE | \
25 SNDRV_PCM_FMTBIT_S20_3LE | \
26 SNDRV_PCM_FMTBIT_S24_LE)
27#define REG_CACHE_NUM 20
28
29/**
30 * fsl_esai: ESAI private data
31 *
32 * @dma_params_rx: DMA parameters for receive channel
33 * @dma_params_tx: DMA parameters for transmit channel
34 * @pdev: platform device pointer
35 * @regmap: regmap handler
36 * @coreclk: clock source to access register
37 * @extalclk: esai clock source to derive HCK, SCK and FS
38 * @fsysclk: system clock source to derive HCK, SCK and FS
39 * @fifo_depth: depth of tx/rx FIFO
40 * @slot_width: width of each DAI slot
41 * @hck_rate: clock rate of desired HCKx clock
42 * @sck_div: if using PSR/PM dividers for SCKx clock
43 * @slave_mode: if fully using DAI slave mode
44 * @synchronous: if using tx/rx synchronous mode
45 * @name: driver name
46 */
47struct fsl_esai {
48 struct snd_dmaengine_dai_dma_data dma_params_rx;
49 struct snd_dmaengine_dai_dma_data dma_params_tx;
50 struct imx_dma_data filter_data_tx;
51 struct imx_dma_data filter_data_rx;
52 struct snd_pcm_substream *substream[2];
53 struct platform_device *pdev;
54 struct regmap *regmap;
55 struct clk *coreclk;
56 struct clk *extalclk;
57 struct clk *fsysclk;
58 struct clk *dmaclk;
59 u32 fifo_depth;
60 u32 slot_width;
61 u32 hck_rate[2];
62 bool sck_div[2];
63 bool slave_mode;
64 bool synchronous;
65 char name[32];
66 u32 reg_cache[REG_CACHE_NUM];
67};
37 68
38static inline void write_esai_mask(u32 __iomem *addr, u32 clear, u32 set) 69static irqreturn_t esai_isr(int irq, void *devid)
39{ 70{
40 u32 val = readl(addr); 71 struct fsl_esai *esai_priv = (struct fsl_esai *)devid;
41 val = (val & ~clear) | set; 72 struct platform_device *pdev = esai_priv->pdev;
42 writel(val, addr); 73 u32 esr;
74
75 regmap_read(esai_priv->regmap, REG_ESAI_ESR, &esr);
76
77 if (esr & ESAI_ESR_TINIT_MASK)
78 dev_dbg(&pdev->dev, "isr: Transmition Initialized\n");
79
80 if (esr & ESAI_ESR_RFF_MASK)
81 dev_warn(&pdev->dev, "isr: Receiving overrun\n");
82
83 if (esr & ESAI_ESR_TFE_MASK)
84 dev_warn(&pdev->dev, "isr: Transmition underrun\n");
85
86 if (esr & ESAI_ESR_TLS_MASK)
87 dev_dbg(&pdev->dev, "isr: Just transmitted the last slot\n");
88
89 if (esr & ESAI_ESR_TDE_MASK)
90 dev_dbg(&pdev->dev, "isr: Transmition data exception\n");
91
92 if (esr & ESAI_ESR_TED_MASK)
93 dev_dbg(&pdev->dev, "isr: Transmitting even slots\n");
94
95 if (esr & ESAI_ESR_TD_MASK)
96 dev_dbg(&pdev->dev, "isr: Transmitting data\n");
97
98 if (esr & ESAI_ESR_RLS_MASK)
99 dev_dbg(&pdev->dev, "isr: Just received the last slot\n");
100
101 if (esr & ESAI_ESR_RDE_MASK)
102 dev_dbg(&pdev->dev, "isr: Receiving data exception\n");
103
104 if (esr & ESAI_ESR_RED_MASK)
105 dev_dbg(&pdev->dev, "isr: Receiving even slots\n");
106
107 if (esr & ESAI_ESR_RD_MASK)
108 dev_dbg(&pdev->dev, "isr: Receiving data\n");
109
110 return IRQ_HANDLED;
43} 111}
44 112
45static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, 113/**
46 int clk_id, unsigned int freq, int dir) 114 * This function is used to calculate the divisors of psr, pm, fp and it is
115 * supposed to be called in set_dai_sysclk() and set_bclk().
116 *
117 * @ratio: desired overall ratio for the paticipating dividers
118 * @usefp: for HCK setting, there is no need to set fp divider
119 * @fp: bypass other dividers by setting fp directly if fp != 0
120 * @tx: current setting is for playback or capture
121 */
122static int fsl_esai_divisor_cal(struct snd_soc_dai *dai, bool tx, u32 ratio,
123 bool usefp, u32 fp)
47{ 124{
48 struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai); 125 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
49 u32 ecr, tccr, rccr; 126 u32 psr, pm = 999, maxfp, prod, sub, savesub, i, j;
50 127
51 clk_enable(esai->clk); 128 maxfp = usefp ? 16 : 1;
52 ecr = readl(esai->base + ESAI_ECR); 129
53 tccr = readl(esai->base + ESAI_TCCR); 130 if (usefp && fp)
54 rccr = readl(esai->base + ESAI_RCCR); 131 goto out_fp;
55 132
56 if (dir == SND_SOC_CLOCK_IN) { 133 if (ratio > 2 * 8 * 256 * maxfp || ratio < 2) {
57 tccr &= ~(ESAI_TCCR_THCKD | ESAI_TCCR_TCKD | ESAI_TCCR_TFSD); 134 dev_err(dai->dev, "the ratio is out of range (2 ~ %d)\n",
58 rccr &= ~(ESAI_RCCR_RHCKD | ESAI_RCCR_RCKD | ESAI_RCCR_RFSD); 135 2 * 8 * 256 * maxfp);
59 } else { 136 return -EINVAL;
60 tccr |= ESAI_TCCR_THCKD | ESAI_TCCR_TCKD | ESAI_TCCR_TFSD; 137 } else if (ratio % 2) {
61 rccr |= ESAI_RCCR_RHCKD | ESAI_RCCR_RCKD | ESAI_RCCR_RFSD; 138 dev_err(dai->dev, "the raio must be even if using upper divider\n");
62 139 return -EINVAL;
63 if (clk_id == ESAI_CLK_FSYS) { 140 }
64 ecr &= ~(ESAI_ECR_ETI | ESAI_ECR_ETO); 141
65 ecr &= ~(ESAI_ECR_ERI | ESAI_ECR_ERO); 142 ratio /= 2;
66 } else if (clk_id == ESAI_CLK_EXTAL) { 143
67 ecr |= ESAI_ECR_ETI; 144 psr = ratio <= 256 * maxfp ? ESAI_xCCR_xPSR_BYPASS : ESAI_xCCR_xPSR_DIV8;
68 ecr |= ESAI_ECR_ETO; 145
69 ecr |= ESAI_ECR_ERI; 146 /* Set the max fluctuation -- 0.1% of the max devisor */
70 ecr |= ESAI_ECR_ERO; 147 savesub = (psr ? 1 : 8) * 256 * maxfp / 1000;
71 } else if (clk_id == ESAI_CLK_EXTAL_DIV) { 148
72 ecr |= ESAI_ECR_ETI; 149 /* Find the best value for PM */
73 ecr &= ~ESAI_ECR_ETO; 150 for (i = 1; i <= 256; i++) {
74 ecr |= ESAI_ECR_ERI; 151 for (j = 1; j <= maxfp; j++) {
75 ecr &= ~ESAI_ECR_ERO; 152 /* PSR (1 or 8) * PM (1 ~ 256) * FP (1 ~ 16) */
153 prod = (psr ? 1 : 8) * i * j;
154
155 if (prod == ratio)
156 sub = 0;
157 else if (prod / ratio == 1)
158 sub = prod - ratio;
159 else if (ratio / prod == 1)
160 sub = ratio - prod;
161 else
162 continue;
163
164 /* Calculate the fraction */
165 sub = sub * 1000 / ratio;
166 if (sub < savesub) {
167 savesub = sub;
168 pm = i;
169 fp = j;
170 }
171
172 /* We are lucky */
173 if (savesub == 0)
174 goto out;
76 } 175 }
77 } 176 }
78 177
79 writel(ecr, esai->base + ESAI_ECR); 178 if (pm == 999) {
80 writel(tccr, esai->base + ESAI_TCCR); 179 dev_err(dai->dev, "failed to calculate proper divisors\n");
81 writel(rccr, esai->base + ESAI_RCCR); 180 return -EINVAL;
181 }
182
183out:
184 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
185 ESAI_xCCR_xPSR_MASK | ESAI_xCCR_xPM_MASK,
186 psr | ESAI_xCCR_xPM(pm));
187
188out_fp:
189 /* Bypass fp if not being required */
190 if (maxfp <= 1)
191 return 0;
82 192
83 ESAI_DUMP(); 193 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
84 clk_disable(esai->clk); 194 ESAI_xCCR_xFP_MASK, ESAI_xCCR_xFP(fp));
85 195
86 return 0; 196 return 0;
87} 197}
88 198
89static int fsl_esai_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, 199/**
90 int div_id, int div) 200 * This function mainly configures the clock frequency of MCLK (HCKT/HCKR)
201 *
202 * @Parameters:
203 * clk_id: The clock source of HCKT/HCKR
204 * (Input from outside; output from inside, FSYS or EXTAL)
205 * freq: The required clock rate of HCKT/HCKR
206 * dir: The clock direction of HCKT/HCKR
207 *
208 * Note: If the direction is input, we do not care about clk_id.
209 */
210static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
211 unsigned int freq, int dir)
91{ 212{
92 struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai); 213 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
93 u32 tccr, rccr; 214 struct clk *clksrc = esai_priv->extalclk;
94 215 bool tx = clk_id <= ESAI_HCKT_EXTAL;
95 clk_enable(esai->clk); 216 bool in = dir == SND_SOC_CLOCK_IN;
96 tccr = readl(esai->base + ESAI_TCCR); 217 u32 ret, ratio, ecr = 0;
97 rccr = readl(esai->base + ESAI_RCCR); 218 unsigned long clk_rate;
98 219
99 switch (div_id) { 220 /* sck_div can be only bypassed if ETO/ERO=0 and SNC_SOC_CLOCK_OUT */
100 case ESAI_TX_DIV_PSR: 221 esai_priv->sck_div[tx] = true;
101 if ((div << ESAI_TCCR_TPSR_SHIFT) & ESAI_TCCR_TPSR_MASK) 222
102 return -EINVAL; 223 /* Set the direction of HCKT/HCKR pins */
103 tccr &= ESAI_TCCR_TPSR_MASK; 224 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
104 if (div) 225 ESAI_xCCR_xHCKD, in ? 0 : ESAI_xCCR_xHCKD);
105 tccr |= ESAI_TCCR_TPSR_BYPASS; 226
106 else 227 if (in)
107 tccr &= ~ESAI_TCCR_TPSR_DIV8; 228 goto out;
108 break; 229
109 case ESAI_TX_DIV_PM: 230 switch (clk_id) {
110 if ((div << ESAI_TCCR_TPM_SHIFT) & ESAI_TCCR_TPM_MASK) 231 case ESAI_HCKT_FSYS:
111 return -EINVAL; 232 case ESAI_HCKR_FSYS:
112 tccr &= ESAI_TCCR_TPM_MASK; 233 clksrc = esai_priv->fsysclk;
113 tccr |= ESAI_TCCR_TPM(div);
114 break; 234 break;
115 case ESAI_TX_DIV_FP: 235 case ESAI_HCKT_EXTAL:
116 if ((div << ESAI_TCCR_TFP_SHIFT) & ESAI_TCCR_TFP_MASK) 236 ecr |= ESAI_ECR_ETI;
117 return -EINVAL; 237 case ESAI_HCKR_EXTAL:
118 tccr &= ESAI_TCCR_TFP_MASK; 238 ecr |= ESAI_ECR_ERI;
119 tccr |= ESAI_TCCR_TFP(div);
120 break;
121 case ESAI_RX_DIV_PSR:
122 if ((div << ESAI_RCCR_RPSR_SHIFT) & ESAI_RCCR_RPSR_MASK)
123 return -EINVAL;
124 rccr &= ESAI_RCCR_RPSR_MASK;
125 if (div)
126 rccr |= ESAI_RCCR_RPSR_BYPASS;
127 else
128 rccr &= ~ESAI_RCCR_RPSR_DIV8;
129 break;
130 case ESAI_RX_DIV_PM:
131 if ((div << ESAI_RCCR_RPM_SHIFT) & ESAI_RCCR_RPM_MASK)
132 return -EINVAL;
133 rccr &= ESAI_RCCR_RPM_MASK;
134 rccr |= ESAI_RCCR_RPM(div);
135 break;
136 case ESAI_RX_DIV_FP:
137 if ((div << ESAI_RCCR_RFP_SHIFT) & ESAI_RCCR_RFP_MASK)
138 return -EINVAL;
139 rccr &= ESAI_RCCR_RFP_MASK;
140 rccr |= ESAI_RCCR_RFP(div);
141 break; 239 break;
142 default: 240 default:
143 return -EINVAL; 241 return -EINVAL;
144 } 242 }
145 writel(tccr, esai->base + ESAI_TCCR); 243
146 writel(rccr, esai->base + ESAI_RCCR); 244 if (IS_ERR(clksrc)) {
147 clk_disable(esai->clk); 245 dev_err(dai->dev, "no assigned %s clock\n",
246 clk_id % 2 ? "extal" : "fsys");
247 return PTR_ERR(clksrc);
248 }
249 clk_rate = clk_get_rate(clksrc);
250
251 ratio = clk_rate / freq;
252 if (ratio * freq > clk_rate)
253 ret = ratio * freq - clk_rate;
254 else if (ratio * freq < clk_rate)
255 ret = clk_rate - ratio * freq;
256 else
257 ret = 0;
258
259 /* Block if clock source can not be divided into the required rate */
260 if (ret != 0 && clk_rate / ret < 1000) {
261 dev_err(dai->dev, "failed to derive required HCK%c rate\n",
262 tx ? 'T' : 'R');
263 return -EINVAL;
264 }
265
266 if (ratio == 1) {
267 /* Bypass all the dividers if not being needed */
268 ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO;
269 goto out;
270 }
271
272 ret = fsl_esai_divisor_cal(dai, tx, ratio, false, 0);
273 if (ret)
274 return ret;
275
276 esai_priv->sck_div[tx] = false;
277
278out:
279 esai_priv->hck_rate[tx] = freq;
280
281 regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
282 tx ? ESAI_ECR_ETI | ESAI_ECR_ETO :
283 ESAI_ECR_ERI | ESAI_ECR_ERO, ecr);
148 284
149 return 0; 285 return 0;
150} 286}
151 287
152/* 288/**
153 * ESAI Network Mode or TDM slots configuration. 289 * This function configures the related dividers according to the bclk rate
154 */ 290 */
155static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, 291static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
156 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
157{ 292{
158 struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai); 293 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
159 u32 tccr, rccr; 294 u32 hck_rate = esai_priv->hck_rate[tx];
295 u32 sub, ratio = hck_rate / freq;
296
297 /* Don't apply for fully slave mode*/
298 if (esai_priv->slave_mode)
299 return 0;
300
301 if (ratio * freq > hck_rate)
302 sub = ratio * freq - hck_rate;
303 else if (ratio * freq < hck_rate)
304 sub = hck_rate - ratio * freq;
305 else
306 sub = 0;
307
308 /* Block if clock source can not be divided into the required rate */
309 if (sub != 0 && hck_rate / sub < 1000) {
310 dev_err(dai->dev, "failed to derive required SCK%c rate\n",
311 tx ? 'T' : 'R');
312 return -EINVAL;
313 }
314
315 if (esai_priv->sck_div[tx] && (ratio > 16 || ratio == 0)) {
316 dev_err(dai->dev, "the ratio is out of range (1 ~ 16)\n");
317 return -EINVAL;
318 }
160 319
161 clk_enable(esai->clk); 320 return fsl_esai_divisor_cal(dai, tx, ratio, true,
162 tccr = readl(esai->base + ESAI_TCCR); 321 esai_priv->sck_div[tx] ? 0 : ratio);
322}
163 323
164 tccr &= ESAI_TCCR_TDC_MASK; 324static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
165 tccr |= ESAI_TCCR_TDC(slots - 1); 325 u32 rx_mask, int slots, int slot_width)
326{
327 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
166 328
167 writel(tccr, esai->base + ESAI_TCCR); 329 regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
168 writel((tx_mask & 0xffff), esai->base + ESAI_TSMA); 330 ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
169 writel(((tx_mask >> 16) & 0xffff), esai->base + ESAI_TSMB);
170 331
171 rccr = readl(esai->base + ESAI_RCCR); 332 regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA,
333 ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask));
334 regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB,
335 ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(tx_mask));
172 336
173 rccr &= ESAI_RCCR_RDC_MASK; 337 regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
174 rccr |= ESAI_RCCR_RDC(slots - 1); 338 ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
175 339
176 writel(rccr, esai->base + ESAI_RCCR); 340 regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA,
177 writel((rx_mask & 0xffff), esai->base + ESAI_RSMA); 341 ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask));
178 writel(((rx_mask >> 16) & 0xffff), esai->base + ESAI_RSMB); 342 regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB,
343 ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(rx_mask));
179 344
180 ESAI_DUMP(); 345 esai_priv->slot_width = slot_width;
181 clk_disable(esai->clk);
182 346
183 return 0; 347 return 0;
184} 348}
185 349
186/* 350static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
187 * ESAI DAI format configuration.
188 */
189static int fsl_esai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
190{ 351{
191 struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai); 352 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
192 u32 tcr, tccr, rcr, rccr, saicr; 353 u32 xcr = 0, xccr = 0, mask;
193
194 clk_enable(esai->clk);
195 tcr = readl(esai->base + ESAI_TCR);
196 tccr = readl(esai->base + ESAI_TCCR);
197 rcr = readl(esai->base + ESAI_RCR);
198 rccr = readl(esai->base + ESAI_RCCR);
199 saicr = readl(esai->base + ESAI_SAICR);
200 354
201 /* DAI mode */ 355 /* DAI mode */
202 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 356 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
203 case SND_SOC_DAIFMT_I2S: 357 case SND_SOC_DAIFMT_I2S:
204 /* data on rising edge of bclk, frame low 1clk before data */ 358 /* Data on rising edge of bclk, frame low, 1clk before data */
205 tcr &= ~ESAI_TCR_TFSL; 359 xcr |= ESAI_xCR_xFSR;
206 tcr |= ESAI_TCR_TFSR; 360 xccr |= ESAI_xCCR_xFSP | ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
207 rcr &= ~ESAI_RCR_RFSL;
208 rcr |= ESAI_RCR_RFSR;
209 break; 361 break;
210 case SND_SOC_DAIFMT_LEFT_J: 362 case SND_SOC_DAIFMT_LEFT_J:
211 /* data on rising edge of bclk, frame high with data */ 363 /* Data on rising edge of bclk, frame high */
212 tcr &= ~(ESAI_TCR_TFSL | ESAI_TCR_TFSR); 364 xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
213 rcr &= ~(ESAI_RCR_RFSL | ESAI_RCR_RFSR);
214 break; 365 break;
215 case SND_SOC_DAIFMT_DSP_B: 366 case SND_SOC_DAIFMT_RIGHT_J:
216 /* data on rising edge of bclk, frame high with data */ 367 /* Data on rising edge of bclk, frame high, right aligned */
217 tcr |= ESAI_TCR_TFSL; 368 xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCR_xWA;
218 rcr |= ESAI_RCR_RFSL;
219 break; 369 break;
220 case SND_SOC_DAIFMT_DSP_A: 370 case SND_SOC_DAIFMT_DSP_A:
221 /* data on rising edge of bclk, frame high 1clk before data */ 371 /* Data on rising edge of bclk, frame high, 1clk before data */
222 tcr |= ESAI_TCR_TFSL; 372 xcr |= ESAI_xCR_xFSL | ESAI_xCR_xFSR;
223 rcr |= ESAI_RCR_RFSL; 373 xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
374 break;
375 case SND_SOC_DAIFMT_DSP_B:
376 /* Data on rising edge of bclk, frame high */
377 xcr |= ESAI_xCR_xFSL;
378 xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
224 break; 379 break;
225 default: 380 default:
226 return -EINVAL; 381 return -EINVAL;
@@ -228,343 +383,216 @@ static int fsl_esai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
228 383
229 /* DAI clock inversion */ 384 /* DAI clock inversion */
230 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 385 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
231 case SND_SOC_DAIFMT_IB_IF: 386 case SND_SOC_DAIFMT_NB_NF:
232 tccr |= ESAI_TCCR_TFSP; 387 /* Nothing to do for both normal cases */
233 tccr &= ~(ESAI_TCCR_TCKP | ESAI_TCCR_THCKP);
234 rccr &= ~(ESAI_RCCR_RCKP | ESAI_RCCR_RHCKP);
235 rccr |= ESAI_RCCR_RFSP;
236 break; 388 break;
237 case SND_SOC_DAIFMT_IB_NF: 389 case SND_SOC_DAIFMT_IB_NF:
238 tccr &= ~(ESAI_TCCR_TCKP | ESAI_TCCR_THCKP | ESAI_TCCR_TFSP); 390 /* Invert bit clock */
239 rccr &= ~(ESAI_RCCR_RCKP | ESAI_RCCR_RHCKP | ESAI_RCCR_RFSP); 391 xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
240 break; 392 break;
241 case SND_SOC_DAIFMT_NB_IF: 393 case SND_SOC_DAIFMT_NB_IF:
242 tccr |= ESAI_TCCR_TCKP | ESAI_TCCR_THCKP | ESAI_TCCR_TFSP; 394 /* Invert frame clock */
243 rccr |= ESAI_RCCR_RCKP | ESAI_RCCR_RHCKP | ESAI_RCCR_RFSP; 395 xccr ^= ESAI_xCCR_xFSP;
244 break; 396 break;
245 case SND_SOC_DAIFMT_NB_NF: 397 case SND_SOC_DAIFMT_IB_IF:
246 tccr &= ~ESAI_TCCR_TFSP; 398 /* Invert both clocks */
247 tccr |= ESAI_TCCR_TCKP | ESAI_TCCR_THCKP; 399 xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP;
248 rccr &= ~ESAI_RCCR_RFSP;
249 rccr |= ESAI_RCCR_RCKP | ESAI_RCCR_RHCKP;
250 break; 400 break;
251 default: 401 default:
252 return -EINVAL; 402 return -EINVAL;
253 } 403 }
254 404
405 esai_priv->slave_mode = false;
406
255 /* DAI clock master masks */ 407 /* DAI clock master masks */
256 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 408 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
257 case SND_SOC_DAIFMT_CBM_CFM: 409 case SND_SOC_DAIFMT_CBM_CFM:
258 tccr &= ~(ESAI_TCCR_TFSD | ESAI_TCCR_TCKD); 410 esai_priv->slave_mode = true;
259 rccr &= ~(ESAI_RCCR_RFSD | ESAI_RCCR_RCKD);
260 break; 411 break;
261 case SND_SOC_DAIFMT_CBS_CFM: 412 case SND_SOC_DAIFMT_CBS_CFM:
262 tccr &= ~ESAI_TCCR_TFSD; 413 xccr |= ESAI_xCCR_xCKD;
263 tccr |= ESAI_TCCR_TCKD;
264 rccr &= ~ESAI_RCCR_RFSD;
265 rccr |= ESAI_RCCR_RCKD;
266 break; 414 break;
267 case SND_SOC_DAIFMT_CBM_CFS: 415 case SND_SOC_DAIFMT_CBM_CFS:
268 tccr &= ~ESAI_TCCR_TCKD; 416 xccr |= ESAI_xCCR_xFSD;
269 tccr |= ESAI_TCCR_TFSD;
270 rccr &= ~ESAI_RCCR_RCKD;
271 rccr |= ESAI_RCCR_RFSD;
272 break; 417 break;
273 case SND_SOC_DAIFMT_CBS_CFS: 418 case SND_SOC_DAIFMT_CBS_CFS:
274 tccr |= (ESAI_TCCR_TFSD | ESAI_TCCR_TCKD); 419 xccr |= ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
275 rccr |= (ESAI_RCCR_RFSD | ESAI_RCCR_RCKD);
276 break; 420 break;
277 default: 421 default:
278 return -EINVAL; 422 return -EINVAL;
279 } 423 }
280 424
281 /* sync */ 425 mask = ESAI_xCR_xFSL | ESAI_xCR_xFSR;
282 if (esai->flags & IMX_ESAI_SYN) 426 regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, mask, xcr);
283 saicr |= ESAI_SAICR_SYNC; 427 regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, mask, xcr);
284 else
285 saicr &= ~ESAI_SAICR_SYNC;
286
287 tcr &= ESAI_TCR_TMOD_MASK;
288 rcr &= ESAI_RCR_RMOD_MASK;
289 if (esai->flags & IMX_ESAI_NET) {
290 tcr |= ESAI_TCR_TMOD_NETWORK;
291 rcr |= ESAI_RCR_RMOD_NETWORK;
292 } else {
293 tcr |= ESAI_TCR_TMOD_NORMAL;
294 rcr |= ESAI_RCR_RMOD_NORMAL;
295 }
296
297 writel(tcr, esai->base + ESAI_TCR);
298 writel(tccr, esai->base + ESAI_TCCR);
299 writel(rcr, esai->base + ESAI_RCR);
300 writel(rccr, esai->base + ESAI_RCCR);
301
302 writel(saicr, esai->base + ESAI_SAICR);
303 428
304 ESAI_DUMP(); 429 mask = ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP |
305 clk_disable(esai->clk); 430 ESAI_xCCR_xFSD | ESAI_xCCR_xCKD | ESAI_xCR_xWA;
431 regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, mask, xccr);
432 regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, mask, xccr);
306 433
307 return 0; 434 return 0;
308} 435}
309 436
310static int fsl_esai_startup(struct snd_pcm_substream *substream, 437static int fsl_esai_startup(struct snd_pcm_substream *substream,
311 struct snd_soc_dai *cpu_dai) 438 struct snd_soc_dai *dai)
312{ 439{
313 struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai); 440 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
314 441
315 clk_enable(esai->clk); 442 /*
316 clk_prepare_enable(esai->dmaclk); 443 * Some platforms might use the same bit to gate all three or two of
317 clk_prepare_enable(esai->extalclk); 444 * clocks, so keep all clocks open/close at the same time for safety
318 445 */
319 esai->substream[substream->stream] = substream; 446 clk_prepare_enable(esai_priv->dmaclk);
320 447 clk_prepare_enable(esai_priv->coreclk);
321 ESAI_DUMP(); 448 if (!IS_ERR(esai_priv->extalclk))
322 return 0; 449 clk_prepare_enable(esai_priv->extalclk);
323} 450 if (!IS_ERR(esai_priv->fsysclk))
324 451 clk_prepare_enable(esai_priv->fsysclk);
325/* 452
326 * This function is called to initialize the TX port before enable 453 if (!dai->active) {
327 * the tx port. 454 /* Set synchronous mode */
328 */ 455 regmap_update_bits(esai_priv->regmap, REG_ESAI_SAICR,
329static int fsl_esai_hw_tx_params(struct snd_pcm_substream *substream, 456 ESAI_SAICR_SYNC, esai_priv->synchronous ?
330 struct snd_pcm_hw_params *params, 457 ESAI_SAICR_SYNC : 0);
331 struct snd_soc_dai *cpu_dai) 458
332{ 459 /* Set a default slot number -- 2 */
333 struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai); 460 regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
334 u32 tcr, tfcr; 461 ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2));
335 unsigned int channels; 462 regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
336 463 ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2));
337 tcr = readl(esai->base + ESAI_TCR);
338 tfcr = readl(esai->base + ESAI_TFCR);
339
340 tfcr |= ESAI_TFCR_TFR;
341 writel(tfcr, esai->base + ESAI_TFCR);
342 tfcr &= ~ESAI_TFCR_TFR;
343 /* DAI data (word) size */
344 tfcr &= ESAI_TFCR_TWA_MASK;
345 tcr &= ESAI_TCR_TSWS_MASK;
346
347 switch (params_format(params)) {
348 case SNDRV_PCM_FORMAT_S16_LE:
349 tfcr |= ESAI_WORD_LEN_16;
350 tcr |= ESAI_TCR_TSHFD_MSB | ESAI_TCR_TSWS_STL32_WDL16;
351 break;
352 case SNDRV_PCM_FORMAT_S20_3LE:
353 tfcr |= ESAI_WORD_LEN_20;
354 tcr |= ESAI_TCR_TSHFD_MSB | ESAI_TCR_TSWS_STL32_WDL20;
355 break;
356 case SNDRV_PCM_FORMAT_S24_LE:
357 tfcr |= ESAI_WORD_LEN_24;
358 tcr |= ESAI_TCR_TSHFD_MSB | ESAI_TCR_TSWS_STL32_WDL24;
359 break;
360 default:
361 return -EINVAL;
362 } 464 }
363 465
364 channels = params_channels(params); 466 esai_priv->substream[substream->stream] = substream;
365 tfcr &= ESAI_TFCR_TE_MASK;
366 tfcr |= ESAI_TFCR_TE(channels);
367
368 tfcr |= ESAI_TFCR_TFWM(esai->fifo_depth);
369
370 /* Left aligned, Zero padding */
371 tcr |= ESAI_TCR_PADC;
372 /* TDR initialized from the FIFO */
373 tfcr |= ESAI_TFCR_TIEN;
374 467
375 writel(tcr, esai->base + ESAI_TCR);
376 writel(tfcr, esai->base + ESAI_TFCR);
377
378 ESAI_DUMP();
379 return 0; 468 return 0;
380} 469}
381 470
382/* 471static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
383 * This function is called to initialize the RX port before enable 472 struct snd_pcm_hw_params *params,
384 * the rx port. 473 struct snd_soc_dai *dai)
385 */
386static int fsl_esai_hw_rx_params(struct snd_pcm_substream *substream,
387 struct snd_pcm_hw_params *params,
388 struct snd_soc_dai *cpu_dai)
389{ 474{
390 struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai); 475 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
391 u32 rcr, rfcr; 476 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
392 unsigned int channels; 477 u32 width = snd_pcm_format_width(params_format(params));
393 478 u32 channels = params_channels(params);
394 rcr = readl(esai->base + ESAI_RCR); 479 u32 bclk, mask, val, ret;
395 rfcr = readl(esai->base + ESAI_RFCR);
396
397 rfcr |= ESAI_RFCR_RFR;
398 writel(rfcr, esai->base + ESAI_RFCR);
399 rfcr &= ~ESAI_RFCR_RFR;
400
401 rfcr &= ESAI_RFCR_RWA_MASK;
402 rcr &= ESAI_RCR_RSWS_MASK;
403 switch (params_format(params)) {
404 case SNDRV_PCM_FORMAT_S16_LE:
405 rfcr |= ESAI_WORD_LEN_16;
406 rcr |= ESAI_RCR_RSHFD_MSB | ESAI_RCR_RSWS_STL32_WDL16;
407 break;
408 case SNDRV_PCM_FORMAT_S20_3LE:
409 rfcr |= ESAI_WORD_LEN_20;
410 rcr |= ESAI_RCR_RSHFD_MSB | ESAI_RCR_RSWS_STL32_WDL20;
411 break;
412 case SNDRV_PCM_FORMAT_S24_LE:
413 rfcr |= ESAI_WORD_LEN_24;
414 rcr |= ESAI_RCR_RSHFD_MSB | ESAI_RCR_RSWS_STL32_WDL24;
415 break;
416 default:
417 return -EINVAL;
418 }
419 480
420 channels = params_channels(params); 481 bclk = params_rate(params) * esai_priv->slot_width * 2;
421 rfcr &= ESAI_RFCR_RE_MASK;
422 rfcr |= ESAI_RFCR_RE(channels);
423 482
424 rfcr |= ESAI_RFCR_RFWM(esai->fifo_depth); 483 ret = fsl_esai_set_bclk(dai, tx, bclk);
484 if (ret)
485 return ret;
425 486
426 writel(rcr, esai->base + ESAI_RCR); 487 /* Use Normal mode to support monaural audio */
427 writel(rfcr, esai->base + ESAI_RFCR); 488 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
489 ESAI_xCR_xMOD_MASK, params_channels(params) > 1 ?
490 ESAI_xCR_xMOD_NETWORK : 0);
428 491
429 ESAI_DUMP(); 492 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
430 return 0; 493 ESAI_xFCR_xFR_MASK, ESAI_xFCR_xFR);
431}
432 494
433/* 495 mask = ESAI_xFCR_xFR_MASK | ESAI_xFCR_xWA_MASK | ESAI_xFCR_xFWM_MASK |
434 * This function is called to initialize the TX or RX port, 496 (tx ? ESAI_xFCR_TE_MASK | ESAI_xFCR_TIEN : ESAI_xFCR_RE_MASK);
435 */ 497 val = ESAI_xFCR_xWA(width) | ESAI_xFCR_xFWM(esai_priv->fifo_depth) |
436static int fsl_esai_hw_params(struct snd_pcm_substream *substream, 498 (tx ? ESAI_xFCR_TE(channels) | ESAI_xFCR_TIEN : ESAI_xFCR_RE(channels));
437 struct snd_pcm_hw_params *params,
438 struct snd_soc_dai *cpu_dai)
439{
440 struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai);
441 int ret = 0;
442
443 /* Tx/Rx config */
444 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
445 if (readl(esai->base + ESAI_TCR) & ESAI_TCR_TE0)
446 return 0;
447 499
448 ret = fsl_esai_hw_tx_params(substream, params, cpu_dai); 500 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val);
449 } else {
450 if (readl(esai->base + ESAI_RCR) & ESAI_RCR_RE1)
451 return 0;
452 501
453 ret = fsl_esai_hw_rx_params(substream, params, cpu_dai); 502 mask = ESAI_xCR_xSWS_MASK | (tx ? ESAI_xCR_PADC : 0);
454 } 503 val = ESAI_xCR_xSWS(esai_priv->slot_width, width) | (tx ? ESAI_xCR_PADC : 0);
455 504
456 /* 505 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val);
457 * PRRC and PCRC should be set after control register has been set,
458 * before the trigger() be called, according the reference manual.
459 */
460 writel(ESAI_GPIO_ESAI, esai->base + ESAI_PRRC);
461 writel(ESAI_GPIO_ESAI, esai->base + ESAI_PCRC);
462 506
463 return ret; 507 /* Reset Port C */
508 regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
509 ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO));
510 regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
511 ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO));
512 return 0;
464} 513}
465 514
466static void fsl_esai_shutdown(struct snd_pcm_substream *substream, 515static void fsl_esai_shutdown(struct snd_pcm_substream *substream,
467 struct snd_soc_dai *cpu_dai) 516 struct snd_soc_dai *dai)
468{ 517{
469 struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai); 518 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
470 519
471 if (!cpu_dai->active) { 520 if (!dai->active) {
472 writel(0, esai->base + ESAI_PRRC); 521 /* Reset Port C */
473 writel(0, esai->base + ESAI_PCRC); 522 regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
523 ESAI_PRRC_PDC_MASK, 0);
524 regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
525 ESAI_PCRC_PC_MASK, 0);
474 } 526 }
475 527
476 esai->substream[substream->stream] = NULL; 528 esai_priv->substream[substream->stream] = NULL;
477 529
478 clk_disable_unprepare(esai->extalclk); 530 if (!IS_ERR(esai_priv->fsysclk))
479 clk_disable_unprepare(esai->dmaclk); 531 clk_disable_unprepare(esai_priv->fsysclk);
480 clk_disable(esai->clk); 532 if (!IS_ERR(esai_priv->extalclk))
533 clk_disable_unprepare(esai_priv->extalclk);
534 clk_disable_unprepare(esai_priv->coreclk);
535 clk_disable_unprepare(esai_priv->dmaclk);
481} 536}
482 537
483static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, 538static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
484 struct snd_soc_dai *cpu_dai) 539 struct snd_soc_dai *dai)
485{ 540{
486 struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai); 541 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
487 u32 reg, tfcr = 0, rfcr = 0; 542 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
488 int i; 543 u8 i, channels = substream->runtime->channels;
489 544
490 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
491 tfcr = readl(esai->base + ESAI_TFCR);
492 reg = readl(esai->base + ESAI_TCR);
493 } else {
494 rfcr = readl(esai->base + ESAI_RFCR);
495 reg = readl(esai->base + ESAI_RCR);
496 }
497 switch (cmd) { 545 switch (cmd) {
498 case SNDRV_PCM_TRIGGER_START: 546 case SNDRV_PCM_TRIGGER_START:
499 case SNDRV_PCM_TRIGGER_RESUME: 547 case SNDRV_PCM_TRIGGER_RESUME:
500 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 548 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
501 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 549 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
502 tfcr |= ESAI_TFCR_TFEN; 550 ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN);
503 writel(tfcr, esai->base + ESAI_TFCR); 551
504 /* write initial words to ETDR register */ 552 /* Write initial words reqiured by ESAI as normal procedure */
505 for (i = 0; i < substream->runtime->channels; i++) 553 for (i = 0; tx && i < channels; i++)
506 writel(0x0, esai->base + ESAI_ETDR); 554 regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0);
507 reg |= ESAI_TCR_TE(substream->runtime->channels); 555
508 writel(reg, esai->base + ESAI_TCR); 556 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
509 } else { 557 tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
510 rfcr |= ESAI_RFCR_RFEN; 558 tx ? ESAI_xCR_TE(channels) : ESAI_xCR_RE(channels));
511 writel(rfcr, esai->base + ESAI_RFCR);
512 reg |= ESAI_RCR_RE(substream->runtime->channels);
513 writel(reg, esai->base + ESAI_RCR);
514 }
515 break; 559 break;
516 case SNDRV_PCM_TRIGGER_SUSPEND: 560 case SNDRV_PCM_TRIGGER_SUSPEND:
517 case SNDRV_PCM_TRIGGER_STOP: 561 case SNDRV_PCM_TRIGGER_STOP:
518 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 562 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
519 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 563 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
520 reg &= ~ESAI_TCR_TE(substream->runtime->channels); 564 tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0);
521 writel(reg, esai->base + ESAI_TCR); 565
522 tfcr |= ESAI_TFCR_TFR; 566 /* Disable and reset FIFO */
523 tfcr &= ~ESAI_TFCR_TFEN; 567 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
524 writel(tfcr, esai->base + ESAI_TFCR); 568 ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR);
525 tfcr &= ~ESAI_TFCR_TFR; 569 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
526 writel(tfcr, esai->base + ESAI_TFCR); 570 ESAI_xFCR_xFR, 0);
527 } else {
528 reg &= ~ESAI_RCR_RE(substream->runtime->channels);
529 writel(reg, esai->base + ESAI_RCR);
530 rfcr |= ESAI_RFCR_RFR;
531 rfcr &= ~ESAI_RFCR_RFEN;
532 writel(rfcr, esai->base + ESAI_RFCR);
533 rfcr &= ~ESAI_RFCR_RFR;
534 writel(rfcr, esai->base + ESAI_RFCR);
535 }
536 break; 571 break;
537 default: 572 default:
538 return -EINVAL; 573 return -EINVAL;
539 } 574 }
540 575
541 ESAI_DUMP();
542 return 0; 576 return 0;
543} 577}
544 578
545#define IMX_ESAI_RATES SNDRV_PCM_RATE_8000_192000
546
547#define IMX_ESAI_FORMATS \
548 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
549 SNDRV_PCM_FMTBIT_S24_LE)
550
551static struct snd_soc_dai_ops fsl_esai_dai_ops = { 579static struct snd_soc_dai_ops fsl_esai_dai_ops = {
552 .startup = fsl_esai_startup, 580 .startup = fsl_esai_startup,
553 .shutdown = fsl_esai_shutdown, 581 .shutdown = fsl_esai_shutdown,
554 .trigger = fsl_esai_trigger, 582 .trigger = fsl_esai_trigger,
555 .hw_params = fsl_esai_hw_params, 583 .hw_params = fsl_esai_hw_params,
556 .set_sysclk = fsl_esai_set_dai_sysclk, 584 .set_sysclk = fsl_esai_set_dai_sysclk,
557 .set_clkdiv = fsl_esai_set_dai_clkdiv,
558 .set_fmt = fsl_esai_set_dai_fmt, 585 .set_fmt = fsl_esai_set_dai_fmt,
559 .set_tdm_slot = fsl_esai_set_dai_tdm_slot, 586 .set_tdm_slot = fsl_esai_set_dai_tdm_slot,
560}; 587};
561 588
562static int fsl_esai_dai_probe(struct snd_soc_dai *dai) 589static int fsl_esai_dai_probe(struct snd_soc_dai *dai)
563{ 590{
564 struct fsl_esai *esai = snd_soc_dai_get_drvdata(dai); 591 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
592
593 snd_soc_dai_init_dma_data(dai, &esai_priv->dma_params_tx,
594 &esai_priv->dma_params_rx);
565 595
566 dai->playback_dma_data = &esai->dma_params_tx;
567 dai->capture_dma_data = &esai->dma_params_rx;
568 return 0; 596 return 0;
569} 597}
570 598
@@ -574,15 +602,15 @@ static struct snd_soc_dai_driver fsl_esai_dai = {
574 .stream_name = "esai-Playback", 602 .stream_name = "esai-Playback",
575 .channels_min = 1, 603 .channels_min = 1,
576 .channels_max = 12, 604 .channels_max = 12,
577 .rates = IMX_ESAI_RATES, 605 .rates = FSL_ESAI_RATES,
578 .formats = IMX_ESAI_FORMATS, 606 .formats = FSL_ESAI_FORMATS,
579 }, 607 },
580 .capture = { 608 .capture = {
581 .stream_name = "esai-Capture", 609 .stream_name = "esai-Capture",
582 .channels_min = 1, 610 .channels_min = 1,
583 .channels_max = 8, 611 .channels_max = 8,
584 .rates = IMX_ESAI_RATES, 612 .rates = FSL_ESAI_RATES,
585 .formats = IMX_ESAI_FORMATS, 613 .formats = FSL_ESAI_FORMATS,
586 }, 614 },
587 .ops = &fsl_esai_dai_ops, 615 .ops = &fsl_esai_dai_ops,
588}; 616};
@@ -591,51 +619,128 @@ static const struct snd_soc_component_driver fsl_esai_component = {
591 .name = "fsl-esai", 619 .name = "fsl-esai",
592}; 620};
593 621
622static bool fsl_esai_readable_reg(struct device *dev, unsigned int reg)
623{
624 switch (reg) {
625 case REG_ESAI_ERDR:
626 case REG_ESAI_ECR:
627 case REG_ESAI_ESR:
628 case REG_ESAI_TFCR:
629 case REG_ESAI_TFSR:
630 case REG_ESAI_RFCR:
631 case REG_ESAI_RFSR:
632 case REG_ESAI_RX0:
633 case REG_ESAI_RX1:
634 case REG_ESAI_RX2:
635 case REG_ESAI_RX3:
636 case REG_ESAI_SAISR:
637 case REG_ESAI_SAICR:
638 case REG_ESAI_TCR:
639 case REG_ESAI_TCCR:
640 case REG_ESAI_RCR:
641 case REG_ESAI_RCCR:
642 case REG_ESAI_TSMA:
643 case REG_ESAI_TSMB:
644 case REG_ESAI_RSMA:
645 case REG_ESAI_RSMB:
646 case REG_ESAI_PRRC:
647 case REG_ESAI_PCRC:
648 return true;
649 default:
650 return false;
651 }
652}
653
654static bool fsl_esai_writeable_reg(struct device *dev, unsigned int reg)
655{
656 switch (reg) {
657 case REG_ESAI_ETDR:
658 case REG_ESAI_ECR:
659 case REG_ESAI_TFCR:
660 case REG_ESAI_RFCR:
661 case REG_ESAI_TX0:
662 case REG_ESAI_TX1:
663 case REG_ESAI_TX2:
664 case REG_ESAI_TX3:
665 case REG_ESAI_TX4:
666 case REG_ESAI_TX5:
667 case REG_ESAI_TSR:
668 case REG_ESAI_SAICR:
669 case REG_ESAI_TCR:
670 case REG_ESAI_TCCR:
671 case REG_ESAI_RCR:
672 case REG_ESAI_RCCR:
673 case REG_ESAI_TSMA:
674 case REG_ESAI_TSMB:
675 case REG_ESAI_RSMA:
676 case REG_ESAI_RSMB:
677 case REG_ESAI_PRRC:
678 case REG_ESAI_PCRC:
679 return true;
680 default:
681 return false;
682 }
683}
684
685static const struct regmap_config fsl_esai_regmap_config = {
686 .reg_bits = 32,
687 .reg_stride = 4,
688 .val_bits = 32,
689
690 .max_register = REG_ESAI_PCRC,
691 .readable_reg = fsl_esai_readable_reg,
692 .writeable_reg = fsl_esai_writeable_reg,
693};
694
594static bool fsl_esai_check_xrun(struct snd_pcm_substream *substream) 695static bool fsl_esai_check_xrun(struct snd_pcm_substream *substream)
595{ 696{
596 struct snd_soc_pcm_runtime *rtd = substream->private_data; 697 struct snd_soc_pcm_runtime *rtd = substream->private_data;
597 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 698 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
598 struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai); 699 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(cpu_dai);
599 u32 saisr = readl(esai->base + ESAI_SAISR); 700 u32 saisr;
701
702 regmap_read(esai_priv->regmap, REG_ESAI_SAISR, &saisr);
600 703
601 return saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE) ; 704 return saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE) ;
602} 705}
603 706
604static int store_reg(struct snd_soc_dai *cpu_dai) 707static int store_reg(struct snd_soc_dai *cpu_dai)
605{ 708{
606 struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai); 709 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(cpu_dai);
607 710
608 esai->reg_cache[0] = readl(esai->base + ESAI_ECR); 711 regmap_read(esai_priv->regmap, REG_ESAI_ECR, &esai_priv->reg_cache[0]);
609 esai->reg_cache[2] = readl(esai->base + ESAI_TFCR); 712 regmap_read(esai_priv->regmap, REG_ESAI_TFCR, &esai_priv->reg_cache[2]);
610 esai->reg_cache[4] = readl(esai->base + ESAI_RFCR); 713 regmap_read(esai_priv->regmap, REG_ESAI_RFCR, &esai_priv->reg_cache[4]);
611 esai->reg_cache[8] = readl(esai->base + ESAI_SAICR); 714 regmap_read(esai_priv->regmap, REG_ESAI_SAICR, &esai_priv->reg_cache[8]);
612 esai->reg_cache[9] = readl(esai->base + ESAI_TCR); 715 regmap_read(esai_priv->regmap, REG_ESAI_TCR, &esai_priv->reg_cache[9]);
613 esai->reg_cache[10] = readl(esai->base + ESAI_TCCR); 716 regmap_read(esai_priv->regmap, REG_ESAI_TCCR, &esai_priv->reg_cache[10]);
614 esai->reg_cache[11] = readl(esai->base + ESAI_RCR); 717 regmap_read(esai_priv->regmap, REG_ESAI_RCR, &esai_priv->reg_cache[11]);
615 esai->reg_cache[12] = readl(esai->base + ESAI_RCCR); 718 regmap_read(esai_priv->regmap, REG_ESAI_RCCR, &esai_priv->reg_cache[12]);
616 esai->reg_cache[13] = readl(esai->base + ESAI_TSMA); 719 regmap_read(esai_priv->regmap, REG_ESAI_TSMA, &esai_priv->reg_cache[13]);
617 esai->reg_cache[14] = readl(esai->base + ESAI_TSMB); 720 regmap_read(esai_priv->regmap, REG_ESAI_TSMB, &esai_priv->reg_cache[14]);
618 esai->reg_cache[15] = readl(esai->base + ESAI_RSMA); 721 regmap_read(esai_priv->regmap, REG_ESAI_RSMA, &esai_priv->reg_cache[15]);
619 esai->reg_cache[16] = readl(esai->base + ESAI_RSMB); 722 regmap_read(esai_priv->regmap, REG_ESAI_RSMB, &esai_priv->reg_cache[16]);
723
620 return 0; 724 return 0;
621} 725}
622 726
623static int restore_reg(struct snd_soc_dai *cpu_dai) 727static int restore_reg(struct snd_soc_dai *cpu_dai)
624{ 728{
625 struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai); 729 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(cpu_dai);
626 730
627 writel(esai->reg_cache[0], esai->base + ESAI_ECR); 731 regmap_write(esai_priv->regmap, REG_ESAI_ECR, esai_priv->reg_cache[0]);
628 writel(esai->reg_cache[2] & ~ESAI_TFCR_TFEN, esai->base + ESAI_TFCR); 732 regmap_write(esai_priv->regmap, REG_ESAI_TFCR, esai_priv->reg_cache[2] & ~ESAI_xFCR_xFEN);
629 writel(esai->reg_cache[4] & ~ESAI_RFCR_RFEN, esai->base + ESAI_RFCR); 733 regmap_write(esai_priv->regmap, REG_ESAI_RFCR, esai_priv->reg_cache[4] & ~ESAI_xFCR_xFEN);
630 writel(esai->reg_cache[8], esai->base + ESAI_SAICR); 734 regmap_write(esai_priv->regmap, REG_ESAI_SAICR, esai_priv->reg_cache[8]);
631 writel(esai->reg_cache[9] & ~ESAI_TCR_TE(12), esai->base + ESAI_TCR); 735 regmap_write(esai_priv->regmap, REG_ESAI_TCR, esai_priv->reg_cache[9] & ~ESAI_xCR_TE(12));
632 writel(esai->reg_cache[10], esai->base + ESAI_TCCR); 736 regmap_write(esai_priv->regmap, REG_ESAI_TCCR, esai_priv->reg_cache[10]);
633 writel(esai->reg_cache[11] & ~ESAI_RCR_RE(8), esai->base + ESAI_RCR); 737 regmap_write(esai_priv->regmap, REG_ESAI_RCR, esai_priv->reg_cache[11] & ~ESAI_xCR_RE(8));
634 writel(esai->reg_cache[12], esai->base + ESAI_RCCR); 738 regmap_write(esai_priv->regmap, REG_ESAI_RCCR, esai_priv->reg_cache[12]);
635 writel(esai->reg_cache[13], esai->base + ESAI_TSMA); 739 regmap_write(esai_priv->regmap, REG_ESAI_TSMA, esai_priv->reg_cache[13]);
636 writel(esai->reg_cache[14], esai->base + ESAI_TSMB); 740 regmap_write(esai_priv->regmap, REG_ESAI_TSMB, esai_priv->reg_cache[14]);
637 writel(esai->reg_cache[15], esai->base + ESAI_RSMA); 741 regmap_write(esai_priv->regmap, REG_ESAI_RSMA, esai_priv->reg_cache[15]);
638 writel(esai->reg_cache[16], esai->base + ESAI_RSMB); 742 regmap_write(esai_priv->regmap, REG_ESAI_RSMB, esai_priv->reg_cache[16]);
743
639 return 0; 744 return 0;
640} 745}
641 746
@@ -677,229 +782,210 @@ static void fsl_esai_reset(struct snd_pcm_substream *substream, bool stop)
677{ 782{
678 struct snd_soc_pcm_runtime *rtd = substream->private_data; 783 struct snd_soc_pcm_runtime *rtd = substream->private_data;
679 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 784 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
680 struct fsl_esai *esai = snd_soc_dai_get_drvdata(cpu_dai); 785 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(cpu_dai);
681 ESAI_DUMP(); 786 u32 saisr;
682 787
683 if (stop) { 788 if (stop) {
684 stop_lock_stream(esai->substream[0]); 789 stop_lock_stream(esai_priv->substream[0]);
685 stop_lock_stream(esai->substream[1]); 790 stop_lock_stream(esai_priv->substream[1]);
686 } 791 }
687 792
688 store_reg(cpu_dai); 793 store_reg(cpu_dai);
689 794
690 writel(ESAI_ECR_ESAIEN | ESAI_ECR_ERST, esai->base + ESAI_ECR); 795 regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN | ESAI_ECR_ERST);
691 writel(ESAI_ECR_ESAIEN, esai->base + ESAI_ECR); 796 regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN);
692 797
693 write_esai_mask(esai->base+ESAI_TCR, 0, ESAI_TCR_TPR); 798 regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, ESAI_xCR_xPR_MASK, ESAI_xCR_xPR);
694 write_esai_mask(esai->base+ESAI_RCR, 0, ESAI_RCR_RPR); 799 regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, ESAI_xCR_xPR_MASK, ESAI_xCR_xPR);
695 800
696 restore_reg(cpu_dai); 801 restore_reg(cpu_dai);
697 802
698 write_esai_mask(esai->base+ESAI_TCR, ESAI_TCR_TPR, 0); 803 regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, ESAI_xCR_xPR_MASK, 0);
699 write_esai_mask(esai->base+ESAI_RCR, ESAI_RCR_RPR, 0); 804 regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, ESAI_xCR_xPR_MASK, 0);
700 805
701 writel(ESAI_GPIO_ESAI, esai->base + ESAI_PRRC); 806 regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
702 writel(ESAI_GPIO_ESAI, esai->base + ESAI_PCRC); 807 ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO));
808 regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
809 ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO));
703 810
704 /* read "TUE" flag.*/ 811 regmap_read(esai_priv->regmap, REG_ESAI_SAISR, &saisr);
705 readl(esai->base + ESAI_SAISR);
706 812
707 if (stop) { 813 if (stop) {
708 start_unlock_stream(esai->substream[1]); 814 start_unlock_stream(esai_priv->substream[1]);
709 start_unlock_stream(esai->substream[0]); 815 start_unlock_stream(esai_priv->substream[0]);
710 } 816 }
711 ESAI_DUMP();
712}
713
714static int fsl_esai_reg_init(struct fsl_esai *esai)
715{
716 u32 xccr, slots = 2;
717
718 clk_enable(esai->clk);
719
720 /* Reset and enable the ESAI module */
721 writel(ESAI_ECR_ERST, esai->base + ESAI_ECR);
722 writel(ESAI_ECR_ESAIEN, esai->base + ESAI_ECR);
723
724 /* Set default slot number to 2 for common DAI FMTs */
725 xccr = readl(esai->base + ESAI_TCCR);
726 xccr &= ESAI_TCCR_TDC_MASK;
727 xccr |= ESAI_TCCR_TDC(slots - 1);
728 writel(xccr, esai->base + ESAI_TCCR);
729
730 xccr = readl(esai->base + ESAI_RCCR);
731 xccr &= ESAI_RCCR_RDC_MASK;
732 xccr |= ESAI_RCCR_RDC(slots - 1);
733 writel(xccr, esai->base + ESAI_RCCR);
734
735 clk_disable(esai->clk);
736
737 return 0;
738} 817}
739 818
740static int fsl_esai_probe(struct platform_device *pdev) 819static int fsl_esai_probe(struct platform_device *pdev)
741{ 820{
742 struct device_node *np = pdev->dev.of_node; 821 struct device_node *np = pdev->dev.of_node;
743 struct resource res; 822 struct fsl_esai *esai_priv;
744 struct fsl_esai *esai; 823 struct resource *res;
745 const uint32_t *iprop; 824 const uint32_t *iprop;
746 uint32_t flag; 825 void __iomem *regs;
747 const char *p; 826 int irq, ret;
748 u32 dma_events[2]; 827 u32 dma_events[2];
749 int ret = 0;
750 828
751 esai = devm_kzalloc(&pdev->dev, sizeof(*esai), GFP_KERNEL); 829 esai_priv = devm_kzalloc(&pdev->dev, sizeof(*esai_priv), GFP_KERNEL);
752 if (!esai) { 830 if (!esai_priv)
753 dev_err(&pdev->dev, "mem allocation failed\n");
754 return -ENOMEM; 831 return -ENOMEM;
755 }
756 832
757 ret = of_property_read_u32(np, "fsl,flags", &flag); 833 esai_priv->pdev = pdev;
758 if (ret < 0) { 834 strcpy(esai_priv->name, np->name);
759 dev_err(&pdev->dev, "There is no flag for esai\n"); 835
760 return -EINVAL; 836 /* Get the addresses and IRQ */
837 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
838 regs = devm_ioremap_resource(&pdev->dev, res);
839 if (IS_ERR(regs))
840 return PTR_ERR(regs);
841
842 esai_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
843 "core", regs, &fsl_esai_regmap_config);
844 if (IS_ERR(esai_priv->regmap)) {
845 dev_err(&pdev->dev, "failed to init regmap: %ld\n",
846 PTR_ERR(esai_priv->regmap));
847 return PTR_ERR(esai_priv->regmap);
761 } 848 }
762 esai->flags = flag;
763 849
764 esai->clk = devm_clk_get(&pdev->dev, "core"); 850 esai_priv->coreclk = devm_clk_get(&pdev->dev, "core");
765 if (IS_ERR(esai->clk)) { 851 if (IS_ERR(esai_priv->coreclk)) {
766 ret = PTR_ERR(esai->clk); 852 dev_err(&pdev->dev, "failed to get core clock: %ld\n",
767 dev_err(&pdev->dev, "Cannot get the clock: %d\n", ret); 853 PTR_ERR(esai_priv->coreclk));
768 return ret; 854 return PTR_ERR(esai_priv->coreclk);
769 } 855 }
770 clk_prepare(esai->clk);
771 856
772 esai->dmaclk = devm_clk_get(&pdev->dev, "dma"); 857 esai_priv->extalclk = devm_clk_get(&pdev->dev, "extal");
773 if (IS_ERR(esai->dmaclk)) { 858 if (IS_ERR(esai_priv->extalclk))
774 ret = PTR_ERR(esai->dmaclk); 859 dev_warn(&pdev->dev, "failed to get extal clock: %ld\n",
775 dev_err(&pdev->dev, "Cannot get dma clock: %d\n", ret); 860 PTR_ERR(esai_priv->extalclk));
776 goto failed_get_resource; 861
862 esai_priv->fsysclk = devm_clk_get(&pdev->dev, "fsys");
863 if (IS_ERR(esai_priv->fsysclk))
864 dev_warn(&pdev->dev, "failed to get fsys clock: %ld\n",
865 PTR_ERR(esai_priv->fsysclk));
866
867 esai_priv->dmaclk = devm_clk_get(&pdev->dev, "dma");
868 if (IS_ERR(esai_priv->dmaclk)) {
869 dev_err(&pdev->dev, "Cannot get dma clock: %ld\n",
870 PTR_ERR(esai_priv->dmaclk));
871 return PTR_ERR(esai_priv->dmaclk);
777 } 872 }
778 873
779 esai->extalclk = devm_clk_get(&pdev->dev, "extal"); 874 irq = platform_get_irq(pdev, 0);
780 if (IS_ERR(esai->extalclk)) { 875 if (irq < 0) {
781 ret = PTR_ERR(esai->extalclk); 876 dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
782 dev_err(&pdev->dev, "Cannot get extal clock: %d\n", ret); 877 return irq;
783 goto failed_get_resource;
784 } 878 }
785 879
786 ret = of_address_to_resource(np, 0, &res); 880 ret = devm_request_irq(&pdev->dev, irq, esai_isr, 0,
881 esai_priv->name, esai_priv);
787 if (ret) { 882 if (ret) {
788 dev_err(&pdev->dev, "could not determine device resources\n"); 883 dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
789 goto failed_get_resource; 884 return ret;
790 } 885 }
791 886
792 esai->base = of_iomap(np, 0); 887 /* Set a default slot size */
793 if (!esai->base) { 888 esai_priv->slot_width = 32;
794 dev_err(&pdev->dev, "could not map device resources\n");
795 ret = -ENOMEM;
796 goto failed_iomap;
797 }
798 889
799 esai->irq = irq_of_parse_and_map(np, 0); 890 /* Set a default master/slave state */
891 esai_priv->slave_mode = true;
800 892
801 /* Determine the FIFO depth. */ 893 /* Determine the FIFO depth */
802 iprop = of_get_property(np, "fsl,fifo-depth", NULL); 894 iprop = of_get_property(np, "fsl,fifo-depth", NULL);
803 if (iprop) 895 if (iprop)
804 esai->fifo_depth = be32_to_cpup(iprop); 896 esai_priv->fifo_depth = be32_to_cpup(iprop);
805 else 897 else
806 esai->fifo_depth = 64; 898 esai_priv->fifo_depth = 64;
807
808 esai->dma_params_tx.maxburst = 16;
809 esai->dma_params_rx.maxburst = 16;
810
811 esai->dma_params_tx.addr = res.start + ESAI_ETDR;
812 esai->dma_params_rx.addr = res.start + ESAI_ERDR;
813 899
814 esai->dma_params_tx.filter_data = &esai->filter_data_tx; 900 esai_priv->dma_params_tx.maxburst = 16;
815 esai->dma_params_rx.filter_data = &esai->filter_data_rx; 901 esai_priv->dma_params_rx.maxburst = 16;
902 esai_priv->dma_params_tx.addr = res->start + REG_ESAI_ETDR;
903 esai_priv->dma_params_rx.addr = res->start + REG_ESAI_ERDR;
816 904
817 esai->dma_params_tx.check_xrun = fsl_esai_check_xrun; 905 esai_priv->dma_params_tx.filter_data = &esai_priv->filter_data_tx;
818 esai->dma_params_rx.check_xrun = fsl_esai_check_xrun; 906 esai_priv->dma_params_rx.filter_data = &esai_priv->filter_data_rx;
819 esai->dma_params_tx.device_reset = fsl_esai_reset;
820 esai->dma_params_rx.device_reset = fsl_esai_reset;
821 907
822 ret = of_property_read_u32_array(pdev->dev.of_node, 908 ret = of_property_read_u32_array(pdev->dev.of_node,
823 "fsl,esai-dma-events", dma_events, 2); 909 "fsl,esai-dma-events", dma_events, 2);
824 if (ret) { 910 if (ret) {
825 dev_err(&pdev->dev, "could not get dma events\n"); 911 dev_err(&pdev->dev, "could not get dma events\n");
826 goto failed_get_dma; 912 return ret;
827 } 913 }
828 914
829 esai->filter_data_tx.dma_request0 = dma_events[0]; 915 esai_priv->filter_data_tx.dma_request0 = dma_events[0];
830 esai->filter_data_rx.dma_request0 = dma_events[1]; 916 esai_priv->filter_data_rx.dma_request0 = dma_events[1];
831 esai->filter_data_tx.peripheral_type = IMX_DMATYPE_ESAI; 917 esai_priv->filter_data_tx.peripheral_type = IMX_DMATYPE_ESAI;
832 esai->filter_data_rx.peripheral_type = IMX_DMATYPE_ESAI; 918 esai_priv->filter_data_rx.peripheral_type = IMX_DMATYPE_ESAI;
919
920 esai_priv->dma_params_tx.check_xrun = fsl_esai_check_xrun;
921 esai_priv->dma_params_rx.check_xrun = fsl_esai_check_xrun;
922 esai_priv->dma_params_tx.device_reset = fsl_esai_reset;
923 esai_priv->dma_params_rx.device_reset = fsl_esai_reset;
924
925 esai_priv->synchronous =
926 of_property_read_bool(np, "fsl,esai-synchronous");
833 927
834 platform_set_drvdata(pdev, esai); 928 /* Implement full symmetry for synchronous mode */
929 if (esai_priv->synchronous) {
930 fsl_esai_dai.symmetric_rates = 1;
931 fsl_esai_dai.symmetric_channels = 1;
932 fsl_esai_dai.symmetric_samplebits = 1;
933 }
835 934
836 p = strrchr(np->full_name, '/') + 1; 935 dev_set_drvdata(&pdev->dev, esai_priv);
837 strcpy(esai->name, p);
838 fsl_esai_dai.name = esai->name;
839 936
840 ret = snd_soc_register_component(&pdev->dev, &fsl_esai_component, 937 /* Reset ESAI unit */
841 &fsl_esai_dai, 1); 938 ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ERST);
842 if (ret) { 939 if (ret) {
843 dev_err(&pdev->dev, "register DAI failed\n"); 940 dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret);
844 goto failed_register; 941 return ret;
845 } 942 }
846 943
847 ret = imx_pcm_dma_init(pdev, SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | 944 /*
848 SND_DMAENGINE_PCM_FLAG_NO_DT | 945 * We need to enable ESAI so as to access some of its registers.
849 SND_DMAENGINE_PCM_FLAG_COMPAT, 946 * Otherwise, we would fail to dump regmap from user space.
850 IMX_ESAI_DMABUF_SIZE); 947 */
948 ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN);
851 if (ret) { 949 if (ret) {
852 dev_err(&pdev->dev, "init pcm dma failed\n"); 950 dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret);
853 goto failed_pcm_init; 951 return ret;
854 } 952 }
855 953
856 fsl_esai_reg_init(esai); 954 ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component,
955 &fsl_esai_dai, 1);
956 if (ret) {
957 dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
958 return ret;
959 }
857 960
858 return 0; 961 ret = imx_pcm_dma_init(pdev, SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
962 SND_DMAENGINE_PCM_FLAG_NO_DT |
963 SND_DMAENGINE_PCM_FLAG_COMPAT,
964 IMX_ESAI_DMABUF_SIZE);
965 if (ret)
966 dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
859 967
860failed_pcm_init:
861 snd_soc_unregister_component(&pdev->dev);
862failed_register:
863failed_get_dma:
864 irq_dispose_mapping(esai->irq);
865 iounmap(esai->base);
866failed_iomap:
867failed_get_resource:
868 clk_unprepare(esai->clk);
869 return ret; 968 return ret;
870} 969}
871 970
872static int fsl_esai_remove(struct platform_device *pdev) 971static const struct of_device_id fsl_esai_dt_ids[] = {
873{ 972 { .compatible = "fsl,imx35-esai", },
874 struct fsl_esai *esai = platform_get_drvdata(pdev);
875
876 imx_pcm_dma_exit(pdev);
877 snd_soc_unregister_component(&pdev->dev);
878
879 irq_dispose_mapping(esai->irq);
880 iounmap(esai->base);
881 clk_unprepare(esai->clk);
882 return 0;
883}
884
885static const struct of_device_id fsl_esai_ids[] = {
886 { .compatible = "fsl,imx6q-esai", },
887 {} 973 {}
888}; 974};
975MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
889 976
890static struct platform_driver fsl_esai_driver = { 977static struct platform_driver fsl_esai_driver = {
891 .probe = fsl_esai_probe, 978 .probe = fsl_esai_probe,
892 .remove = fsl_esai_remove,
893 .driver = { 979 .driver = {
894 .name = "fsl-esai-dai", 980 .name = "fsl-esai-dai",
895 .owner = THIS_MODULE, 981 .owner = THIS_MODULE,
896 .of_match_table = fsl_esai_ids, 982 .of_match_table = fsl_esai_dt_ids,
897 }, 983 },
898}; 984};
899 985
900module_platform_driver(fsl_esai_driver); 986module_platform_driver(fsl_esai_driver);
901 987
902MODULE_AUTHOR("Freescale Semiconductor, Inc."); 988MODULE_AUTHOR("Freescale Semiconductor, Inc.");
903MODULE_DESCRIPTION("i.MX ASoC ESAI driver"); 989MODULE_DESCRIPTION("Freescale ESAI CPU DAI driver");
990MODULE_LICENSE("GPL v2");
904MODULE_ALIAS("platform:fsl-esai-dai"); 991MODULE_ALIAS("platform:fsl-esai-dai");
905MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/fsl_esai.h b/sound/soc/fsl/fsl_esai.h
index b2551c530782..9c9f957fcae1 100644
--- a/sound/soc/fsl/fsl_esai.h
+++ b/sound/soc/fsl/fsl_esai.h
@@ -1,339 +1,354 @@
1/* 1/*
2 * imx-esai.h -- ESAI driver header file for Freescale IMX 2 * fsl_esai.h - ALSA ESAI interface for the Freescale i.MX SoC
3 * 3 *
4 * Copyright 2008-2014 Freescale Semiconductor, Inc. All Rights Reserved. 4 * Copyright (C) 2014 Freescale Semiconductor, Inc.
5 */
6
7/*
8 * The code contained herein is licensed under the GNU General Public
9 * License. You may obtain a copy of the GNU General Public License
10 * Version 2 or later at the following locations:
11 * 5 *
12 * http://www.opensource.org/licenses/gpl-license.html 6 * Author: Nicolin Chen <Guangyu.Chen@freescale.com>
13 * http://www.gnu.org/copyleft/gpl.html 7 *
8 * This file is licensed under the terms of the GNU General Public License
9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
14 */ 11 */
15 12
16#ifndef _MXC_ESAI_H 13#ifndef _FSL_ESAI_DAI_H
17#define _MXC_ESAI_H 14#define _FSL_ESAI_DAI_H
18 15
19#ifdef IMX_ESAI_DUMP 16/* ESAI Register Map */
20#define ESAI_DUMP() \ 17#define REG_ESAI_ETDR 0x00
21 do {pr_info("dump @ %s\n", __func__); \ 18#define REG_ESAI_ERDR 0x04
22 pr_info("ESAI_ECR 0x%08x\n", readl(esai->base + ESAI_ECR)); \ 19#define REG_ESAI_ECR 0x08
23 pr_info("ESAI_ESR 0x%08x\n", readl(esai->base + ESAI_ESR)); \ 20#define REG_ESAI_ESR 0x0C
24 pr_info("ESAI_TFCR 0x%08x\n", readl(esai->base + ESAI_TFCR)); \ 21#define REG_ESAI_TFCR 0x10
25 pr_info("ESAI_TFSR 0x%08x\n", readl(esai->base + ESAI_TFSR)); \ 22#define REG_ESAI_TFSR 0x14
26 pr_info("ESAI_RFCR 0x%08x\n", readl(esai->base + ESAI_RFCR)); \ 23#define REG_ESAI_RFCR 0x18
27 pr_info("ESAI_RFSR 0x%08x\n", readl(esai->base + ESAI_RFSR)); \ 24#define REG_ESAI_RFSR 0x1C
28 pr_info("ESAI_TSR 0x%08x\n", readl(esai->base + ESAI_TSR)); \ 25#define REG_ESAI_xFCR(tx) (tx ? REG_ESAI_TFCR : REG_ESAI_RFCR)
29 pr_info("ESAI_SAISR 0x%08x\n", readl(esai->base + ESAI_SAISR)); \ 26#define REG_ESAI_xFSR(tx) (tx ? REG_ESAI_TFSR : REG_ESAI_RFSR)
30 pr_info("ESAI_SAICR 0x%08x\n", readl(esai->base + ESAI_SAICR)); \ 27#define REG_ESAI_TX0 0x80
31 pr_info("ESAI_TCR 0x%08x\n", readl(esai->base + ESAI_TCR)); \ 28#define REG_ESAI_TX1 0x84
32 pr_info("ESAI_TCCR 0x%08x\n", readl(esai->base + ESAI_TCCR)); \ 29#define REG_ESAI_TX2 0x88
33 pr_info("ESAI_RCR 0x%08x\n", readl(esai->base + ESAI_RCR)); \ 30#define REG_ESAI_TX3 0x8C
34 pr_info("ESAI_RCCR 0x%08x\n", readl(esai->base + ESAI_RCCR)); \ 31#define REG_ESAI_TX4 0x90
35 pr_info("ESAI_TSMA 0x%08x\n", readl(esai->base + ESAI_TSMA)); \ 32#define REG_ESAI_TX5 0x94
36 pr_info("ESAI_TSMB 0x%08x\n", readl(esai->base + ESAI_TSMB)); \ 33#define REG_ESAI_TSR 0x98
37 pr_info("ESAI_RSMA 0x%08x\n", readl(esai->base + ESAI_RSMA)); \ 34#define REG_ESAI_RX0 0xA0
38 pr_info("ESAI_RSMB 0x%08x\n", readl(esai->base + ESAI_RSMB)); \ 35#define REG_ESAI_RX1 0xA4
39 pr_info("ESAI_PRRC 0x%08x\n", readl(esai->base + ESAI_PRRC)); \ 36#define REG_ESAI_RX2 0xA8
40 pr_info("ESAI_PCRC 0x%08x\n", readl(esai->base + ESAI_PCRC)); \ 37#define REG_ESAI_RX3 0xAC
41 } while (0); 38#define REG_ESAI_SAISR 0xCC
42#else 39#define REG_ESAI_SAICR 0xD0
43#define ESAI_DUMP() 40#define REG_ESAI_TCR 0xD4
44#endif 41#define REG_ESAI_TCCR 0xD8
45 42#define REG_ESAI_RCR 0xDC
46#define ESAI_ETDR 0x00 43#define REG_ESAI_RCCR 0xE0
47#define ESAI_ERDR 0x04 44#define REG_ESAI_xCR(tx) (tx ? REG_ESAI_TCR : REG_ESAI_RCR)
48#define ESAI_ECR 0x08 45#define REG_ESAI_xCCR(tx) (tx ? REG_ESAI_TCCR : REG_ESAI_RCCR)
49#define ESAI_ESR 0x0C 46#define REG_ESAI_TSMA 0xE4
50#define ESAI_TFCR 0x10 47#define REG_ESAI_TSMB 0xE8
51#define ESAI_TFSR 0x14 48#define REG_ESAI_RSMA 0xEC
52#define ESAI_RFCR 0x18 49#define REG_ESAI_RSMB 0xF0
53#define ESAI_RFSR 0x1C 50#define REG_ESAI_xSMA(tx) (tx ? REG_ESAI_TSMA : REG_ESAI_RSMA)
54#define ESAI_TX0 0x80 51#define REG_ESAI_xSMB(tx) (tx ? REG_ESAI_TSMB : REG_ESAI_RSMB)
55#define ESAI_TX1 0x84 52#define REG_ESAI_PRRC 0xF8
56#define ESAI_TX2 0x88 53#define REG_ESAI_PCRC 0xFC
57#define ESAI_TX3 0x8C 54
58#define ESAI_TX4 0x90 55/* ESAI Control Register -- REG_ESAI_ECR 0x8 */
59#define ESAI_TX5 0x94 56#define ESAI_ECR_ETI_SHIFT 19
60#define ESAI_TSR 0x98 57#define ESAI_ECR_ETI_MASK (1 << ESAI_ECR_ETI_SHIFT)
61#define ESAI_RX0 0xA0 58#define ESAI_ECR_ETI (1 << ESAI_ECR_ETI_SHIFT)
62#define ESAI_RX1 0xA4 59#define ESAI_ECR_ETO_SHIFT 18
63#define ESAI_RX2 0xA8 60#define ESAI_ECR_ETO_MASK (1 << ESAI_ECR_ETO_SHIFT)
64#define ESAI_RX3 0xAC 61#define ESAI_ECR_ETO (1 << ESAI_ECR_ETO_SHIFT)
65#define ESAI_SAISR 0xCC 62#define ESAI_ECR_ERI_SHIFT 17
66#define ESAI_SAICR 0xD0 63#define ESAI_ECR_ERI_MASK (1 << ESAI_ECR_ERI_SHIFT)
67#define ESAI_TCR 0xD4 64#define ESAI_ECR_ERI (1 << ESAI_ECR_ERI_SHIFT)
68#define ESAI_TCCR 0xD8 65#define ESAI_ECR_ERO_SHIFT 16
69#define ESAI_RCR 0xDC 66#define ESAI_ECR_ERO_MASK (1 << ESAI_ECR_ERO_SHIFT)
70#define ESAI_RCCR 0xE0 67#define ESAI_ECR_ERO (1 << ESAI_ECR_ERO_SHIFT)
71#define ESAI_TSMA 0xE4 68#define ESAI_ECR_ERST_SHIFT 1
72#define ESAI_TSMB 0xE8 69#define ESAI_ECR_ERST_MASK (1 << ESAI_ECR_ERST_SHIFT)
73#define ESAI_RSMA 0xEC 70#define ESAI_ECR_ERST (1 << ESAI_ECR_ERST_SHIFT)
74#define ESAI_RSMB 0xF0 71#define ESAI_ECR_ESAIEN_SHIFT 0
75#define ESAI_PRRC 0xF8 72#define ESAI_ECR_ESAIEN_MASK (1 << ESAI_ECR_ESAIEN_SHIFT)
76#define ESAI_PCRC 0xFC 73#define ESAI_ECR_ESAIEN (1 << ESAI_ECR_ESAIEN_SHIFT)
77 74
78#define ESAI_ECR_ETI (1 << 19) 75/* ESAI Status Register -- REG_ESAI_ESR 0xC */
79#define ESAI_ECR_ETO (1 << 18) 76#define ESAI_ESR_TINIT_SHIFT 10
80#define ESAI_ECR_ERI (1 << 17) 77#define ESAI_ESR_TINIT_MASK (1 << ESAI_ESR_TINIT_SHIFT)
81#define ESAI_ECR_ERO (1 << 16) 78#define ESAI_ESR_TINIT (1 << ESAI_ESR_TINIT_SHIFT)
82#define ESAI_ECR_ERST (1 << 1) 79#define ESAI_ESR_RFF_SHIFT 9
83#define ESAI_ECR_ESAIEN (1 << 0) 80#define ESAI_ESR_RFF_MASK (1 << ESAI_ESR_RFF_SHIFT)
84 81#define ESAI_ESR_RFF (1 << ESAI_ESR_RFF_SHIFT)
85#define ESAI_ESR_TINIT (1 << 10) 82#define ESAI_ESR_TFE_SHIFT 8
86#define ESAI_ESR_RFF (1 << 9) 83#define ESAI_ESR_TFE_MASK (1 << ESAI_ESR_TFE_SHIFT)
87#define ESAI_ESR_TFE (1 << 8) 84#define ESAI_ESR_TFE (1 << ESAI_ESR_TFE_SHIFT)
88#define ESAI_ESR_TLS (1 << 7) 85#define ESAI_ESR_TLS_SHIFT 7
89#define ESAI_ESR_TDE (1 << 6) 86#define ESAI_ESR_TLS_MASK (1 << ESAI_ESR_TLS_SHIFT)
90#define ESAI_ESR_TED (1 << 5) 87#define ESAI_ESR_TLS (1 << ESAI_ESR_TLS_SHIFT)
91#define ESAI_ESR_TD (1 << 4) 88#define ESAI_ESR_TDE_SHIFT 6
92#define ESAI_ESR_RLS (1 << 3) 89#define ESAI_ESR_TDE_MASK (1 << ESAI_ESR_TDE_SHIFT)
93#define ESAI_ESR_RDE (1 << 2) 90#define ESAI_ESR_TDE (1 << ESAI_ESR_TDE_SHIFT)
94#define ESAI_ESR_RED (1 << 1) 91#define ESAI_ESR_TED_SHIFT 5
95#define ESAI_ESR_RD (1 << 0) 92#define ESAI_ESR_TED_MASK (1 << ESAI_ESR_TED_SHIFT)
96 93#define ESAI_ESR_TED (1 << ESAI_ESR_TED_SHIFT)
97#define ESAI_TFCR_TIEN (1 << 19) 94#define ESAI_ESR_TD_SHIFT 4
98#define ESAI_TFCR_TE5 (1 << 7) 95#define ESAI_ESR_TD_MASK (1 << ESAI_ESR_TD_SHIFT)
99#define ESAI_TFCR_TE4 (1 << 6) 96#define ESAI_ESR_TD (1 << ESAI_ESR_TD_SHIFT)
100#define ESAI_TFCR_TE3 (1 << 5) 97#define ESAI_ESR_RLS_SHIFT 3
101#define ESAI_TFCR_TE2 (1 << 4) 98#define ESAI_ESR_RLS_MASK (1 << ESAI_ESR_RLS_SHIFT)
102#define ESAI_TFCR_TE1 (1 << 3) 99#define ESAI_ESR_RLS (1 << ESAI_ESR_RLS_SHIFT)
103#define ESAI_TFCR_TE0 (1 << 2) 100#define ESAI_ESR_RDE_SHIFT 2
104#define ESAI_TFCR_TFR (1 << 1) 101#define ESAI_ESR_RDE_MASK (1 << ESAI_ESR_RDE_SHIFT)
105#define ESAI_TFCR_TFEN (1 << 0) 102#define ESAI_ESR_RDE (1 << ESAI_ESR_RDE_SHIFT)
106#define ESAI_TFCR_TE(x) ((0x3f >> (6 - ((x + 1) >> 1))) << 2) 103#define ESAI_ESR_RED_SHIFT 1
107#define ESAI_TFCR_TE_MASK 0xfff03 104#define ESAI_ESR_RED_MASK (1 << ESAI_ESR_RED_SHIFT)
108#define ESAI_TFCR_TFWM(x) ((x - 1) << 8) 105#define ESAI_ESR_RED (1 << ESAI_ESR_RED_SHIFT)
109#define ESAI_TFCR_TWA_MASK 0xf8ffff 106#define ESAI_ESR_RD_SHIFT 0
110 107#define ESAI_ESR_RD_MASK (1 << ESAI_ESR_RD_SHIFT)
111#define ESAI_RFCR_REXT (1 << 19) 108#define ESAI_ESR_RD (1 << ESAI_ESR_RD_SHIFT)
112#define ESAI_RFCR_RE3 (1 << 5)
113#define ESAI_RFCR_RE2 (1 << 4)
114#define ESAI_RFCR_RE1 (1 << 3)
115#define ESAI_RFCR_RE0 (1 << 2)
116#define ESAI_RFCR_RFR (1 << 1)
117#define ESAI_RFCR_RFEN (1 << 0)
118#define ESAI_RFCR_RE(x) ((0xf >> (4 - ((x + 1) >> 1))) << 2)
119#define ESAI_RFCR_RE_MASK 0xfffc3
120#define ESAI_RFCR_RFWM(x) ((x-1) << 8)
121#define ESAI_RFCR_RWA_MASK 0xf8ffff
122
123#define ESAI_WORD_LEN_32 (0x00 << 16)
124#define ESAI_WORD_LEN_28 (0x01 << 16)
125#define ESAI_WORD_LEN_24 (0x02 << 16)
126#define ESAI_WORD_LEN_20 (0x03 << 16)
127#define ESAI_WORD_LEN_16 (0x04 << 16)
128#define ESAI_WORD_LEN_12 (0x05 << 16)
129#define ESAI_WORD_LEN_8 (0x06 << 16)
130#define ESAI_WORD_LEN_4 (0x07 << 16)
131
132#define ESAI_SAISR_TODFE (1 << 17)
133#define ESAI_SAISR_TEDE (1 << 16)
134#define ESAI_SAISR_TDE (1 << 15)
135#define ESAI_SAISR_TUE (1 << 14)
136#define ESAI_SAISR_TFS (1 << 13)
137#define ESAI_SAISR_RODF (1 << 10)
138#define ESAI_SAISR_REDF (1 << 9)
139#define ESAI_SAISR_RDF (1 << 8)
140#define ESAI_SAISR_ROE (1 << 7)
141#define ESAI_SAISR_RFS (1 << 6)
142#define ESAI_SAISR_IF2 (1 << 2)
143#define ESAI_SAISR_IF1 (1 << 1)
144#define ESAI_SAISR_IF0 (1 << 0)
145
146#define ESAI_SAICR_ALC (1 << 8)
147#define ESAI_SAICR_TEBE (1 << 7)
148#define ESAI_SAICR_SYNC (1 << 6)
149#define ESAI_SAICR_OF2 (1 << 2)
150#define ESAI_SAICR_OF1 (1 << 1)
151#define ESAI_SAICR_OF0 (1 << 0)
152
153#define ESAI_TCR_TLIE (1 << 23)
154#define ESAI_TCR_TIE (1 << 22)
155#define ESAI_TCR_TEDIE (1 << 21)
156#define ESAI_TCR_TEIE (1 << 20)
157#define ESAI_TCR_TPR (1 << 19)
158#define ESAI_TCR_PADC (1 << 17)
159#define ESAI_TCR_TFSR (1 << 16)
160#define ESAI_TCR_TFSL (1 << 15)
161#define ESAI_TCR_TWA (1 << 7)
162#define ESAI_TCR_TSHFD_MSB (0 << 6)
163#define ESAI_TCR_TSHFD_LSB (1 << 6)
164#define ESAI_TCR_TE5 (1 << 5)
165#define ESAI_TCR_TE4 (1 << 4)
166#define ESAI_TCR_TE3 (1 << 3)
167#define ESAI_TCR_TE2 (1 << 2)
168#define ESAI_TCR_TE1 (1 << 1)
169#define ESAI_TCR_TE0 (1 << 0)
170#define ESAI_TCR_TE(x) (0x3f >> (6 - ((x + 1) >> 1)))
171
172#define ESAI_TCR_TSWS_MASK 0xff83ff
173#define ESAI_TCR_TSWS_STL8_WDL8 (0x00 << 10)
174#define ESAI_TCR_TSWS_STL12_WDL8 (0x04 << 10)
175#define ESAI_TCR_TSWS_STL12_WDL12 (0x01 << 10)
176#define ESAI_TCR_TSWS_STL16_WDL8 (0x08 << 10)
177#define ESAI_TCR_TSWS_STL16_WDL12 (0x05 << 10)
178#define ESAI_TCR_TSWS_STL16_WDL16 (0x02 << 10)
179#define ESAI_TCR_TSWS_STL20_WDL8 (0x0c << 10)
180#define ESAI_TCR_TSWS_STL20_WDL12 (0x09 << 10)
181#define ESAI_TCR_TSWS_STL20_WDL16 (0x06 << 10)
182#define ESAI_TCR_TSWS_STL20_WDL20 (0x03 << 10)
183#define ESAI_TCR_TSWS_STL24_WDL8 (0x10 << 10)
184#define ESAI_TCR_TSWS_STL24_WDL12 (0x0d << 10)
185#define ESAI_TCR_TSWS_STL24_WDL16 (0x0a << 10)
186#define ESAI_TCR_TSWS_STL24_WDL20 (0x07 << 10)
187#define ESAI_TCR_TSWS_STL24_WDL24 (0x1e << 10)
188#define ESAI_TCR_TSWS_STL32_WDL8 (0x18 << 10)
189#define ESAI_TCR_TSWS_STL32_WDL12 (0x15 << 10)
190#define ESAI_TCR_TSWS_STL32_WDL16 (0x12 << 10)
191#define ESAI_TCR_TSWS_STL32_WDL20 (0x0f << 10)
192#define ESAI_TCR_TSWS_STL32_WDL24 (0x1f << 10)
193
194#define ESAI_TCR_TMOD_MASK 0xfffcff
195#define ESAI_TCR_TMOD_NORMAL (0x00 << 8)
196#define ESAI_TCR_TMOD_ONDEMAND (0x01 << 8)
197#define ESAI_TCR_TMOD_NETWORK (0x01 << 8)
198#define ESAI_TCR_TMOD_RESERVED (0x02 << 8)
199#define ESAI_TCR_TMOD_AC97 (0x03 << 8)
200
201#define ESAI_TCCR_THCKD (1 << 23)
202#define ESAI_TCCR_TFSD (1 << 22)
203#define ESAI_TCCR_TCKD (1 << 21)
204#define ESAI_TCCR_THCKP (1 << 20)
205#define ESAI_TCCR_TFSP (1 << 19)
206#define ESAI_TCCR_TCKP (1 << 18)
207
208#define ESAI_TCCR_TPSR_MASK 0xfffeff
209#define ESAI_TCCR_TPSR_SHIFT 8
210#define ESAI_TCCR_TPSR_BYPASS (1 << 8)
211#define ESAI_TCCR_TPSR_DIV8 (0 << 8)
212
213#define ESAI_TCCR_TFP_MASK 0xfc3fff
214#define ESAI_TCCR_TFP_SHIFT 14
215#define ESAI_TCCR_TFP(x) ((x & 0xf) << 14)
216
217#define ESAI_TCCR_TDC_MASK 0xffc1ff
218#define ESAI_TCCR_TDC_SHIFT 9
219#define ESAI_TCCR_TDC(x) (((x) & 0x1f) << 9)
220
221#define ESAI_TCCR_TPM_MASK 0xffff00
222#define ESAI_TCCR_TPM_SHIFT 0
223#define ESAI_TCCR_TPM(x) (x & 0xff)
224 109
225#define ESAI_RCR_RLIE (1 << 23) 110/*
226#define ESAI_RCR_RIE (1 << 22) 111 * Transmit FIFO Configuration Register -- REG_ESAI_TFCR 0x10
227#define ESAI_RCR_REDIE (1 << 21) 112 * Receive FIFO Configuration Register -- REG_ESAI_RFCR 0x18
228#define ESAI_RCR_REIE (1 << 20) 113 */
229#define ESAI_RCR_RPR (1 << 19) 114#define ESAI_xFCR_TIEN_SHIFT 19
230#define ESAI_RCR_RFSR (1 << 16) 115#define ESAI_xFCR_TIEN_MASK (1 << ESAI_xFCR_TIEN_SHIFT)
231#define ESAI_RCR_RFSL (1 << 15) 116#define ESAI_xFCR_TIEN (1 << ESAI_xFCR_TIEN_SHIFT)
232#define ESAI_RCR_RWA (1 << 7) 117#define ESAI_xFCR_REXT_SHIFT 19
233#define ESAI_RCR_RSHFD_MSB (0 << 6) 118#define ESAI_xFCR_REXT_MASK (1 << ESAI_xFCR_REXT_SHIFT)
234#define ESAI_RCR_RSHFD_LSB (1 << 6) 119#define ESAI_xFCR_REXT (1 << ESAI_xFCR_REXT_SHIFT)
235#define ESAI_RCR_RE3 (1 << 3) 120#define ESAI_xFCR_xWA_SHIFT 16
236#define ESAI_RCR_RE2 (1 << 2) 121#define ESAI_xFCR_xWA_WIDTH 3
237#define ESAI_RCR_RE1 (1 << 1) 122#define ESAI_xFCR_xWA_MASK (((1 << ESAI_xFCR_xWA_WIDTH) - 1) << ESAI_xFCR_xWA_SHIFT)
238#define ESAI_RCR_RE0 (1 << 0) 123#define ESAI_xFCR_xWA(v) (((8 - ((v) >> 2)) << ESAI_xFCR_xWA_SHIFT) & ESAI_xFCR_xWA_MASK)
239#define ESAI_RCR_RE(x) (0xf >> (4 - ((x + 1) >> 1))) 124#define ESAI_xFCR_xFWM_SHIFT 8
240 125#define ESAI_xFCR_xFWM_WIDTH 8
241#define ESAI_RCR_RSWS_MASK 0xff83ff 126#define ESAI_xFCR_xFWM_MASK (((1 << ESAI_xFCR_xFWM_WIDTH) - 1) << ESAI_xFCR_xFWM_SHIFT)
242#define ESAI_RCR_RSWS_STL8_WDL8 (0x00 << 10) 127#define ESAI_xFCR_xFWM(v) ((((v) - 1) << ESAI_xFCR_xFWM_SHIFT) & ESAI_xFCR_xFWM_MASK)
243#define ESAI_RCR_RSWS_STL12_WDL8 (0x04 << 10) 128#define ESAI_xFCR_xE_SHIFT 2
244#define ESAI_RCR_RSWS_STL12_WDL12 (0x01 << 10) 129#define ESAI_xFCR_TE_WIDTH 6
245#define ESAI_RCR_RSWS_STL16_WDL8 (0x08 << 10) 130#define ESAI_xFCR_RE_WIDTH 4
246#define ESAI_RCR_RSWS_STL16_WDL12 (0x05 << 10) 131#define ESAI_xFCR_TE_MASK (((1 << ESAI_xFCR_TE_WIDTH) - 1) << ESAI_xFCR_xE_SHIFT)
247#define ESAI_RCR_RSWS_STL16_WDL16 (0x02 << 10) 132#define ESAI_xFCR_RE_MASK (((1 << ESAI_xFCR_RE_WIDTH) - 1) << ESAI_xFCR_xE_SHIFT)
248#define ESAI_RCR_RSWS_STL20_WDL8 (0x0c << 10) 133#define ESAI_xFCR_TE(x) ((ESAI_xFCR_TE_MASK >> (ESAI_xFCR_TE_WIDTH - ((x + 1) >> 1))) & ESAI_xFCR_TE_MASK)
249#define ESAI_RCR_RSWS_STL20_WDL12 (0x09 << 10) 134#define ESAI_xFCR_RE(x) ((ESAI_xFCR_RE_MASK >> (ESAI_xFCR_RE_WIDTH - ((x + 1) >> 1))) & ESAI_xFCR_RE_MASK)
250#define ESAI_RCR_RSWS_STL20_WDL16 (0x06 << 10) 135#define ESAI_xFCR_xFR_SHIFT 1
251#define ESAI_RCR_RSWS_STL20_WDL20 (0x03 << 10) 136#define ESAI_xFCR_xFR_MASK (1 << ESAI_xFCR_xFR_SHIFT)
252#define ESAI_RCR_RSWS_STL24_WDL8 (0x10 << 10) 137#define ESAI_xFCR_xFR (1 << ESAI_xFCR_xFR_SHIFT)
253#define ESAI_RCR_RSWS_STL24_WDL12 (0x0d << 10) 138#define ESAI_xFCR_xFEN_SHIFT 0
254#define ESAI_RCR_RSWS_STL24_WDL16 (0x0a << 10) 139#define ESAI_xFCR_xFEN_MASK (1 << ESAI_xFCR_xFEN_SHIFT)
255#define ESAI_RCR_RSWS_STL24_WDL20 (0x07 << 10) 140#define ESAI_xFCR_xFEN (1 << ESAI_xFCR_xFEN_SHIFT)
256#define ESAI_RCR_RSWS_STL24_WDL24 (0x1e << 10)
257#define ESAI_RCR_RSWS_STL32_WDL8 (0x18 << 10)
258#define ESAI_RCR_RSWS_STL32_WDL12 (0x15 << 10)
259#define ESAI_RCR_RSWS_STL32_WDL16 (0x12 << 10)
260#define ESAI_RCR_RSWS_STL32_WDL20 (0x0f << 10)
261#define ESAI_RCR_RSWS_STL32_WDL24 (0x1f << 10)
262
263#define ESAI_RCR_RMOD_MASK 0xfffcff
264#define ESAI_RCR_RMOD_NORMAL (0x00 << 8)
265#define ESAI_RCR_RMOD_ONDEMAND (0x01 << 8)
266#define ESAI_RCR_RMOD_NETWORK (0x01 << 8)
267#define ESAI_RCR_RMOD_RESERVED (0x02 << 8)
268#define ESAI_RCR_RMOD_AC97 (0x03 << 8)
269
270#define ESAI_RCCR_RHCKD (1 << 23)
271#define ESAI_RCCR_RFSD (1 << 22)
272#define ESAI_RCCR_RCKD (1 << 21)
273#define ESAI_RCCR_RHCKP (1 << 20)
274#define ESAI_RCCR_RFSP (1 << 19)
275#define ESAI_RCCR_RCKP (1 << 18)
276
277#define ESAI_RCCR_RPSR_MASK 0xfffeff
278#define ESAI_RCCR_RPSR_SHIFT 8
279#define ESAI_RCCR_RPSR_BYPASS (1 << 8)
280#define ESAI_RCCR_RPSR_DIV8 (0 << 8)
281
282#define ESAI_RCCR_RFP_MASK 0xfc3fff
283#define ESAI_RCCR_RFP_SHIFT 14
284#define ESAI_RCCR_RFP(x) ((x & 0xf) << 14)
285 141
286#define ESAI_RCCR_RDC_MASK 0xffc1ff 142/*
287#define ESAI_RCCR_RDC_SHIFT 9 143 * Transmit FIFO Status Register -- REG_ESAI_TFSR 0x14
288#define ESAI_RCCR_RDC(x) (((x) & 0x1f) << 9) 144 * Receive FIFO Status Register --REG_ESAI_RFSR 0x1C
145 */
146#define ESAI_xFSR_NTFO_SHIFT 12
147#define ESAI_xFSR_NRFI_SHIFT 12
148#define ESAI_xFSR_NTFI_SHIFT 8
149#define ESAI_xFSR_NRFO_SHIFT 8
150#define ESAI_xFSR_NTFx_WIDTH 3
151#define ESAI_xFSR_NRFx_WIDTH 2
152#define ESAI_xFSR_NTFO_MASK (((1 << ESAI_xFSR_NTFx_WIDTH) - 1) << ESAI_xFSR_NTFO_SHIFT)
153#define ESAI_xFSR_NTFI_MASK (((1 << ESAI_xFSR_NTFx_WIDTH) - 1) << ESAI_xFSR_NTFI_SHIFT)
154#define ESAI_xFSR_NRFO_MASK (((1 << ESAI_xFSR_NRFx_WIDTH) - 1) << ESAI_xFSR_NRFO_SHIFT)
155#define ESAI_xFSR_NRFI_MASK (((1 << ESAI_xFSR_NRFx_WIDTH) - 1) << ESAI_xFSR_NRFI_SHIFT)
156#define ESAI_xFSR_xFCNT_SHIFT 0
157#define ESAI_xFSR_xFCNT_WIDTH 8
158#define ESAI_xFSR_xFCNT_MASK (((1 << ESAI_xFSR_xFCNT_WIDTH) - 1) << ESAI_xFSR_xFCNT_SHIFT)
159
160/* ESAI Transmit Slot Register -- REG_ESAI_TSR 0x98 */
161#define ESAI_TSR_SHIFT 0
162#define ESAI_TSR_WIDTH 24
163#define ESAI_TSR_MASK (((1 << ESAI_TSR_WIDTH) - 1) << ESAI_TSR_SHIFT)
164
165/* Serial Audio Interface Status Register -- REG_ESAI_SAISR 0xCC */
166#define ESAI_SAISR_TODFE_SHIFT 17
167#define ESAI_SAISR_TODFE_MASK (1 << ESAI_SAISR_TODFE_SHIFT)
168#define ESAI_SAISR_TODFE (1 << ESAI_SAISR_TODFE_SHIFT)
169#define ESAI_SAISR_TEDE_SHIFT 16
170#define ESAI_SAISR_TEDE_MASK (1 << ESAI_SAISR_TEDE_SHIFT)
171#define ESAI_SAISR_TEDE (1 << ESAI_SAISR_TEDE_SHIFT)
172#define ESAI_SAISR_TDE_SHIFT 15
173#define ESAI_SAISR_TDE_MASK (1 << ESAI_SAISR_TDE_SHIFT)
174#define ESAI_SAISR_TDE (1 << ESAI_SAISR_TDE_SHIFT)
175#define ESAI_SAISR_TUE_SHIFT 14
176#define ESAI_SAISR_TUE_MASK (1 << ESAI_SAISR_TUE_SHIFT)
177#define ESAI_SAISR_TUE (1 << ESAI_SAISR_TUE_SHIFT)
178#define ESAI_SAISR_TFS_SHIFT 13
179#define ESAI_SAISR_TFS_MASK (1 << ESAI_SAISR_TFS_SHIFT)
180#define ESAI_SAISR_TFS (1 << ESAI_SAISR_TFS_SHIFT)
181#define ESAI_SAISR_RODF_SHIFT 10
182#define ESAI_SAISR_RODF_MASK (1 << ESAI_SAISR_RODF_SHIFT)
183#define ESAI_SAISR_RODF (1 << ESAI_SAISR_RODF_SHIFT)
184#define ESAI_SAISR_REDF_SHIFT 9
185#define ESAI_SAISR_REDF_MASK (1 << ESAI_SAISR_REDF_SHIFT)
186#define ESAI_SAISR_REDF (1 << ESAI_SAISR_REDF_SHIFT)
187#define ESAI_SAISR_RDF_SHIFT 8
188#define ESAI_SAISR_RDF_MASK (1 << ESAI_SAISR_RDF_SHIFT)
189#define ESAI_SAISR_RDF (1 << ESAI_SAISR_RDF_SHIFT)
190#define ESAI_SAISR_ROE_SHIFT 7
191#define ESAI_SAISR_ROE_MASK (1 << ESAI_SAISR_ROE_SHIFT)
192#define ESAI_SAISR_ROE (1 << ESAI_SAISR_ROE_SHIFT)
193#define ESAI_SAISR_RFS_SHIFT 6
194#define ESAI_SAISR_RFS_MASK (1 << ESAI_SAISR_RFS_SHIFT)
195#define ESAI_SAISR_RFS (1 << ESAI_SAISR_RFS_SHIFT)
196#define ESAI_SAISR_IF2_SHIFT 2
197#define ESAI_SAISR_IF2_MASK (1 << ESAI_SAISR_IF2_SHIFT)
198#define ESAI_SAISR_IF2 (1 << ESAI_SAISR_IF2_SHIFT)
199#define ESAI_SAISR_IF1_SHIFT 1
200#define ESAI_SAISR_IF1_MASK (1 << ESAI_SAISR_IF1_SHIFT)
201#define ESAI_SAISR_IF1 (1 << ESAI_SAISR_IF1_SHIFT)
202#define ESAI_SAISR_IF0_SHIFT 0
203#define ESAI_SAISR_IF0_MASK (1 << ESAI_SAISR_IF0_SHIFT)
204#define ESAI_SAISR_IF0 (1 << ESAI_SAISR_IF0_SHIFT)
205
206/* Serial Audio Interface Control Register -- REG_ESAI_SAICR 0xD0 */
207#define ESAI_SAICR_ALC_SHIFT 8
208#define ESAI_SAICR_ALC_MASK (1 << ESAI_SAICR_ALC_SHIFT)
209#define ESAI_SAICR_ALC (1 << ESAI_SAICR_ALC_SHIFT)
210#define ESAI_SAICR_TEBE_SHIFT 7
211#define ESAI_SAICR_TEBE_MASK (1 << ESAI_SAICR_TEBE_SHIFT)
212#define ESAI_SAICR_TEBE (1 << ESAI_SAICR_TEBE_SHIFT)
213#define ESAI_SAICR_SYNC_SHIFT 6
214#define ESAI_SAICR_SYNC_MASK (1 << ESAI_SAICR_SYNC_SHIFT)
215#define ESAI_SAICR_SYNC (1 << ESAI_SAICR_SYNC_SHIFT)
216#define ESAI_SAICR_OF2_SHIFT 2
217#define ESAI_SAICR_OF2_MASK (1 << ESAI_SAICR_OF2_SHIFT)
218#define ESAI_SAICR_OF2 (1 << ESAI_SAICR_OF2_SHIFT)
219#define ESAI_SAICR_OF1_SHIFT 1
220#define ESAI_SAICR_OF1_MASK (1 << ESAI_SAICR_OF1_SHIFT)
221#define ESAI_SAICR_OF1 (1 << ESAI_SAICR_OF1_SHIFT)
222#define ESAI_SAICR_OF0_SHIFT 0
223#define ESAI_SAICR_OF0_MASK (1 << ESAI_SAICR_OF0_SHIFT)
224#define ESAI_SAICR_OF0 (1 << ESAI_SAICR_OF0_SHIFT)
289 225
290#define ESAI_RCCR_RPM_MASK 0xffff00 226/*
291#define ESAI_RCCR_RPM_SHIFT 0 227 * Transmit Control Register -- REG_ESAI_TCR 0xD4
292#define ESAI_RCCR_RPM(x) (x & 0xff) 228 * Receive Control Register -- REG_ESAI_RCR 0xDC
229 */
230#define ESAI_xCR_xLIE_SHIFT 23
231#define ESAI_xCR_xLIE_MASK (1 << ESAI_xCR_xLIE_SHIFT)
232#define ESAI_xCR_xLIE (1 << ESAI_xCR_xLIE_SHIFT)
233#define ESAI_xCR_xIE_SHIFT 22
234#define ESAI_xCR_xIE_MASK (1 << ESAI_xCR_xIE_SHIFT)
235#define ESAI_xCR_xIE (1 << ESAI_xCR_xIE_SHIFT)
236#define ESAI_xCR_xEDIE_SHIFT 21
237#define ESAI_xCR_xEDIE_MASK (1 << ESAI_xCR_xEDIE_SHIFT)
238#define ESAI_xCR_xEDIE (1 << ESAI_xCR_xEDIE_SHIFT)
239#define ESAI_xCR_xEIE_SHIFT 20
240#define ESAI_xCR_xEIE_MASK (1 << ESAI_xCR_xEIE_SHIFT)
241#define ESAI_xCR_xEIE (1 << ESAI_xCR_xEIE_SHIFT)
242#define ESAI_xCR_xPR_SHIFT 19
243#define ESAI_xCR_xPR_MASK (1 << ESAI_xCR_xPR_SHIFT)
244#define ESAI_xCR_xPR (1 << ESAI_xCR_xPR_SHIFT)
245#define ESAI_xCR_PADC_SHIFT 17
246#define ESAI_xCR_PADC_MASK (1 << ESAI_xCR_PADC_SHIFT)
247#define ESAI_xCR_PADC (1 << ESAI_xCR_PADC_SHIFT)
248#define ESAI_xCR_xFSR_SHIFT 16
249#define ESAI_xCR_xFSR_MASK (1 << ESAI_xCR_xFSR_SHIFT)
250#define ESAI_xCR_xFSR (1 << ESAI_xCR_xFSR_SHIFT)
251#define ESAI_xCR_xFSL_SHIFT 15
252#define ESAI_xCR_xFSL_MASK (1 << ESAI_xCR_xFSL_SHIFT)
253#define ESAI_xCR_xFSL (1 << ESAI_xCR_xFSL_SHIFT)
254#define ESAI_xCR_xSWS_SHIFT 10
255#define ESAI_xCR_xSWS_WIDTH 5
256#define ESAI_xCR_xSWS_MASK (((1 << ESAI_xCR_xSWS_WIDTH) - 1) << ESAI_xCR_xSWS_SHIFT)
257#define ESAI_xCR_xSWS(s, w) ((w < 24 ? (s - w + ((w - 8) >> 2)) : (s < 32 ? 0x1e : 0x1f)) << ESAI_xCR_xSWS_SHIFT)
258#define ESAI_xCR_xMOD_SHIFT 8
259#define ESAI_xCR_xMOD_WIDTH 2
260#define ESAI_xCR_xMOD_MASK (((1 << ESAI_xCR_xMOD_WIDTH) - 1) << ESAI_xCR_xMOD_SHIFT)
261#define ESAI_xCR_xMOD_ONDEMAND (0x1 << ESAI_xCR_xMOD_SHIFT)
262#define ESAI_xCR_xMOD_NETWORK (0x1 << ESAI_xCR_xMOD_SHIFT)
263#define ESAI_xCR_xMOD_AC97 (0x3 << ESAI_xCR_xMOD_SHIFT)
264#define ESAI_xCR_xWA_SHIFT 7
265#define ESAI_xCR_xWA_MASK (1 << ESAI_xCR_xWA_SHIFT)
266#define ESAI_xCR_xWA (1 << ESAI_xCR_xWA_SHIFT)
267#define ESAI_xCR_xSHFD_SHIFT 6
268#define ESAI_xCR_xSHFD_MASK (1 << ESAI_xCR_xSHFD_SHIFT)
269#define ESAI_xCR_xSHFD (1 << ESAI_xCR_xSHFD_SHIFT)
270#define ESAI_xCR_xE_SHIFT 0
271#define ESAI_xCR_TE_WIDTH 6
272#define ESAI_xCR_RE_WIDTH 4
273#define ESAI_xCR_TE_MASK (((1 << ESAI_xCR_TE_WIDTH) - 1) << ESAI_xCR_xE_SHIFT)
274#define ESAI_xCR_RE_MASK (((1 << ESAI_xCR_RE_WIDTH) - 1) << ESAI_xCR_xE_SHIFT)
275#define ESAI_xCR_TE(x) ((ESAI_xCR_TE_MASK >> (ESAI_xCR_TE_WIDTH - ((x + 1) >> 1))) & ESAI_xCR_TE_MASK)
276#define ESAI_xCR_RE(x) ((ESAI_xCR_RE_MASK >> (ESAI_xCR_RE_WIDTH - ((x + 1) >> 1))) & ESAI_xCR_RE_MASK)
293 277
294#define ESAI_GPIO_ESAI 0xfff 278/*
279 * Transmit Clock Control Register -- REG_ESAI_TCCR 0xD8
280 * Receive Clock Control Register -- REG_ESAI_RCCR 0xE0
281 */
282#define ESAI_xCCR_xHCKD_SHIFT 23
283#define ESAI_xCCR_xHCKD_MASK (1 << ESAI_xCCR_xHCKD_SHIFT)
284#define ESAI_xCCR_xHCKD (1 << ESAI_xCCR_xHCKD_SHIFT)
285#define ESAI_xCCR_xFSD_SHIFT 22
286#define ESAI_xCCR_xFSD_MASK (1 << ESAI_xCCR_xFSD_SHIFT)
287#define ESAI_xCCR_xFSD (1 << ESAI_xCCR_xFSD_SHIFT)
288#define ESAI_xCCR_xCKD_SHIFT 21
289#define ESAI_xCCR_xCKD_MASK (1 << ESAI_xCCR_xCKD_SHIFT)
290#define ESAI_xCCR_xCKD (1 << ESAI_xCCR_xCKD_SHIFT)
291#define ESAI_xCCR_xHCKP_SHIFT 20
292#define ESAI_xCCR_xHCKP_MASK (1 << ESAI_xCCR_xHCKP_SHIFT)
293#define ESAI_xCCR_xHCKP (1 << ESAI_xCCR_xHCKP_SHIFT)
294#define ESAI_xCCR_xFSP_SHIFT 19
295#define ESAI_xCCR_xFSP_MASK (1 << ESAI_xCCR_xFSP_SHIFT)
296#define ESAI_xCCR_xFSP (1 << ESAI_xCCR_xFSP_SHIFT)
297#define ESAI_xCCR_xCKP_SHIFT 18
298#define ESAI_xCCR_xCKP_MASK (1 << ESAI_xCCR_xCKP_SHIFT)
299#define ESAI_xCCR_xCKP (1 << ESAI_xCCR_xCKP_SHIFT)
300#define ESAI_xCCR_xFP_SHIFT 14
301#define ESAI_xCCR_xFP_WIDTH 4
302#define ESAI_xCCR_xFP_MASK (((1 << ESAI_xCCR_xFP_WIDTH) - 1) << ESAI_xCCR_xFP_SHIFT)
303#define ESAI_xCCR_xFP(v) ((((v) - 1) << ESAI_xCCR_xFP_SHIFT) & ESAI_xCCR_xFP_MASK)
304#define ESAI_xCCR_xDC_SHIFT 9
305#define ESAI_xCCR_xDC_WIDTH 4
306#define ESAI_xCCR_xDC_MASK (((1 << ESAI_xCCR_xDC_WIDTH) - 1) << ESAI_xCCR_xDC_SHIFT)
307#define ESAI_xCCR_xDC(v) ((((v) - 1) << ESAI_xCCR_xDC_SHIFT) & ESAI_xCCR_xDC_MASK)
308#define ESAI_xCCR_xPSR_SHIFT 8
309#define ESAI_xCCR_xPSR_MASK (1 << ESAI_xCCR_xPSR_SHIFT)
310#define ESAI_xCCR_xPSR_BYPASS (1 << ESAI_xCCR_xPSR_SHIFT)
311#define ESAI_xCCR_xPSR_DIV8 (0 << ESAI_xCCR_xPSR_SHIFT)
312#define ESAI_xCCR_xPM_SHIFT 0
313#define ESAI_xCCR_xPM_WIDTH 8
314#define ESAI_xCCR_xPM_MASK (((1 << ESAI_xCCR_xPM_WIDTH) - 1) << ESAI_xCCR_xPM_SHIFT)
315#define ESAI_xCCR_xPM(v) ((((v) - 1) << ESAI_xCCR_xPM_SHIFT) & ESAI_xCCR_xPM_MASK)
316
317/* Transmit Slot Mask Register A/B -- REG_ESAI_TSMA/B 0xE4 ~ 0xF0 */
318#define ESAI_xSMA_xS_SHIFT 0
319#define ESAI_xSMA_xS_WIDTH 16
320#define ESAI_xSMA_xS_MASK (((1 << ESAI_xSMA_xS_WIDTH) - 1) << ESAI_xSMA_xS_SHIFT)
321#define ESAI_xSMA_xS(v) ((v) & ESAI_xSMA_xS_MASK)
322#define ESAI_xSMB_xS_SHIFT 0
323#define ESAI_xSMB_xS_WIDTH 16
324#define ESAI_xSMB_xS_MASK (((1 << ESAI_xSMB_xS_WIDTH) - 1) << ESAI_xSMB_xS_SHIFT)
325#define ESAI_xSMB_xS(v) (((v) >> ESAI_xSMA_xS_WIDTH) & ESAI_xSMA_xS_MASK)
326
327/* Port C Direction Register -- REG_ESAI_PRRC 0xF8 */
328#define ESAI_PRRC_PDC_SHIFT 0
329#define ESAI_PRRC_PDC_WIDTH 12
330#define ESAI_PRRC_PDC_MASK (((1 << ESAI_PRRC_PDC_WIDTH) - 1) << ESAI_PRRC_PDC_SHIFT)
331#define ESAI_PRRC_PDC(v) ((v) & ESAI_PRRC_PDC_MASK)
332
333/* Port C Control Register -- REG_ESAI_PCRC 0xFC */
334#define ESAI_PCRC_PC_SHIFT 0
335#define ESAI_PCRC_PC_WIDTH 12
336#define ESAI_PCRC_PC_MASK (((1 << ESAI_PCRC_PC_WIDTH) - 1) << ESAI_PCRC_PC_SHIFT)
337#define ESAI_PCRC_PC(v) ((v) & ESAI_PCRC_PC_MASK)
338
339#define ESAI_GPIO 0xfff
295 340
296/* ESAI clock source */ 341/* ESAI clock source */
297#define ESAI_CLK_FSYS 0 342#define ESAI_HCKT_FSYS 0
298#define ESAI_CLK_EXTAL 1 343#define ESAI_HCKT_EXTAL 1
299#define ESAI_CLK_EXTAL_DIV 2 344#define ESAI_HCKR_FSYS 2
345#define ESAI_HCKR_EXTAL 3
300 346
301/* ESAI clock divider */ 347/* ESAI clock divider */
302#define ESAI_TX_DIV_PSR 0 348#define ESAI_TX_DIV_PSR 0
303#define ESAI_TX_DIV_PM 1 349#define ESAI_TX_DIV_PM 1
304#define ESAI_TX_DIV_FP 2 350#define ESAI_TX_DIV_FP 2
305#define ESAI_RX_DIV_PSR 3 351#define ESAI_RX_DIV_PSR 3
306#define ESAI_RX_DIV_PM 4 352#define ESAI_RX_DIV_PM 4
307#define ESAI_RX_DIV_FP 5 353#define ESAI_RX_DIV_FP 5
308 354#endif /* _FSL_ESAI_DAI_H */
309#define DRV_NAME "imx-esai"
310
311#include <linux/dmaengine.h>
312#include <sound/dmaengine_pcm.h>
313#include <linux/platform_data/dma-imx.h>
314
315#define IMX_DAI_ESAI_TX 0x04
316#define IMX_DAI_ESAI_RX 0x08
317#define IMX_DAI_ESAI_TXRX (IMX_DAI_ESAI_TX | IMX_DAI_ESAI_RX)
318#define REG_CACHE_NUM 20
319
320struct fsl_esai {
321 struct clk *clk;
322 struct clk *dmaclk;
323 struct clk *extalclk;
324 void __iomem *base;
325 int irq;
326 unsigned int flags;
327 unsigned int fifo_depth;
328
329 struct snd_dmaengine_dai_dma_data dma_params_rx;
330 struct snd_dmaengine_dai_dma_data dma_params_tx;
331 struct imx_dma_data filter_data_tx;
332 struct imx_dma_data filter_data_rx;
333 struct snd_pcm_substream *substream[2];
334
335 char name[32];
336 u32 reg_cache[REG_CACHE_NUM];
337};
338
339#endif
diff --git a/sound/soc/fsl/imx-cs42888.c b/sound/soc/fsl/imx-cs42888.c
index a56f4f1984ed..f625cd609853 100644
--- a/sound/soc/fsl/imx-cs42888.c
+++ b/sound/soc/fsl/imx-cs42888.c
@@ -33,7 +33,6 @@
33#define CODEC_CLK_ESAI_HCKT 2 33#define CODEC_CLK_ESAI_HCKT 2
34 34
35struct imx_priv { 35struct imx_priv {
36 int hw;
37 int fe_p2p_rate; 36 int fe_p2p_rate;
38 int fe_p2p_width; 37 int fe_p2p_width;
39 unsigned int mclk_freq; 38 unsigned int mclk_freq;
@@ -43,43 +42,6 @@ struct imx_priv {
43 42
44static struct imx_priv card_priv; 43static struct imx_priv card_priv;
45 44
46static int imx_cs42888_startup(struct snd_pcm_substream *substream)
47{
48 struct snd_soc_pcm_runtime *rtd = substream->private_data;
49 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
50 struct imx_priv *priv = &card_priv;
51
52 if (!cpu_dai->active)
53 priv->hw = 0;
54 return 0;
55}
56
57static void imx_cs42888_shutdown(struct snd_pcm_substream *substream)
58{
59 struct snd_soc_pcm_runtime *rtd = substream->private_data;
60 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
61 struct imx_priv *priv = &card_priv;
62
63 if (!cpu_dai->active)
64 priv->hw = 0;
65}
66
67static const struct {
68 int rate;
69 int ratio1;
70 int ratio2;
71} sr_vals[] = {
72 { 32000, 3, 3 },
73 { 48000, 3, 3 },
74 { 64000, 1, 1 },
75 { 96000, 1, 1 },
76 { 128000, 1, 1 },
77 { 44100, 3, 3 },
78 { 88200, 1, 1 },
79 { 176400, 0, 0 },
80 { 192000, 0, 0 },
81};
82
83static int imx_cs42888_surround_hw_params(struct snd_pcm_substream *substream, 45static int imx_cs42888_surround_hw_params(struct snd_pcm_substream *substream,
84 struct snd_pcm_hw_params *params) 46 struct snd_pcm_hw_params *params)
85{ 47{
@@ -87,47 +49,22 @@ static int imx_cs42888_surround_hw_params(struct snd_pcm_substream *substream,
87 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 49 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
88 struct snd_soc_dai *codec_dai = rtd->codec_dai; 50 struct snd_soc_dai *codec_dai = rtd->codec_dai;
89 struct imx_priv *priv = &card_priv; 51 struct imx_priv *priv = &card_priv;
90 unsigned int rate = params_rate(params);
91 unsigned int lrclk_ratio = 0, i;
92 u32 dai_format = 0; 52 u32 dai_format = 0;
93 53
94 if (priv->hw)
95 return 0;
96
97 priv->hw = 1;
98
99 for (i = 0; i < ARRAY_SIZE(sr_vals); i++) {
100 if (sr_vals[i].rate == rate) {
101 if (priv->codec_mclk & CODEC_CLK_ESAI_HCKT)
102 lrclk_ratio = sr_vals[i].ratio1;
103 if (priv->codec_mclk & CODEC_CLK_EXTER_OSC)
104 lrclk_ratio = sr_vals[i].ratio2;
105 break;
106 }
107 }
108 if (i == ARRAY_SIZE(sr_vals)) {
109 dev_err(&priv->pdev->dev, "Unsupported rate %dHz\n", rate);
110 return -EINVAL;
111 }
112
113 dai_format = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | 54 dai_format = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF |
114 SND_SOC_DAIFMT_CBS_CFS; 55 SND_SOC_DAIFMT_CBS_CFS;
115 56 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
116 snd_soc_dai_set_sysclk(cpu_dai, ESAI_CLK_EXTAL, 57 snd_soc_dai_set_sysclk(cpu_dai, ESAI_HCKT_EXTAL,
58 priv->mclk_freq, SND_SOC_CLOCK_OUT);
59 else
60 snd_soc_dai_set_sysclk(cpu_dai, ESAI_HCKR_EXTAL,
117 priv->mclk_freq, SND_SOC_CLOCK_OUT); 61 priv->mclk_freq, SND_SOC_CLOCK_OUT);
118 snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PM, 0);
119 snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PM, 0);
120 snd_soc_dai_set_sysclk(codec_dai, 0, priv->mclk_freq, SND_SOC_CLOCK_IN); 62 snd_soc_dai_set_sysclk(codec_dai, 0, priv->mclk_freq, SND_SOC_CLOCK_IN);
121 63
122 /* set cpu DAI configuration */ 64 /* set cpu DAI configuration */
123 snd_soc_dai_set_fmt(cpu_dai, dai_format); 65 snd_soc_dai_set_fmt(cpu_dai, dai_format);
124 /* set i.MX active slot mask */ 66 /* set i.MX active slot mask */
125 snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32); 67 snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32);
126 /* set the ratio */
127 snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PSR, 1);
128 snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_FP, lrclk_ratio);
129 snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PSR, 1);
130 snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_FP, lrclk_ratio);
131 68
132 /* set codec DAI configuration */ 69 /* set codec DAI configuration */
133 snd_soc_dai_set_fmt(codec_dai, dai_format); 70 snd_soc_dai_set_fmt(codec_dai, dai_format);
@@ -135,8 +72,6 @@ static int imx_cs42888_surround_hw_params(struct snd_pcm_substream *substream,
135} 72}
136 73
137static struct snd_soc_ops imx_cs42888_surround_ops = { 74static struct snd_soc_ops imx_cs42888_surround_ops = {
138 .startup = imx_cs42888_startup,
139 .shutdown = imx_cs42888_shutdown,
140 .hw_params = imx_cs42888_surround_hw_params, 75 .hw_params = imx_cs42888_surround_hw_params,
141}; 76};
142 77