]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - sound/soc/fsl/fsl_esai.c
iommu/exynos: Fix checkpatch warning
[karo-tx-linux.git] / sound / soc / fsl / fsl_esai.c
1 /*
2  * Freescale ESAI ALSA SoC Digital Audio Interface (DAI) driver
3  *
4  * Copyright (C) 2014 Freescale Semiconductor, Inc.
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.
9  */
10
11 #include <linux/clk.h>
12 #include <linux/dmaengine.h>
13 #include <linux/module.h>
14 #include <linux/of_irq.h>
15 #include <linux/of_platform.h>
16 #include <sound/dmaengine_pcm.h>
17 #include <sound/pcm_params.h>
18
19 #include "fsl_esai.h"
20 #include "imx-pcm.h"
21 #include "fsl_utils.h"
22
23 #define FSL_ESAI_RATES          SNDRV_PCM_RATE_8000_192000
24 #define FSL_ESAI_FORMATS        (SNDRV_PCM_FMTBIT_S8 | \
25                                 SNDRV_PCM_FMTBIT_S16_LE | \
26                                 SNDRV_PCM_FMTBIT_S20_3LE | \
27                                 SNDRV_PCM_FMTBIT_S24_LE)
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  */
47 struct fsl_esai {
48         struct snd_dmaengine_dai_dma_data dma_params_rx;
49         struct snd_dmaengine_dai_dma_data dma_params_tx;
50         struct platform_device *pdev;
51         struct regmap *regmap;
52         struct clk *coreclk;
53         struct clk *extalclk;
54         struct clk *fsysclk;
55         u32 fifo_depth;
56         u32 slot_width;
57         u32 hck_rate[2];
58         bool sck_div[2];
59         bool slave_mode;
60         bool synchronous;
61         char name[32];
62 };
63
64 static irqreturn_t esai_isr(int irq, void *devid)
65 {
66         struct fsl_esai *esai_priv = (struct fsl_esai *)devid;
67         struct platform_device *pdev = esai_priv->pdev;
68         u32 esr;
69
70         regmap_read(esai_priv->regmap, REG_ESAI_ESR, &esr);
71
72         if (esr & ESAI_ESR_TINIT_MASK)
73                 dev_dbg(&pdev->dev, "isr: Transmition Initialized\n");
74
75         if (esr & ESAI_ESR_RFF_MASK)
76                 dev_warn(&pdev->dev, "isr: Receiving overrun\n");
77
78         if (esr & ESAI_ESR_TFE_MASK)
79                 dev_warn(&pdev->dev, "isr: Transmition underrun\n");
80
81         if (esr & ESAI_ESR_TLS_MASK)
82                 dev_dbg(&pdev->dev, "isr: Just transmitted the last slot\n");
83
84         if (esr & ESAI_ESR_TDE_MASK)
85                 dev_dbg(&pdev->dev, "isr: Transmition data exception\n");
86
87         if (esr & ESAI_ESR_TED_MASK)
88                 dev_dbg(&pdev->dev, "isr: Transmitting even slots\n");
89
90         if (esr & ESAI_ESR_TD_MASK)
91                 dev_dbg(&pdev->dev, "isr: Transmitting data\n");
92
93         if (esr & ESAI_ESR_RLS_MASK)
94                 dev_dbg(&pdev->dev, "isr: Just received the last slot\n");
95
96         if (esr & ESAI_ESR_RDE_MASK)
97                 dev_dbg(&pdev->dev, "isr: Receiving data exception\n");
98
99         if (esr & ESAI_ESR_RED_MASK)
100                 dev_dbg(&pdev->dev, "isr: Receiving even slots\n");
101
102         if (esr & ESAI_ESR_RD_MASK)
103                 dev_dbg(&pdev->dev, "isr: Receiving data\n");
104
105         return IRQ_HANDLED;
106 }
107
108 /**
109  * This function is used to calculate the divisors of psr, pm, fp and it is
110  * supposed to be called in set_dai_sysclk() and set_bclk().
111  *
112  * @ratio: desired overall ratio for the paticipating dividers
113  * @usefp: for HCK setting, there is no need to set fp divider
114  * @fp: bypass other dividers by setting fp directly if fp != 0
115  * @tx: current setting is for playback or capture
116  */
117 static int fsl_esai_divisor_cal(struct snd_soc_dai *dai, bool tx, u32 ratio,
118                                 bool usefp, u32 fp)
119 {
120         struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
121         u32 psr, pm = 999, maxfp, prod, sub, savesub, i, j;
122
123         maxfp = usefp ? 16 : 1;
124
125         if (usefp && fp)
126                 goto out_fp;
127
128         if (ratio > 2 * 8 * 256 * maxfp || ratio < 2) {
129                 dev_err(dai->dev, "the ratio is out of range (2 ~ %d)\n",
130                                 2 * 8 * 256 * maxfp);
131                 return -EINVAL;
132         } else if (ratio % 2) {
133                 dev_err(dai->dev, "the raio must be even if using upper divider\n");
134                 return -EINVAL;
135         }
136
137         ratio /= 2;
138
139         psr = ratio <= 256 * maxfp ? ESAI_xCCR_xPSR_BYPASS : ESAI_xCCR_xPSR_DIV8;
140
141         /* Set the max fluctuation -- 0.1% of the max devisor */
142         savesub = (psr ? 1 : 8)  * 256 * maxfp / 1000;
143
144         /* Find the best value for PM */
145         for (i = 1; i <= 256; i++) {
146                 for (j = 1; j <= maxfp; j++) {
147                         /* PSR (1 or 8) * PM (1 ~ 256) * FP (1 ~ 16) */
148                         prod = (psr ? 1 : 8) * i * j;
149
150                         if (prod == ratio)
151                                 sub = 0;
152                         else if (prod / ratio == 1)
153                                 sub = prod - ratio;
154                         else if (ratio / prod == 1)
155                                 sub = ratio - prod;
156                         else
157                                 continue;
158
159                         /* Calculate the fraction */
160                         sub = sub * 1000 / ratio;
161                         if (sub < savesub) {
162                                 savesub = sub;
163                                 pm = i;
164                                 fp = j;
165                         }
166
167                         /* We are lucky */
168                         if (savesub == 0)
169                                 goto out;
170                 }
171         }
172
173         if (pm == 999) {
174                 dev_err(dai->dev, "failed to calculate proper divisors\n");
175                 return -EINVAL;
176         }
177
178 out:
179         regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
180                            ESAI_xCCR_xPSR_MASK | ESAI_xCCR_xPM_MASK,
181                            psr | ESAI_xCCR_xPM(pm));
182
183 out_fp:
184         /* Bypass fp if not being required */
185         if (maxfp <= 1)
186                 return 0;
187
188         regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
189                            ESAI_xCCR_xFP_MASK, ESAI_xCCR_xFP(fp));
190
191         return 0;
192 }
193
194 /**
195  * This function mainly configures the clock frequency of MCLK (HCKT/HCKR)
196  *
197  * @Parameters:
198  * clk_id: The clock source of HCKT/HCKR
199  *        (Input from outside; output from inside, FSYS or EXTAL)
200  * freq: The required clock rate of HCKT/HCKR
201  * dir: The clock direction of HCKT/HCKR
202  *
203  * Note: If the direction is input, we do not care about clk_id.
204  */
205 static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
206                                    unsigned int freq, int dir)
207 {
208         struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
209         struct clk *clksrc = esai_priv->extalclk;
210         bool tx = clk_id <= ESAI_HCKT_EXTAL;
211         bool in = dir == SND_SOC_CLOCK_IN;
212         u32 ret, ratio, ecr = 0;
213         unsigned long clk_rate;
214
215         /* sck_div can be only bypassed if ETO/ERO=0 and SNC_SOC_CLOCK_OUT */
216         esai_priv->sck_div[tx] = true;
217
218         /* Set the direction of HCKT/HCKR pins */
219         regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
220                            ESAI_xCCR_xHCKD, in ? 0 : ESAI_xCCR_xHCKD);
221
222         if (in)
223                 goto out;
224
225         switch (clk_id) {
226         case ESAI_HCKT_FSYS:
227         case ESAI_HCKR_FSYS:
228                 clksrc = esai_priv->fsysclk;
229                 break;
230         case ESAI_HCKT_EXTAL:
231                 ecr |= ESAI_ECR_ETI;
232         case ESAI_HCKR_EXTAL:
233                 ecr |= ESAI_ECR_ERI;
234                 break;
235         default:
236                 return -EINVAL;
237         }
238
239         if (IS_ERR(clksrc)) {
240                 dev_err(dai->dev, "no assigned %s clock\n",
241                                 clk_id % 2 ? "extal" : "fsys");
242                 return PTR_ERR(clksrc);
243         }
244         clk_rate = clk_get_rate(clksrc);
245
246         ratio = clk_rate / freq;
247         if (ratio * freq > clk_rate)
248                 ret = ratio * freq - clk_rate;
249         else if (ratio * freq < clk_rate)
250                 ret = clk_rate - ratio * freq;
251         else
252                 ret = 0;
253
254         /* Block if clock source can not be divided into the required rate */
255         if (ret != 0 && clk_rate / ret < 1000) {
256                 dev_err(dai->dev, "failed to derive required HCK%c rate\n",
257                                 tx ? 'T' : 'R');
258                 return -EINVAL;
259         }
260
261         if (ratio == 1) {
262                 /* Bypass all the dividers if not being needed */
263                 ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO;
264                 goto out;
265         }
266
267         ret = fsl_esai_divisor_cal(dai, tx, ratio, false, 0);
268         if (ret)
269                 return ret;
270
271         esai_priv->sck_div[tx] = false;
272
273 out:
274         esai_priv->hck_rate[tx] = freq;
275
276         regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
277                            tx ? ESAI_ECR_ETI | ESAI_ECR_ETO :
278                            ESAI_ECR_ERI | ESAI_ECR_ERO, ecr);
279
280         return 0;
281 }
282
283 /**
284  * This function configures the related dividers according to the bclk rate
285  */
286 static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
287 {
288         struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
289         u32 hck_rate = esai_priv->hck_rate[tx];
290         u32 sub, ratio = hck_rate / freq;
291
292         /* Don't apply for fully slave mode*/
293         if (esai_priv->slave_mode)
294                 return 0;
295
296         if (ratio * freq > hck_rate)
297                 sub = ratio * freq - hck_rate;
298         else if (ratio * freq < hck_rate)
299                 sub = hck_rate - ratio * freq;
300         else
301                 sub = 0;
302
303         /* Block if clock source can not be divided into the required rate */
304         if (sub != 0 && hck_rate / sub < 1000) {
305                 dev_err(dai->dev, "failed to derive required SCK%c rate\n",
306                                 tx ? 'T' : 'R');
307                 return -EINVAL;
308         }
309
310         if (esai_priv->sck_div[tx] && (ratio > 16 || ratio == 0)) {
311                 dev_err(dai->dev, "the ratio is out of range (1 ~ 16)\n");
312                 return -EINVAL;
313         }
314
315         return fsl_esai_divisor_cal(dai, tx, ratio, true,
316                         esai_priv->sck_div[tx] ? 0 : ratio);
317 }
318
319 static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
320                                      u32 rx_mask, int slots, int slot_width)
321 {
322         struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
323
324         regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
325                            ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
326
327         regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA,
328                            ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask));
329         regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB,
330                            ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(tx_mask));
331
332         regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
333                            ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
334
335         regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA,
336                            ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask));
337         regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB,
338                            ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask));
339
340         esai_priv->slot_width = slot_width;
341
342         return 0;
343 }
344
345 static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
346 {
347         struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
348         u32 xcr = 0, xccr = 0, mask;
349
350         /* DAI mode */
351         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
352         case SND_SOC_DAIFMT_I2S:
353                 /* Data on rising edge of bclk, frame low, 1clk before data */
354                 xcr |= ESAI_xCR_xFSR;
355                 xccr |= ESAI_xCCR_xFSP | ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
356                 break;
357         case SND_SOC_DAIFMT_LEFT_J:
358                 /* Data on rising edge of bclk, frame high */
359                 xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
360                 break;
361         case SND_SOC_DAIFMT_RIGHT_J:
362                 /* Data on rising edge of bclk, frame high, right aligned */
363                 xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCR_xWA;
364                 break;
365         case SND_SOC_DAIFMT_DSP_A:
366                 /* Data on rising edge of bclk, frame high, 1clk before data */
367                 xcr |= ESAI_xCR_xFSL | ESAI_xCR_xFSR;
368                 xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
369                 break;
370         case SND_SOC_DAIFMT_DSP_B:
371                 /* Data on rising edge of bclk, frame high */
372                 xcr |= ESAI_xCR_xFSL;
373                 xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
374                 break;
375         default:
376                 return -EINVAL;
377         }
378
379         /* DAI clock inversion */
380         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
381         case SND_SOC_DAIFMT_NB_NF:
382                 /* Nothing to do for both normal cases */
383                 break;
384         case SND_SOC_DAIFMT_IB_NF:
385                 /* Invert bit clock */
386                 xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
387                 break;
388         case SND_SOC_DAIFMT_NB_IF:
389                 /* Invert frame clock */
390                 xccr ^= ESAI_xCCR_xFSP;
391                 break;
392         case SND_SOC_DAIFMT_IB_IF:
393                 /* Invert both clocks */
394                 xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP;
395                 break;
396         default:
397                 return -EINVAL;
398         }
399
400         esai_priv->slave_mode = false;
401
402         /* DAI clock master masks */
403         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
404         case SND_SOC_DAIFMT_CBM_CFM:
405                 esai_priv->slave_mode = true;
406                 break;
407         case SND_SOC_DAIFMT_CBS_CFM:
408                 xccr |= ESAI_xCCR_xCKD;
409                 break;
410         case SND_SOC_DAIFMT_CBM_CFS:
411                 xccr |= ESAI_xCCR_xFSD;
412                 break;
413         case SND_SOC_DAIFMT_CBS_CFS:
414                 xccr |= ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
415                 break;
416         default:
417                 return -EINVAL;
418         }
419
420         mask = ESAI_xCR_xFSL | ESAI_xCR_xFSR;
421         regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, mask, xcr);
422         regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, mask, xcr);
423
424         mask = ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP |
425                 ESAI_xCCR_xFSD | ESAI_xCCR_xCKD | ESAI_xCR_xWA;
426         regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, mask, xccr);
427         regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, mask, xccr);
428
429         return 0;
430 }
431
432 static int fsl_esai_startup(struct snd_pcm_substream *substream,
433                             struct snd_soc_dai *dai)
434 {
435         int ret;
436         struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
437
438         /*
439          * Some platforms might use the same bit to gate all three or two of
440          * clocks, so keep all clocks open/close at the same time for safety
441          */
442         ret = clk_prepare_enable(esai_priv->coreclk);
443         if (ret)
444                 return ret;
445         if (!IS_ERR(esai_priv->extalclk)) {
446                 ret = clk_prepare_enable(esai_priv->extalclk);
447                 if (ret)
448                         goto err_extalck;
449         }
450         if (!IS_ERR(esai_priv->fsysclk)) {
451                 ret = clk_prepare_enable(esai_priv->fsysclk);
452                 if (ret)
453                         goto err_fsysclk;
454         }
455
456         if (!dai->active) {
457                 /* Reset Port C */
458                 regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
459                                    ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO));
460                 regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
461                                    ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO));
462
463                 /* Set synchronous mode */
464                 regmap_update_bits(esai_priv->regmap, REG_ESAI_SAICR,
465                                    ESAI_SAICR_SYNC, esai_priv->synchronous ?
466                                    ESAI_SAICR_SYNC : 0);
467
468                 /* Set a default slot number -- 2 */
469                 regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
470                                    ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2));
471                 regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
472                                    ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2));
473         }
474
475         return 0;
476
477 err_fsysclk:
478         if (!IS_ERR(esai_priv->extalclk))
479                 clk_disable_unprepare(esai_priv->extalclk);
480 err_extalck:
481         clk_disable_unprepare(esai_priv->coreclk);
482
483         return ret;
484 }
485
486 static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
487                               struct snd_pcm_hw_params *params,
488                               struct snd_soc_dai *dai)
489 {
490         struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
491         bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
492         u32 width = snd_pcm_format_width(params_format(params));
493         u32 channels = params_channels(params);
494         u32 bclk, mask, val, ret;
495
496         bclk = params_rate(params) * esai_priv->slot_width * 2;
497
498         ret = fsl_esai_set_bclk(dai, tx, bclk);
499         if (ret)
500                 return ret;
501
502         /* Use Normal mode to support monaural audio */
503         regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
504                            ESAI_xCR_xMOD_MASK, params_channels(params) > 1 ?
505                            ESAI_xCR_xMOD_NETWORK : 0);
506
507         regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
508                            ESAI_xFCR_xFR_MASK, ESAI_xFCR_xFR);
509
510         mask = ESAI_xFCR_xFR_MASK | ESAI_xFCR_xWA_MASK | ESAI_xFCR_xFWM_MASK |
511               (tx ? ESAI_xFCR_TE_MASK | ESAI_xFCR_TIEN : ESAI_xFCR_RE_MASK);
512         val = ESAI_xFCR_xWA(width) | ESAI_xFCR_xFWM(esai_priv->fifo_depth) |
513              (tx ? ESAI_xFCR_TE(channels) | ESAI_xFCR_TIEN : ESAI_xFCR_RE(channels));
514
515         regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val);
516
517         mask = ESAI_xCR_xSWS_MASK | (tx ? ESAI_xCR_PADC : 0);
518         val = ESAI_xCR_xSWS(esai_priv->slot_width, width) | (tx ? ESAI_xCR_PADC : 0);
519
520         regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val);
521
522         return 0;
523 }
524
525 static void fsl_esai_shutdown(struct snd_pcm_substream *substream,
526                               struct snd_soc_dai *dai)
527 {
528         struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
529
530         if (!IS_ERR(esai_priv->fsysclk))
531                 clk_disable_unprepare(esai_priv->fsysclk);
532         if (!IS_ERR(esai_priv->extalclk))
533                 clk_disable_unprepare(esai_priv->extalclk);
534         clk_disable_unprepare(esai_priv->coreclk);
535 }
536
537 static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
538                             struct snd_soc_dai *dai)
539 {
540         struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
541         bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
542         u8 i, channels = substream->runtime->channels;
543
544         switch (cmd) {
545         case SNDRV_PCM_TRIGGER_START:
546         case SNDRV_PCM_TRIGGER_RESUME:
547         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
548                 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
549                                    ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN);
550
551                 /* Write initial words reqiured by ESAI as normal procedure */
552                 for (i = 0; tx && i < channels; i++)
553                         regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0);
554
555                 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
556                                    tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
557                                    tx ? ESAI_xCR_TE(channels) : ESAI_xCR_RE(channels));
558                 break;
559         case SNDRV_PCM_TRIGGER_SUSPEND:
560         case SNDRV_PCM_TRIGGER_STOP:
561         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
562                 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
563                                    tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0);
564
565                 /* Disable and reset FIFO */
566                 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
567                                    ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR);
568                 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
569                                    ESAI_xFCR_xFR, 0);
570                 break;
571         default:
572                 return -EINVAL;
573         }
574
575         return 0;
576 }
577
578 static struct snd_soc_dai_ops fsl_esai_dai_ops = {
579         .startup = fsl_esai_startup,
580         .shutdown = fsl_esai_shutdown,
581         .trigger = fsl_esai_trigger,
582         .hw_params = fsl_esai_hw_params,
583         .set_sysclk = fsl_esai_set_dai_sysclk,
584         .set_fmt = fsl_esai_set_dai_fmt,
585         .xlate_tdm_slot_mask = fsl_asoc_xlate_tdm_slot_mask,
586         .set_tdm_slot = fsl_esai_set_dai_tdm_slot,
587 };
588
589 static int fsl_esai_dai_probe(struct snd_soc_dai *dai)
590 {
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);
595
596         return 0;
597 }
598
599 static struct snd_soc_dai_driver fsl_esai_dai = {
600         .probe = fsl_esai_dai_probe,
601         .playback = {
602                 .channels_min = 1,
603                 .channels_max = 12,
604                 .rates = FSL_ESAI_RATES,
605                 .formats = FSL_ESAI_FORMATS,
606         },
607         .capture = {
608                 .channels_min = 1,
609                 .channels_max = 8,
610                 .rates = FSL_ESAI_RATES,
611                 .formats = FSL_ESAI_FORMATS,
612         },
613         .ops = &fsl_esai_dai_ops,
614 };
615
616 static const struct snd_soc_component_driver fsl_esai_component = {
617         .name           = "fsl-esai",
618 };
619
620 static bool fsl_esai_readable_reg(struct device *dev, unsigned int reg)
621 {
622         switch (reg) {
623         case REG_ESAI_ERDR:
624         case REG_ESAI_ECR:
625         case REG_ESAI_ESR:
626         case REG_ESAI_TFCR:
627         case REG_ESAI_TFSR:
628         case REG_ESAI_RFCR:
629         case REG_ESAI_RFSR:
630         case REG_ESAI_RX0:
631         case REG_ESAI_RX1:
632         case REG_ESAI_RX2:
633         case REG_ESAI_RX3:
634         case REG_ESAI_SAISR:
635         case REG_ESAI_SAICR:
636         case REG_ESAI_TCR:
637         case REG_ESAI_TCCR:
638         case REG_ESAI_RCR:
639         case REG_ESAI_RCCR:
640         case REG_ESAI_TSMA:
641         case REG_ESAI_TSMB:
642         case REG_ESAI_RSMA:
643         case REG_ESAI_RSMB:
644         case REG_ESAI_PRRC:
645         case REG_ESAI_PCRC:
646                 return true;
647         default:
648                 return false;
649         }
650 }
651
652 static bool fsl_esai_writeable_reg(struct device *dev, unsigned int reg)
653 {
654         switch (reg) {
655         case REG_ESAI_ETDR:
656         case REG_ESAI_ECR:
657         case REG_ESAI_TFCR:
658         case REG_ESAI_RFCR:
659         case REG_ESAI_TX0:
660         case REG_ESAI_TX1:
661         case REG_ESAI_TX2:
662         case REG_ESAI_TX3:
663         case REG_ESAI_TX4:
664         case REG_ESAI_TX5:
665         case REG_ESAI_TSR:
666         case REG_ESAI_SAICR:
667         case REG_ESAI_TCR:
668         case REG_ESAI_TCCR:
669         case REG_ESAI_RCR:
670         case REG_ESAI_RCCR:
671         case REG_ESAI_TSMA:
672         case REG_ESAI_TSMB:
673         case REG_ESAI_RSMA:
674         case REG_ESAI_RSMB:
675         case REG_ESAI_PRRC:
676         case REG_ESAI_PCRC:
677                 return true;
678         default:
679                 return false;
680         }
681 }
682
683 static struct regmap_config fsl_esai_regmap_config = {
684         .reg_bits = 32,
685         .reg_stride = 4,
686         .val_bits = 32,
687
688         .max_register = REG_ESAI_PCRC,
689         .readable_reg = fsl_esai_readable_reg,
690         .writeable_reg = fsl_esai_writeable_reg,
691 };
692
693 static int fsl_esai_probe(struct platform_device *pdev)
694 {
695         struct device_node *np = pdev->dev.of_node;
696         struct fsl_esai *esai_priv;
697         struct resource *res;
698         const uint32_t *iprop;
699         void __iomem *regs;
700         int irq, ret;
701
702         esai_priv = devm_kzalloc(&pdev->dev, sizeof(*esai_priv), GFP_KERNEL);
703         if (!esai_priv)
704                 return -ENOMEM;
705
706         esai_priv->pdev = pdev;
707         strcpy(esai_priv->name, np->name);
708
709         if (of_property_read_bool(np, "big-endian"))
710                 fsl_esai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG;
711
712         /* Get the addresses and IRQ */
713         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
714         regs = devm_ioremap_resource(&pdev->dev, res);
715         if (IS_ERR(regs))
716                 return PTR_ERR(regs);
717
718         esai_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
719                         "core", regs, &fsl_esai_regmap_config);
720         if (IS_ERR(esai_priv->regmap)) {
721                 dev_err(&pdev->dev, "failed to init regmap: %ld\n",
722                                 PTR_ERR(esai_priv->regmap));
723                 return PTR_ERR(esai_priv->regmap);
724         }
725
726         esai_priv->coreclk = devm_clk_get(&pdev->dev, "core");
727         if (IS_ERR(esai_priv->coreclk)) {
728                 dev_err(&pdev->dev, "failed to get core clock: %ld\n",
729                                 PTR_ERR(esai_priv->coreclk));
730                 return PTR_ERR(esai_priv->coreclk);
731         }
732
733         esai_priv->extalclk = devm_clk_get(&pdev->dev, "extal");
734         if (IS_ERR(esai_priv->extalclk))
735                 dev_warn(&pdev->dev, "failed to get extal clock: %ld\n",
736                                 PTR_ERR(esai_priv->extalclk));
737
738         esai_priv->fsysclk = devm_clk_get(&pdev->dev, "fsys");
739         if (IS_ERR(esai_priv->fsysclk))
740                 dev_warn(&pdev->dev, "failed to get fsys clock: %ld\n",
741                                 PTR_ERR(esai_priv->fsysclk));
742
743         irq = platform_get_irq(pdev, 0);
744         if (irq < 0) {
745                 dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
746                 return irq;
747         }
748
749         ret = devm_request_irq(&pdev->dev, irq, esai_isr, 0,
750                                esai_priv->name, esai_priv);
751         if (ret) {
752                 dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
753                 return ret;
754         }
755
756         /* Set a default slot size */
757         esai_priv->slot_width = 32;
758
759         /* Set a default master/slave state */
760         esai_priv->slave_mode = true;
761
762         /* Determine the FIFO depth */
763         iprop = of_get_property(np, "fsl,fifo-depth", NULL);
764         if (iprop)
765                 esai_priv->fifo_depth = be32_to_cpup(iprop);
766         else
767                 esai_priv->fifo_depth = 64;
768
769         esai_priv->dma_params_tx.maxburst = 16;
770         esai_priv->dma_params_rx.maxburst = 16;
771         esai_priv->dma_params_tx.addr = res->start + REG_ESAI_ETDR;
772         esai_priv->dma_params_rx.addr = res->start + REG_ESAI_ERDR;
773
774         esai_priv->synchronous =
775                 of_property_read_bool(np, "fsl,esai-synchronous");
776
777         /* Implement full symmetry for synchronous mode */
778         if (esai_priv->synchronous) {
779                 fsl_esai_dai.symmetric_rates = 1;
780                 fsl_esai_dai.symmetric_channels = 1;
781                 fsl_esai_dai.symmetric_samplebits = 1;
782         }
783
784         dev_set_drvdata(&pdev->dev, esai_priv);
785
786         /* Reset ESAI unit */
787         ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ERST);
788         if (ret) {
789                 dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret);
790                 return ret;
791         }
792
793         /*
794          * We need to enable ESAI so as to access some of its registers.
795          * Otherwise, we would fail to dump regmap from user space.
796          */
797         ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN);
798         if (ret) {
799                 dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret);
800                 return ret;
801         }
802
803         ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component,
804                                               &fsl_esai_dai, 1);
805         if (ret) {
806                 dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
807                 return ret;
808         }
809
810         ret = imx_pcm_dma_init(pdev);
811         if (ret)
812                 dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
813
814         return ret;
815 }
816
817 static const struct of_device_id fsl_esai_dt_ids[] = {
818         { .compatible = "fsl,imx35-esai", },
819         {}
820 };
821 MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
822
823 static struct platform_driver fsl_esai_driver = {
824         .probe = fsl_esai_probe,
825         .driver = {
826                 .name = "fsl-esai-dai",
827                 .owner = THIS_MODULE,
828                 .of_match_table = fsl_esai_dt_ids,
829         },
830 };
831
832 module_platform_driver(fsl_esai_driver);
833
834 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
835 MODULE_DESCRIPTION("Freescale ESAI CPU DAI driver");
836 MODULE_LICENSE("GPL v2");
837 MODULE_ALIAS("platform:fsl-esai-dai");