diff options
author | Shengjiu Wang <b02247@freescale.com> | 2014-04-27 22:40:10 -0400 |
---|---|---|
committer | Shengjiu Wang <b02247@freescale.com> | 2014-04-29 00:43:02 -0400 |
commit | 22d1bec44929e5fb6fa8316c4687d493c7d264b4 (patch) | |
tree | 93c47078d636f776b5ef78063fe76f5941b5dcba /sound/soc/fsl | |
parent | 0673acf93a40e5b26b667b627dc62b81b377cc70 (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.c | 1278 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_esai.h | 667 | ||||
-rw-r--r-- | sound/soc/fsl/imx-cs42888.c | 75 |
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 | */ | ||
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 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 | ||
38 | static inline void write_esai_mask(u32 __iomem *addr, u32 clear, u32 set) | 69 | static 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 | ||
45 | static 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 | */ | ||
122 | static 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 | |||
183 | out: | ||
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 | |||
188 | out_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 | ||
89 | static 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 | */ | ||
210 | static 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 | |||
278 | out: | ||
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 | */ |
155 | static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, | 291 | static 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; | 324 | static 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 | /* | 350 | static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
187 | * ESAI DAI format configuration. | ||
188 | */ | ||
189 | static 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 | ||
310 | static int fsl_esai_startup(struct snd_pcm_substream *substream, | 437 | static 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, |
329 | static 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 | /* | 471 | static 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 | */ | ||
386 | static 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) | |
436 | static 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 | ||
466 | static void fsl_esai_shutdown(struct snd_pcm_substream *substream, | 515 | static 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 | ||
483 | static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, | 538 | static 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 | |||
551 | static struct snd_soc_dai_ops fsl_esai_dai_ops = { | 579 | static 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 | ||
562 | static int fsl_esai_dai_probe(struct snd_soc_dai *dai) | 589 | static 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 | ||
622 | static 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 | |||
654 | static 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 | |||
685 | static 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 | |||
594 | static bool fsl_esai_check_xrun(struct snd_pcm_substream *substream) | 695 | static 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 | ||
604 | static int store_reg(struct snd_soc_dai *cpu_dai) | 707 | static 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 | ||
623 | static int restore_reg(struct snd_soc_dai *cpu_dai) | 727 | static 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 | |||
714 | static 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 | ||
740 | static int fsl_esai_probe(struct platform_device *pdev) | 819 | static 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 | ||
860 | failed_pcm_init: | ||
861 | snd_soc_unregister_component(&pdev->dev); | ||
862 | failed_register: | ||
863 | failed_get_dma: | ||
864 | irq_dispose_mapping(esai->irq); | ||
865 | iounmap(esai->base); | ||
866 | failed_iomap: | ||
867 | failed_get_resource: | ||
868 | clk_unprepare(esai->clk); | ||
869 | return ret; | 968 | return ret; |
870 | } | 969 | } |
871 | 970 | ||
872 | static int fsl_esai_remove(struct platform_device *pdev) | 971 | static 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 | |||
885 | static const struct of_device_id fsl_esai_ids[] = { | ||
886 | { .compatible = "fsl,imx6q-esai", }, | ||
887 | {} | 973 | {} |
888 | }; | 974 | }; |
975 | MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids); | ||
889 | 976 | ||
890 | static struct platform_driver fsl_esai_driver = { | 977 | static 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 | ||
900 | module_platform_driver(fsl_esai_driver); | 986 | module_platform_driver(fsl_esai_driver); |
901 | 987 | ||
902 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | 988 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); |
903 | MODULE_DESCRIPTION("i.MX ASoC ESAI driver"); | 989 | MODULE_DESCRIPTION("Freescale ESAI CPU DAI driver"); |
990 | MODULE_LICENSE("GPL v2"); | ||
904 | MODULE_ALIAS("platform:fsl-esai-dai"); | 991 | MODULE_ALIAS("platform:fsl-esai-dai"); |
905 | MODULE_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 | |||
320 | struct 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 | ||
35 | struct imx_priv { | 35 | struct 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 | ||
44 | static struct imx_priv card_priv; | 43 | static struct imx_priv card_priv; |
45 | 44 | ||
46 | static 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 | |||
57 | static 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 | |||
67 | static 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 | |||
83 | static int imx_cs42888_surround_hw_params(struct snd_pcm_substream *substream, | 45 | static 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 | ||
137 | static struct snd_soc_ops imx_cs42888_surround_ops = { | 74 | static 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 | ||