aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolin Chen <nicoleotsuka@gmail.com>2014-07-29 06:08:53 -0400
committerMark Brown <broonie@linaro.org>2014-07-29 14:22:49 -0400
commit3117bb3109dc223e186302f5dc8ce9ed04adca90 (patch)
tree35f65b00d2361c37d158f31a8ae1707975aaf1cc
parent94b912e42829b25d97b6b1f2be66c6aa81ac125f (diff)
ASoC: fsl_asrc: Add ASRC ASoC CPU DAI and platform drivers
The Asynchronous Sample Rate Converter (ASRC) converts the sampling rate of a signal associated with an input clock into a signal associated with a different output clock. The driver currently works as a Front End of DPCM with other Back Ends DAI links such as ESAI<->CS42888 and SSI<->WM8962 and SAI. It converts the original sample rate to a common rate supported by Back Ends for playback while converts the common rate of Back Ends to a desired rate for capture. It has 3 pairs to support three different substreams within totally 10 channels. Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com> Reviewed-by: Varka Bhadram <varkabhadram@gmail.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,asrc.txt60
-rw-r--r--sound/soc/fsl/Kconfig9
-rw-r--r--sound/soc/fsl/Makefile2
-rw-r--r--sound/soc/fsl/fsl_asrc.c992
-rw-r--r--sound/soc/fsl/fsl_asrc.h461
-rw-r--r--sound/soc/fsl/fsl_asrc_dma.c386
6 files changed, 1910 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/sound/fsl,asrc.txt b/Documentation/devicetree/bindings/sound/fsl,asrc.txt
new file mode 100644
index 000000000000..b93362a570be
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,asrc.txt
@@ -0,0 +1,60 @@
1Freescale Asynchronous Sample Rate Converter (ASRC) Controller
2
3The Asynchronous Sample Rate Converter (ASRC) converts the sampling rate of a
4signal associated with an input clock into a signal associated with a different
5output clock. The driver currently works as a Front End of DPCM with other Back
6Ends Audio controller such as ESAI, SSI and SAI. It has three pairs to support
7three substreams within totally 10 channels.
8
9Required properties:
10
11 - compatible : Contains "fsl,imx35-asrc" or "fsl,imx53-asrc".
12
13 - reg : Offset and length of the register set for the device.
14
15 - interrupts : Contains the spdif interrupt.
16
17 - dmas : Generic dma devicetree binding as described in
18 Documentation/devicetree/bindings/dma/dma.txt.
19
20 - dma-names : Contains "rxa", "rxb", "rxc", "txa", "txb" and "txc".
21
22 - clocks : Contains an entry for each entry in clock-names.
23
24 - clock-names : Contains the following entries
25 "mem" Peripheral access clock to access registers.
26 "ipg" Peripheral clock to driver module.
27 "asrck_<0-f>" Clock sources for input and output clock.
28
29 - big-endian : If this property is absent, the little endian mode
30 will be in use as default. Otherwise, the big endian
31 mode will be in use for all the device registers.
32
33 - fsl,asrc-rate : Defines a mutual sample rate used by DPCM Back Ends.
34
35 - fsl,asrc-width : Defines a mutual sample width used by DPCM Back Ends.
36
37Example:
38
39asrc: asrc@02034000 {
40 compatible = "fsl,imx53-asrc";
41 reg = <0x02034000 0x4000>;
42 interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
43 clocks = <&clks 107>, <&clks 107>, <&clks 0>,
44 <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
45 <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
46 <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
47 <&clks 107>, <&clks 0>, <&clks 0>;
48 clock-names = "mem", "ipg", "asrck0",
49 "asrck_1", "asrck_2", "asrck_3", "asrck_4",
50 "asrck_5", "asrck_6", "asrck_7", "asrck_8",
51 "asrck_9", "asrck_a", "asrck_b", "asrck_c",
52 "asrck_d", "asrck_e", "asrck_f";
53 dmas = <&sdma 17 23 1>, <&sdma 18 23 1>, <&sdma 19 23 1>,
54 <&sdma 20 23 1>, <&sdma 21 23 1>, <&sdma 22 23 1>;
55 dma-names = "rxa", "rxb", "rxc",
56 "txa", "txb", "txc";
57 fsl,asrc-rate = <48000>;
58 fsl,asrc-width = <16>;
59 status = "okay";
60};
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 37933629cbed..56fd32b3a881 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -2,6 +2,15 @@ menu "SoC Audio for Freescale CPUs"
2 2
3comment "Common SoC Audio options for Freescale CPUs:" 3comment "Common SoC Audio options for Freescale CPUs:"
4 4
5config SND_SOC_FSL_ASRC
6 tristate "Asynchronous Sample Rate Converter (ASRC) module support"
7 select REGMAP_MMIO
8 help
9 Say Y if you want to add Asynchronous Sample Rate Converter (ASRC)
10 support for the Freescale CPUs.
11 This option is only useful for out-of-tree drivers since
12 in-tree drivers select it automatically.
13
5config SND_SOC_FSL_SAI 14config SND_SOC_FSL_SAI
6 tristate "Synchronous Audio Interface (SAI) module support" 15 tristate "Synchronous Audio Interface (SAI) module support"
7 select REGMAP_MMIO 16 select REGMAP_MMIO
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index db254e358c18..9ff59267eac9 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -11,6 +11,7 @@ snd-soc-p1022-rdk-objs := p1022_rdk.o
11obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o 11obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
12 12
13# Freescale SSI/DMA/SAI/SPDIF Support 13# Freescale SSI/DMA/SAI/SPDIF Support
14snd-soc-fsl-asrc-objs := fsl_asrc.o fsl_asrc_dma.o
14snd-soc-fsl-sai-objs := fsl_sai.o 15snd-soc-fsl-sai-objs := fsl_sai.o
15snd-soc-fsl-ssi-y := fsl_ssi.o 16snd-soc-fsl-ssi-y := fsl_ssi.o
16snd-soc-fsl-ssi-$(CONFIG_DEBUG_FS) += fsl_ssi_dbg.o 17snd-soc-fsl-ssi-$(CONFIG_DEBUG_FS) += fsl_ssi_dbg.o
@@ -18,6 +19,7 @@ snd-soc-fsl-spdif-objs := fsl_spdif.o
18snd-soc-fsl-esai-objs := fsl_esai.o 19snd-soc-fsl-esai-objs := fsl_esai.o
19snd-soc-fsl-utils-objs := fsl_utils.o 20snd-soc-fsl-utils-objs := fsl_utils.o
20snd-soc-fsl-dma-objs := fsl_dma.o 21snd-soc-fsl-dma-objs := fsl_dma.o
22obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc.o
21obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o 23obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o
22obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o 24obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o
23obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o 25obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
new file mode 100644
index 000000000000..27a4a7084343
--- /dev/null
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -0,0 +1,992 @@
1/*
2 * Freescale ASRC ALSA SoC Digital Audio Interface (DAI) driver
3 *
4 * Copyright (C) 2014 Freescale Semiconductor, Inc.
5 *
6 * Author: Nicolin Chen <nicoleotsuka@gmail.com>
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.
11 */
12
13#include <linux/clk.h>
14#include <linux/delay.h>
15#include <linux/dma-mapping.h>
16#include <linux/module.h>
17#include <linux/of_platform.h>
18#include <linux/platform_data/dma-imx.h>
19#include <linux/pm_runtime.h>
20#include <sound/dmaengine_pcm.h>
21#include <sound/pcm_params.h>
22
23#include "fsl_asrc.h"
24
25#define IDEAL_RATIO_DECIMAL_DEPTH 26
26
27#define pair_err(fmt, ...) \
28 dev_err(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
29
30#define pair_dbg(fmt, ...) \
31 dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
32
33/* Sample rates are aligned with that defined in pcm.h file */
34static const u8 process_option[][8][2] = {
35 /* 32kHz 44.1kHz 48kHz 64kHz 88.2kHz 96kHz 176kHz 192kHz */
36 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 5512Hz */
37 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 8kHz */
38 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 11025Hz */
39 {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 16kHz */
40 {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 22050Hz */
41 {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},}, /* 32kHz */
42 {{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 44.1kHz */
43 {{0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 48kHz */
44 {{1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},}, /* 64kHz */
45 {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 88.2kHz */
46 {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 96kHz */
47 {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 176kHz */
48 {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 192kHz */
49};
50
51/* Corresponding to process_option */
52static int supported_input_rate[] = {
53 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200,
54 96000, 176400, 192000,
55};
56
57static int supported_asrc_rate[] = {
58 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000,
59};
60
61/**
62 * The following tables map the relationship between asrc_inclk/asrc_outclk in
63 * fsl_asrc.h and the registers of ASRCSR
64 */
65static unsigned char input_clk_map_imx35[] = {
66 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
67};
68
69static unsigned char output_clk_map_imx35[] = {
70 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
71};
72
73/* i.MX53 uses the same map for input and output */
74static unsigned char input_clk_map_imx53[] = {
75/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */
76 0x0, 0x1, 0x2, 0x7, 0x4, 0x5, 0x6, 0x3, 0x8, 0x9, 0xa, 0xb, 0xc, 0xf, 0xe, 0xd,
77};
78
79static unsigned char output_clk_map_imx53[] = {
80/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */
81 0x8, 0x9, 0xa, 0x7, 0xc, 0x5, 0x6, 0xb, 0x0, 0x1, 0x2, 0x3, 0x4, 0xf, 0xe, 0xd,
82};
83
84static unsigned char *clk_map[2];
85
86/**
87 * Request ASRC pair
88 *
89 * It assigns pair by the order of A->C->B because allocation of pair B,
90 * within range [ANCA, ANCA+ANCB-1], depends on the channels of pair A
91 * while pair A and pair C are comparatively independent.
92 */
93static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair)
94{
95 enum asrc_pair_index index = ASRC_INVALID_PAIR;
96 struct fsl_asrc *asrc_priv = pair->asrc_priv;
97 struct device *dev = &asrc_priv->pdev->dev;
98 unsigned long lock_flags;
99 int i, ret = 0;
100
101 spin_lock_irqsave(&asrc_priv->lock, lock_flags);
102
103 for (i = ASRC_PAIR_A; i < ASRC_PAIR_MAX_NUM; i++) {
104 if (asrc_priv->pair[i] != NULL)
105 continue;
106
107 index = i;
108
109 if (i != ASRC_PAIR_B)
110 break;
111 }
112
113 if (index == ASRC_INVALID_PAIR) {
114 dev_err(dev, "all pairs are busy now\n");
115 ret = -EBUSY;
116 } else if (asrc_priv->channel_avail < channels) {
117 dev_err(dev, "can't afford required channels: %d\n", channels);
118 ret = -EINVAL;
119 } else {
120 asrc_priv->channel_avail -= channels;
121 asrc_priv->pair[index] = pair;
122 pair->channels = channels;
123 pair->index = index;
124 }
125
126 spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
127
128 return ret;
129}
130
131/**
132 * Release ASRC pair
133 *
134 * It clears the resource from asrc_priv and releases the occupied channels.
135 */
136static void fsl_asrc_release_pair(struct fsl_asrc_pair *pair)
137{
138 struct fsl_asrc *asrc_priv = pair->asrc_priv;
139 enum asrc_pair_index index = pair->index;
140 unsigned long lock_flags;
141
142 /* Make sure the pair is disabled */
143 regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
144 ASRCTR_ASRCEi_MASK(index), 0);
145
146 spin_lock_irqsave(&asrc_priv->lock, lock_flags);
147
148 asrc_priv->channel_avail += pair->channels;
149 asrc_priv->pair[index] = NULL;
150 pair->error = 0;
151
152 spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
153}
154
155/**
156 * Configure input and output thresholds
157 */
158static void fsl_asrc_set_watermarks(struct fsl_asrc_pair *pair, u32 in, u32 out)
159{
160 struct fsl_asrc *asrc_priv = pair->asrc_priv;
161 enum asrc_pair_index index = pair->index;
162
163 regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index),
164 ASRMCRi_EXTTHRSHi_MASK |
165 ASRMCRi_INFIFO_THRESHOLD_MASK |
166 ASRMCRi_OUTFIFO_THRESHOLD_MASK,
167 ASRMCRi_EXTTHRSHi |
168 ASRMCRi_INFIFO_THRESHOLD(in) |
169 ASRMCRi_OUTFIFO_THRESHOLD(out));
170}
171
172/**
173 * Calculate the total divisor between asrck clock rate and sample rate
174 *
175 * It follows the formula clk_rate = samplerate * (2 ^ prescaler) * divider
176 */
177static u32 fsl_asrc_cal_asrck_divisor(struct fsl_asrc_pair *pair, u32 div)
178{
179 u32 ps;
180
181 /* Calculate the divisors: prescaler [2^0, 2^7], divder [1, 8] */
182 for (ps = 0; div > 8; ps++)
183 div >>= 1;
184
185 return ((div - 1) << ASRCDRi_AxCPi_WIDTH) | ps;
186}
187
188/**
189 * Calculate and set the ratio for Ideal Ratio mode only
190 *
191 * The ratio is a 32-bit fixed point value with 26 fractional bits.
192 */
193static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair,
194 int inrate, int outrate)
195{
196 struct fsl_asrc *asrc_priv = pair->asrc_priv;
197 enum asrc_pair_index index = pair->index;
198 unsigned long ratio;
199 int i;
200
201 if (!outrate) {
202 pair_err("output rate should not be zero\n");
203 return -EINVAL;
204 }
205
206 /* Calculate the intergal part of the ratio */
207 ratio = (inrate / outrate) << IDEAL_RATIO_DECIMAL_DEPTH;
208
209 /* ... and then the 26 depth decimal part */
210 inrate %= outrate;
211
212 for (i = 1; i <= IDEAL_RATIO_DECIMAL_DEPTH; i++) {
213 inrate <<= 1;
214
215 if (inrate < outrate)
216 continue;
217
218 ratio |= 1 << (IDEAL_RATIO_DECIMAL_DEPTH - i);
219 inrate -= outrate;
220
221 if (!inrate)
222 break;
223 }
224
225 regmap_write(asrc_priv->regmap, REG_ASRIDRL(index), ratio);
226 regmap_write(asrc_priv->regmap, REG_ASRIDRH(index), ratio >> 24);
227
228 return 0;
229}
230
231/**
232 * Configure the assigned ASRC pair
233 *
234 * It configures those ASRC registers according to a configuration instance
235 * of struct asrc_config which includes in/output sample rate, width, channel
236 * and clock settings.
237 */
238static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
239{
240 struct asrc_config *config = pair->config;
241 struct fsl_asrc *asrc_priv = pair->asrc_priv;
242 enum asrc_pair_index index = pair->index;
243 u32 inrate = config->input_sample_rate, indiv;
244 u32 outrate = config->output_sample_rate, outdiv;
245 bool ideal = config->inclk == INCLK_NONE;
246 u32 clk_index[2], div[2];
247 int in, out, channels;
248 struct clk *clk;
249
250 if (!config) {
251 pair_err("invalid pair config\n");
252 return -EINVAL;
253 }
254
255 /* Validate channels */
256 if (config->channel_num < 1 || config->channel_num > 10) {
257 pair_err("does not support %d channels\n", config->channel_num);
258 return -EINVAL;
259 }
260
261 /* Validate output width */
262 if (config->output_word_width == ASRC_WIDTH_8_BIT) {
263 pair_err("does not support 8bit width output\n");
264 return -EINVAL;
265 }
266
267 /* Validate input and output sample rates */
268 for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++)
269 if (inrate == supported_input_rate[in])
270 break;
271
272 if (in == ARRAY_SIZE(supported_input_rate)) {
273 pair_err("unsupported input sample rate: %dHz\n", inrate);
274 return -EINVAL;
275 }
276
277 for (out = 0; out < ARRAY_SIZE(supported_asrc_rate); out++)
278 if (outrate == supported_asrc_rate[out])
279 break;
280
281 if (out == ARRAY_SIZE(supported_asrc_rate)) {
282 pair_err("unsupported output sample rate: %dHz\n", outrate);
283 return -EINVAL;
284 }
285
286 /* Validate input and output clock sources */
287 clk_index[IN] = clk_map[IN][config->inclk];
288 clk_index[OUT] = clk_map[OUT][config->outclk];
289
290 /* We only have output clock for ideal ratio mode */
291 clk = asrc_priv->asrck_clk[clk_index[ideal ? OUT : IN]];
292
293 div[IN] = clk_get_rate(clk) / inrate;
294 if (div[IN] == 0) {
295 pair_err("failed to support input sample rate %dHz by asrck_%x\n",
296 inrate, clk_index[ideal ? OUT : IN]);
297 return -EINVAL;
298 }
299
300 clk = asrc_priv->asrck_clk[clk_index[OUT]];
301
302 /* Use fixed output rate for Ideal Ratio mode (INCLK_NONE) */
303 if (ideal)
304 div[OUT] = clk_get_rate(clk) / IDEAL_RATIO_RATE;
305 else
306 div[OUT] = clk_get_rate(clk) / outrate;
307
308 if (div[OUT] == 0) {
309 pair_err("failed to support output sample rate %dHz by asrck_%x\n",
310 outrate, clk_index[OUT]);
311 return -EINVAL;
312 }
313
314 /* Set the channel number */
315 channels = config->channel_num;
316
317 if (asrc_priv->channel_bits < 4)
318 channels /= 2;
319
320 /* Update channels for current pair */
321 regmap_update_bits(asrc_priv->regmap, REG_ASRCNCR,
322 ASRCNCR_ANCi_MASK(index, asrc_priv->channel_bits),
323 ASRCNCR_ANCi(index, channels, asrc_priv->channel_bits));
324
325 /* Default setting: Automatic selection for processing mode */
326 regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
327 ASRCTR_ATSi_MASK(index), ASRCTR_ATS(index));
328 regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
329 ASRCTR_USRi_MASK(index), 0);
330
331 /* Set the input and output clock sources */
332 regmap_update_bits(asrc_priv->regmap, REG_ASRCSR,
333 ASRCSR_AICSi_MASK(index) | ASRCSR_AOCSi_MASK(index),
334 ASRCSR_AICS(index, clk_index[IN]) |
335 ASRCSR_AOCS(index, clk_index[OUT]));
336
337 /* Calculate the input clock divisors */
338 indiv = fsl_asrc_cal_asrck_divisor(pair, div[IN]);
339 outdiv = fsl_asrc_cal_asrck_divisor(pair, div[OUT]);
340
341 /* Suppose indiv and outdiv includes prescaler, so add its MASK too */
342 regmap_update_bits(asrc_priv->regmap, REG_ASRCDR(index),
343 ASRCDRi_AOCPi_MASK(index) | ASRCDRi_AICPi_MASK(index) |
344 ASRCDRi_AOCDi_MASK(index) | ASRCDRi_AICDi_MASK(index),
345 ASRCDRi_AOCP(index, outdiv) | ASRCDRi_AICP(index, indiv));
346
347 /* Implement word_width configurations */
348 regmap_update_bits(asrc_priv->regmap, REG_ASRMCR1(index),
349 ASRMCR1i_OW16_MASK | ASRMCR1i_IWD_MASK,
350 ASRMCR1i_OW16(config->output_word_width) |
351 ASRMCR1i_IWD(config->input_word_width));
352
353 /* Enable BUFFER STALL */
354 regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index),
355 ASRMCRi_BUFSTALLi_MASK, ASRMCRi_BUFSTALLi);
356
357 /* Set default thresholds for input and output FIFO */
358 fsl_asrc_set_watermarks(pair, ASRC_INPUTFIFO_THRESHOLD,
359 ASRC_INPUTFIFO_THRESHOLD);
360
361 /* Configure the followings only for Ideal Ratio mode */
362 if (!ideal)
363 return 0;
364
365 /* Clear ASTSx bit to use Ideal Ratio mode */
366 regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
367 ASRCTR_ATSi_MASK(index), 0);
368
369 /* Enable Ideal Ratio mode */
370 regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
371 ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index),
372 ASRCTR_IDR(index) | ASRCTR_USR(index));
373
374 /* Apply configurations for pre- and post-processing */
375 regmap_update_bits(asrc_priv->regmap, REG_ASRCFG,
376 ASRCFG_PREMODi_MASK(index) | ASRCFG_POSTMODi_MASK(index),
377 ASRCFG_PREMOD(index, process_option[in][out][0]) |
378 ASRCFG_POSTMOD(index, process_option[in][out][1]));
379
380 return fsl_asrc_set_ideal_ratio(pair, inrate, outrate);
381}
382
383/**
384 * Start the assigned ASRC pair
385 *
386 * It enables the assigned pair and makes it stopped at the stall level.
387 */
388static void fsl_asrc_start_pair(struct fsl_asrc_pair *pair)
389{
390 struct fsl_asrc *asrc_priv = pair->asrc_priv;
391 enum asrc_pair_index index = pair->index;
392 int reg, retry = 10, i;
393
394 /* Enable the current pair */
395 regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
396 ASRCTR_ASRCEi_MASK(index), ASRCTR_ASRCE(index));
397
398 /* Wait for status of initialization */
399 do {
400 udelay(5);
401 regmap_read(asrc_priv->regmap, REG_ASRCFG, &reg);
402 reg &= ASRCFG_INIRQi_MASK(index);
403 } while (!reg && --retry);
404
405 /* Make the input fifo to ASRC STALL level */
406 regmap_read(asrc_priv->regmap, REG_ASRCNCR, &reg);
407 for (i = 0; i < pair->channels * 4; i++)
408 regmap_write(asrc_priv->regmap, REG_ASRDI(index), 0);
409
410 /* Enable overload interrupt */
411 regmap_write(asrc_priv->regmap, REG_ASRIER, ASRIER_AOLIE);
412}
413
414/**
415 * Stop the assigned ASRC pair
416 */
417static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair)
418{
419 struct fsl_asrc *asrc_priv = pair->asrc_priv;
420 enum asrc_pair_index index = pair->index;
421
422 /* Stop the current pair */
423 regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
424 ASRCTR_ASRCEi_MASK(index), 0);
425}
426
427/**
428 * Get DMA channel according to the pair and direction.
429 */
430struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir)
431{
432 struct fsl_asrc *asrc_priv = pair->asrc_priv;
433 enum asrc_pair_index index = pair->index;
434 char name[4];
435
436 sprintf(name, "%cx%c", dir == IN ? 'r' : 't', index + 'a');
437
438 return dma_request_slave_channel(&asrc_priv->pdev->dev, name);
439}
440EXPORT_SYMBOL_GPL(fsl_asrc_get_dma_channel);
441
442static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
443 struct snd_pcm_hw_params *params,
444 struct snd_soc_dai *dai)
445{
446 struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai);
447 int width = snd_pcm_format_width(params_format(params));
448 struct snd_pcm_runtime *runtime = substream->runtime;
449 struct fsl_asrc_pair *pair = runtime->private_data;
450 unsigned int channels = params_channels(params);
451 unsigned int rate = params_rate(params);
452 struct asrc_config config;
453 int word_width, ret;
454
455 ret = fsl_asrc_request_pair(channels, pair);
456 if (ret) {
457 dev_err(dai->dev, "fail to request asrc pair\n");
458 return ret;
459 }
460
461 pair->config = &config;
462
463 if (width == 16)
464 width = ASRC_WIDTH_16_BIT;
465 else
466 width = ASRC_WIDTH_24_BIT;
467
468 if (asrc_priv->asrc_width == 16)
469 word_width = ASRC_WIDTH_16_BIT;
470 else
471 word_width = ASRC_WIDTH_24_BIT;
472
473 config.pair = pair->index;
474 config.channel_num = channels;
475 config.inclk = INCLK_NONE;
476 config.outclk = OUTCLK_ASRCK1_CLK;
477
478 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
479 config.input_word_width = width;
480 config.output_word_width = word_width;
481 config.input_sample_rate = rate;
482 config.output_sample_rate = asrc_priv->asrc_rate;
483 } else {
484 config.input_word_width = word_width;
485 config.output_word_width = width;
486 config.input_sample_rate = asrc_priv->asrc_rate;
487 config.output_sample_rate = rate;
488 }
489
490 ret = fsl_asrc_config_pair(pair);
491 if (ret) {
492 dev_err(dai->dev, "fail to config asrc pair\n");
493 return ret;
494 }
495
496 return 0;
497}
498
499static int fsl_asrc_dai_hw_free(struct snd_pcm_substream *substream,
500 struct snd_soc_dai *dai)
501{
502 struct snd_pcm_runtime *runtime = substream->runtime;
503 struct fsl_asrc_pair *pair = runtime->private_data;
504
505 if (pair)
506 fsl_asrc_release_pair(pair);
507
508 return 0;
509}
510
511static int fsl_asrc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
512 struct snd_soc_dai *dai)
513{
514 struct snd_pcm_runtime *runtime = substream->runtime;
515 struct fsl_asrc_pair *pair = runtime->private_data;
516
517 switch (cmd) {
518 case SNDRV_PCM_TRIGGER_START:
519 case SNDRV_PCM_TRIGGER_RESUME:
520 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
521 fsl_asrc_start_pair(pair);
522 break;
523 case SNDRV_PCM_TRIGGER_STOP:
524 case SNDRV_PCM_TRIGGER_SUSPEND:
525 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
526 fsl_asrc_stop_pair(pair);
527 break;
528 default:
529 return -EINVAL;
530 }
531
532 return 0;
533}
534
535static struct snd_soc_dai_ops fsl_asrc_dai_ops = {
536 .hw_params = fsl_asrc_dai_hw_params,
537 .hw_free = fsl_asrc_dai_hw_free,
538 .trigger = fsl_asrc_dai_trigger,
539};
540
541static int fsl_asrc_dai_probe(struct snd_soc_dai *dai)
542{
543 struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai);
544
545 snd_soc_dai_init_dma_data(dai, &asrc_priv->dma_params_tx,
546 &asrc_priv->dma_params_rx);
547
548 return 0;
549}
550
551#define FSL_ASRC_RATES SNDRV_PCM_RATE_8000_192000
552#define FSL_ASRC_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \
553 SNDRV_PCM_FMTBIT_S16_LE | \
554 SNDRV_PCM_FORMAT_S20_3LE)
555
556static struct snd_soc_dai_driver fsl_asrc_dai = {
557 .probe = fsl_asrc_dai_probe,
558 .playback = {
559 .stream_name = "ASRC-Playback",
560 .channels_min = 1,
561 .channels_max = 10,
562 .rates = FSL_ASRC_RATES,
563 .formats = FSL_ASRC_FORMATS,
564 },
565 .capture = {
566 .stream_name = "ASRC-Capture",
567 .channels_min = 1,
568 .channels_max = 10,
569 .rates = FSL_ASRC_RATES,
570 .formats = FSL_ASRC_FORMATS,
571 },
572 .ops = &fsl_asrc_dai_ops,
573};
574
575static const struct snd_soc_component_driver fsl_asrc_component = {
576 .name = "fsl-asrc-dai",
577};
578
579static bool fsl_asrc_readable_reg(struct device *dev, unsigned int reg)
580{
581 switch (reg) {
582 case REG_ASRCTR:
583 case REG_ASRIER:
584 case REG_ASRCNCR:
585 case REG_ASRCFG:
586 case REG_ASRCSR:
587 case REG_ASRCDR1:
588 case REG_ASRCDR2:
589 case REG_ASRSTR:
590 case REG_ASRPM1:
591 case REG_ASRPM2:
592 case REG_ASRPM3:
593 case REG_ASRPM4:
594 case REG_ASRPM5:
595 case REG_ASRTFR1:
596 case REG_ASRCCR:
597 case REG_ASRDOA:
598 case REG_ASRDOB:
599 case REG_ASRDOC:
600 case REG_ASRIDRHA:
601 case REG_ASRIDRLA:
602 case REG_ASRIDRHB:
603 case REG_ASRIDRLB:
604 case REG_ASRIDRHC:
605 case REG_ASRIDRLC:
606 case REG_ASR76K:
607 case REG_ASR56K:
608 case REG_ASRMCRA:
609 case REG_ASRFSTA:
610 case REG_ASRMCRB:
611 case REG_ASRFSTB:
612 case REG_ASRMCRC:
613 case REG_ASRFSTC:
614 case REG_ASRMCR1A:
615 case REG_ASRMCR1B:
616 case REG_ASRMCR1C:
617 return true;
618 default:
619 return false;
620 }
621}
622
623static bool fsl_asrc_volatile_reg(struct device *dev, unsigned int reg)
624{
625 switch (reg) {
626 case REG_ASRSTR:
627 case REG_ASRDIA:
628 case REG_ASRDIB:
629 case REG_ASRDIC:
630 case REG_ASRDOA:
631 case REG_ASRDOB:
632 case REG_ASRDOC:
633 case REG_ASRFSTA:
634 case REG_ASRFSTB:
635 case REG_ASRFSTC:
636 case REG_ASRCFG:
637 return true;
638 default:
639 return false;
640 }
641}
642
643static bool fsl_asrc_writeable_reg(struct device *dev, unsigned int reg)
644{
645 switch (reg) {
646 case REG_ASRCTR:
647 case REG_ASRIER:
648 case REG_ASRCNCR:
649 case REG_ASRCFG:
650 case REG_ASRCSR:
651 case REG_ASRCDR1:
652 case REG_ASRCDR2:
653 case REG_ASRSTR:
654 case REG_ASRPM1:
655 case REG_ASRPM2:
656 case REG_ASRPM3:
657 case REG_ASRPM4:
658 case REG_ASRPM5:
659 case REG_ASRTFR1:
660 case REG_ASRCCR:
661 case REG_ASRDIA:
662 case REG_ASRDIB:
663 case REG_ASRDIC:
664 case REG_ASRIDRHA:
665 case REG_ASRIDRLA:
666 case REG_ASRIDRHB:
667 case REG_ASRIDRLB:
668 case REG_ASRIDRHC:
669 case REG_ASRIDRLC:
670 case REG_ASR76K:
671 case REG_ASR56K:
672 case REG_ASRMCRA:
673 case REG_ASRMCRB:
674 case REG_ASRMCRC:
675 case REG_ASRMCR1A:
676 case REG_ASRMCR1B:
677 case REG_ASRMCR1C:
678 return true;
679 default:
680 return false;
681 }
682}
683
684static struct regmap_config fsl_asrc_regmap_config = {
685 .reg_bits = 32,
686 .reg_stride = 4,
687 .val_bits = 32,
688
689 .max_register = REG_ASRMCR1C,
690 .readable_reg = fsl_asrc_readable_reg,
691 .volatile_reg = fsl_asrc_volatile_reg,
692 .writeable_reg = fsl_asrc_writeable_reg,
693 .cache_type = REGCACHE_RBTREE,
694};
695
696/**
697 * Initialize ASRC registers with a default configurations
698 */
699static int fsl_asrc_init(struct fsl_asrc *asrc_priv)
700{
701 /* Halt ASRC internal FP when input FIFO needs data for pair A, B, C */
702 regmap_write(asrc_priv->regmap, REG_ASRCTR, ASRCTR_ASRCEN);
703
704 /* Disable interrupt by default */
705 regmap_write(asrc_priv->regmap, REG_ASRIER, 0x0);
706
707 /* Apply recommended settings for parameters from Reference Manual */
708 regmap_write(asrc_priv->regmap, REG_ASRPM1, 0x7fffff);
709 regmap_write(asrc_priv->regmap, REG_ASRPM2, 0x255555);
710 regmap_write(asrc_priv->regmap, REG_ASRPM3, 0xff7280);
711 regmap_write(asrc_priv->regmap, REG_ASRPM4, 0xff7280);
712 regmap_write(asrc_priv->regmap, REG_ASRPM5, 0xff7280);
713
714 /* Base address for task queue FIFO. Set to 0x7C */
715 regmap_update_bits(asrc_priv->regmap, REG_ASRTFR1,
716 ASRTFR1_TF_BASE_MASK, ASRTFR1_TF_BASE(0xfc));
717
718 /* Set the processing clock for 76KHz to 133M */
719 regmap_write(asrc_priv->regmap, REG_ASR76K, 0x06D6);
720
721 /* Set the processing clock for 56KHz to 133M */
722 return regmap_write(asrc_priv->regmap, REG_ASR56K, 0x0947);
723}
724
725/**
726 * Interrupt handler for ASRC
727 */
728static irqreturn_t fsl_asrc_isr(int irq, void *dev_id)
729{
730 struct fsl_asrc *asrc_priv = (struct fsl_asrc *)dev_id;
731 struct device *dev = &asrc_priv->pdev->dev;
732 enum asrc_pair_index index;
733 u32 status;
734
735 regmap_read(asrc_priv->regmap, REG_ASRSTR, &status);
736
737 /* Clean overload error */
738 regmap_write(asrc_priv->regmap, REG_ASRSTR, ASRSTR_AOLE);
739
740 /*
741 * We here use dev_dbg() for all exceptions because ASRC itself does
742 * not care if FIFO overflowed or underrun while a warning in the
743 * interrupt would result a ridged conversion.
744 */
745 for (index = ASRC_PAIR_A; index < ASRC_PAIR_MAX_NUM; index++) {
746 if (!asrc_priv->pair[index])
747 continue;
748
749 if (status & ASRSTR_ATQOL) {
750 asrc_priv->pair[index]->error |= ASRC_TASK_Q_OVERLOAD;
751 dev_dbg(dev, "ASRC Task Queue FIFO overload\n");
752 }
753
754 if (status & ASRSTR_AOOL(index)) {
755 asrc_priv->pair[index]->error |= ASRC_OUTPUT_TASK_OVERLOAD;
756 pair_dbg("Output Task Overload\n");
757 }
758
759 if (status & ASRSTR_AIOL(index)) {
760 asrc_priv->pair[index]->error |= ASRC_INPUT_TASK_OVERLOAD;
761 pair_dbg("Input Task Overload\n");
762 }
763
764 if (status & ASRSTR_AODO(index)) {
765 asrc_priv->pair[index]->error |= ASRC_OUTPUT_BUFFER_OVERFLOW;
766 pair_dbg("Output Data Buffer has overflowed\n");
767 }
768
769 if (status & ASRSTR_AIDU(index)) {
770 asrc_priv->pair[index]->error |= ASRC_INPUT_BUFFER_UNDERRUN;
771 pair_dbg("Input Data Buffer has underflowed\n");
772 }
773 }
774
775 return IRQ_HANDLED;
776}
777
778static int fsl_asrc_probe(struct platform_device *pdev)
779{
780 struct device_node *np = pdev->dev.of_node;
781 struct fsl_asrc *asrc_priv;
782 struct resource *res;
783 void __iomem *regs;
784 int irq, ret, i;
785 char tmp[16];
786
787 asrc_priv = devm_kzalloc(&pdev->dev, sizeof(*asrc_priv), GFP_KERNEL);
788 if (!asrc_priv)
789 return -ENOMEM;
790
791 asrc_priv->pdev = pdev;
792 strcpy(asrc_priv->name, np->name);
793
794 /* Get the addresses and IRQ */
795 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
796 regs = devm_ioremap_resource(&pdev->dev, res);
797 if (IS_ERR(regs))
798 return PTR_ERR(regs);
799
800 asrc_priv->paddr = res->start;
801
802 /* Register regmap and let it prepare core clock */
803 if (of_property_read_bool(np, "big-endian"))
804 fsl_asrc_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG;
805
806 asrc_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "mem", regs,
807 &fsl_asrc_regmap_config);
808 if (IS_ERR(asrc_priv->regmap)) {
809 dev_err(&pdev->dev, "failed to init regmap\n");
810 return PTR_ERR(asrc_priv->regmap);
811 }
812
813 irq = platform_get_irq(pdev, 0);
814 if (irq < 0) {
815 dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
816 return irq;
817 }
818
819 ret = devm_request_irq(&pdev->dev, irq, fsl_asrc_isr, 0,
820 asrc_priv->name, asrc_priv);
821 if (ret) {
822 dev_err(&pdev->dev, "failed to claim irq %u: %d\n", irq, ret);
823 return ret;
824 }
825
826 asrc_priv->mem_clk = devm_clk_get(&pdev->dev, "mem");
827 if (IS_ERR(asrc_priv->mem_clk)) {
828 dev_err(&pdev->dev, "failed to get mem clock\n");
829 return PTR_ERR(asrc_priv->ipg_clk);
830 }
831
832 asrc_priv->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
833 if (IS_ERR(asrc_priv->ipg_clk)) {
834 dev_err(&pdev->dev, "failed to get ipg clock\n");
835 return PTR_ERR(asrc_priv->ipg_clk);
836 }
837
838 for (i = 0; i < ASRC_CLK_MAX_NUM; i++) {
839 sprintf(tmp, "asrck_%x", i);
840 asrc_priv->asrck_clk[i] = devm_clk_get(&pdev->dev, tmp);
841 if (IS_ERR(asrc_priv->asrck_clk[i])) {
842 dev_err(&pdev->dev, "failed to get %s clock\n", tmp);
843 return PTR_ERR(asrc_priv->asrck_clk[i]);
844 }
845 }
846
847 if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx35-asrc")) {
848 asrc_priv->channel_bits = 3;
849 clk_map[IN] = input_clk_map_imx35;
850 clk_map[OUT] = output_clk_map_imx35;
851 } else {
852 asrc_priv->channel_bits = 4;
853 clk_map[IN] = input_clk_map_imx53;
854 clk_map[OUT] = output_clk_map_imx53;
855 }
856
857 ret = fsl_asrc_init(asrc_priv);
858 if (ret) {
859 dev_err(&pdev->dev, "failed to init asrc %d\n", ret);
860 return -EINVAL;
861 }
862
863 asrc_priv->channel_avail = 10;
864
865 ret = of_property_read_u32(np, "fsl,asrc-rate",
866 &asrc_priv->asrc_rate);
867 if (ret) {
868 dev_err(&pdev->dev, "failed to get output rate\n");
869 return -EINVAL;
870 }
871
872 ret = of_property_read_u32(np, "fsl,asrc-width",
873 &asrc_priv->asrc_width);
874 if (ret) {
875 dev_err(&pdev->dev, "failed to get output width\n");
876 return -EINVAL;
877 }
878
879 if (asrc_priv->asrc_width != 16 && asrc_priv->asrc_width != 24) {
880 dev_warn(&pdev->dev, "unsupported width, switching to 24bit\n");
881 asrc_priv->asrc_width = 24;
882 }
883
884 platform_set_drvdata(pdev, asrc_priv);
885 pm_runtime_enable(&pdev->dev);
886 spin_lock_init(&asrc_priv->lock);
887
888 ret = devm_snd_soc_register_component(&pdev->dev, &fsl_asrc_component,
889 &fsl_asrc_dai, 1);
890 if (ret) {
891 dev_err(&pdev->dev, "failed to register ASoC DAI\n");
892 return ret;
893 }
894
895 ret = devm_snd_soc_register_platform(&pdev->dev, &fsl_asrc_platform);
896 if (ret) {
897 dev_err(&pdev->dev, "failed to register ASoC platform\n");
898 return ret;
899 }
900
901 dev_info(&pdev->dev, "driver registered\n");
902
903 return 0;
904}
905
906#if CONFIG_PM_RUNTIME
907static int fsl_asrc_runtime_resume(struct device *dev)
908{
909 struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
910 int i;
911
912 clk_prepare_enable(asrc_priv->mem_clk);
913 clk_prepare_enable(asrc_priv->ipg_clk);
914 for (i = 0; i < ASRC_CLK_MAX_NUM; i++)
915 clk_prepare_enable(asrc_priv->asrck_clk[i]);
916
917 return 0;
918}
919
920static int fsl_asrc_runtime_suspend(struct device *dev)
921{
922 struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
923 int i;
924
925 for (i = 0; i < ASRC_CLK_MAX_NUM; i++)
926 clk_disable_unprepare(asrc_priv->asrck_clk[i]);
927 clk_disable_unprepare(asrc_priv->ipg_clk);
928 clk_disable_unprepare(asrc_priv->mem_clk);
929
930 return 0;
931}
932#endif /* CONFIG_PM_RUNTIME */
933
934#if CONFIG_PM_SLEEP
935static int fsl_asrc_suspend(struct device *dev)
936{
937 struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
938
939 regcache_cache_only(asrc_priv->regmap, true);
940 regcache_mark_dirty(asrc_priv->regmap);
941
942 return 0;
943}
944
945static int fsl_asrc_resume(struct device *dev)
946{
947 struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
948 u32 asrctr;
949
950 /* Stop all pairs provisionally */
951 regmap_read(asrc_priv->regmap, REG_ASRCTR, &asrctr);
952 regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
953 ASRCTR_ASRCEi_ALL_MASK, 0);
954
955 /* Restore all registers */
956 regcache_cache_only(asrc_priv->regmap, false);
957 regcache_sync(asrc_priv->regmap);
958
959 /* Restart enabled pairs */
960 regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
961 ASRCTR_ASRCEi_ALL_MASK, asrctr);
962
963 return 0;
964}
965#endif /* CONFIG_PM_SLEEP */
966
967static const struct dev_pm_ops fsl_asrc_pm = {
968 SET_RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, NULL)
969 SET_SYSTEM_SLEEP_PM_OPS(fsl_asrc_suspend, fsl_asrc_resume)
970};
971
972static const struct of_device_id fsl_asrc_ids[] = {
973 { .compatible = "fsl,imx35-asrc", },
974 { .compatible = "fsl,imx53-asrc", },
975 {}
976};
977MODULE_DEVICE_TABLE(of, fsl_asrc_ids);
978
979static struct platform_driver fsl_asrc_driver = {
980 .probe = fsl_asrc_probe,
981 .driver = {
982 .name = "fsl-asrc",
983 .of_match_table = fsl_asrc_ids,
984 .pm = &fsl_asrc_pm,
985 },
986};
987module_platform_driver(fsl_asrc_driver);
988
989MODULE_DESCRIPTION("Freescale ASRC ASoC driver");
990MODULE_AUTHOR("Nicolin Chen <nicoleotsuka@gmail.com>");
991MODULE_ALIAS("platform:fsl-asrc");
992MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h
new file mode 100644
index 000000000000..a3f211f53c23
--- /dev/null
+++ b/sound/soc/fsl/fsl_asrc.h
@@ -0,0 +1,461 @@
1/*
2 * fsl_asrc.h - Freescale ASRC ALSA SoC header file
3 *
4 * Copyright (C) 2014 Freescale Semiconductor, Inc.
5 *
6 * Author: Nicolin Chen <nicoleotsuka@gmail.com>
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.
11 */
12
13#ifndef _FSL_ASRC_H
14#define _FSL_ASRC_H
15
16#define IN 0
17#define OUT 1
18
19#define ASRC_DMA_BUFFER_NUM 2
20#define ASRC_INPUTFIFO_THRESHOLD 32
21#define ASRC_OUTPUTFIFO_THRESHOLD 32
22#define ASRC_FIFO_THRESHOLD_MIN 0
23#define ASRC_FIFO_THRESHOLD_MAX 63
24#define ASRC_DMA_BUFFER_SIZE (1024 * 48 * 4)
25#define ASRC_MAX_BUFFER_SIZE (1024 * 48)
26#define ASRC_OUTPUT_LAST_SAMPLE 8
27
28#define IDEAL_RATIO_RATE 1000000
29
30#define REG_ASRCTR 0x00
31#define REG_ASRIER 0x04
32#define REG_ASRCNCR 0x0C
33#define REG_ASRCFG 0x10
34#define REG_ASRCSR 0x14
35
36#define REG_ASRCDR1 0x18
37#define REG_ASRCDR2 0x1C
38#define REG_ASRCDR(i) ((i < 2) ? REG_ASRCDR1 : REG_ASRCDR2)
39
40#define REG_ASRSTR 0x20
41#define REG_ASRRA 0x24
42#define REG_ASRRB 0x28
43#define REG_ASRRC 0x2C
44#define REG_ASRPM1 0x40
45#define REG_ASRPM2 0x44
46#define REG_ASRPM3 0x48
47#define REG_ASRPM4 0x4C
48#define REG_ASRPM5 0x50
49#define REG_ASRTFR1 0x54
50#define REG_ASRCCR 0x5C
51
52#define REG_ASRDIA 0x60
53#define REG_ASRDOA 0x64
54#define REG_ASRDIB 0x68
55#define REG_ASRDOB 0x6C
56#define REG_ASRDIC 0x70
57#define REG_ASRDOC 0x74
58#define REG_ASRDI(i) (REG_ASRDIA + (i << 3))
59#define REG_ASRDO(i) (REG_ASRDOA + (i << 3))
60#define REG_ASRDx(x, i) (x == IN ? REG_ASRDI(i) : REG_ASRDO(i))
61
62#define REG_ASRIDRHA 0x80
63#define REG_ASRIDRLA 0x84
64#define REG_ASRIDRHB 0x88
65#define REG_ASRIDRLB 0x8C
66#define REG_ASRIDRHC 0x90
67#define REG_ASRIDRLC 0x94
68#define REG_ASRIDRH(i) (REG_ASRIDRHA + (i << 3))
69#define REG_ASRIDRL(i) (REG_ASRIDRLA + (i << 3))
70
71#define REG_ASR76K 0x98
72#define REG_ASR56K 0x9C
73
74#define REG_ASRMCRA 0xA0
75#define REG_ASRFSTA 0xA4
76#define REG_ASRMCRB 0xA8
77#define REG_ASRFSTB 0xAC
78#define REG_ASRMCRC 0xB0
79#define REG_ASRFSTC 0xB4
80#define REG_ASRMCR(i) (REG_ASRMCRA + (i << 3))
81#define REG_ASRFST(i) (REG_ASRFSTA + (i << 3))
82
83#define REG_ASRMCR1A 0xC0
84#define REG_ASRMCR1B 0xC4
85#define REG_ASRMCR1C 0xC8
86#define REG_ASRMCR1(i) (REG_ASRMCR1A + (i << 2))
87
88
89/* REG0 0x00 REG_ASRCTR */
90#define ASRCTR_ATSi_SHIFT(i) (20 + i)
91#define ASRCTR_ATSi_MASK(i) (1 << ASRCTR_ATSi_SHIFT(i))
92#define ASRCTR_ATS(i) (1 << ASRCTR_ATSi_SHIFT(i))
93#define ASRCTR_USRi_SHIFT(i) (14 + (i << 1))
94#define ASRCTR_USRi_MASK(i) (1 << ASRCTR_USRi_SHIFT(i))
95#define ASRCTR_USR(i) (1 << ASRCTR_USRi_SHIFT(i))
96#define ASRCTR_IDRi_SHIFT(i) (13 + (i << 1))
97#define ASRCTR_IDRi_MASK(i) (1 << ASRCTR_IDRi_SHIFT(i))
98#define ASRCTR_IDR(i) (1 << ASRCTR_IDRi_SHIFT(i))
99#define ASRCTR_SRST_SHIFT 4
100#define ASRCTR_SRST_MASK (1 << ASRCTR_SRST_SHIFT)
101#define ASRCTR_SRST (1 << ASRCTR_SRST_SHIFT)
102#define ASRCTR_ASRCEi_SHIFT(i) (1 + i)
103#define ASRCTR_ASRCEi_MASK(i) (1 << ASRCTR_ASRCEi_SHIFT(i))
104#define ASRCTR_ASRCE(i) (1 << ASRCTR_ASRCEi_SHIFT(i))
105#define ASRCTR_ASRCEi_ALL_MASK (0x7 << ASRCTR_ASRCEi_SHIFT(0))
106#define ASRCTR_ASRCEN_SHIFT 0
107#define ASRCTR_ASRCEN_MASK (1 << ASRCTR_ASRCEN_SHIFT)
108#define ASRCTR_ASRCEN (1 << ASRCTR_ASRCEN_SHIFT)
109
110/* REG1 0x04 REG_ASRIER */
111#define ASRIER_AFPWE_SHIFT 7
112#define ASRIER_AFPWE_MASK (1 << ASRIER_AFPWE_SHIFT)
113#define ASRIER_AFPWE (1 << ASRIER_AFPWE_SHIFT)
114#define ASRIER_AOLIE_SHIFT 6
115#define ASRIER_AOLIE_MASK (1 << ASRIER_AOLIE_SHIFT)
116#define ASRIER_AOLIE (1 << ASRIER_AOLIE_SHIFT)
117#define ASRIER_ADOEi_SHIFT(i) (3 + i)
118#define ASRIER_ADOEi_MASK(i) (1 << ASRIER_ADOEi_SHIFT(i))
119#define ASRIER_ADOE(i) (1 << ASRIER_ADOEi_SHIFT(i))
120#define ASRIER_ADIEi_SHIFT(i) (0 + i)
121#define ASRIER_ADIEi_MASK(i) (1 << ASRIER_ADIEi_SHIFT(i))
122#define ASRIER_ADIE(i) (1 << ASRIER_ADIEi_SHIFT(i))
123
124/* REG2 0x0C REG_ASRCNCR */
125#define ASRCNCR_ANCi_SHIFT(i, b) (b * i)
126#define ASRCNCR_ANCi_MASK(i, b) (((1 << b) - 1) << ASRCNCR_ANCi_SHIFT(i, b))
127#define ASRCNCR_ANCi(i, v, b) ((v << ASRCNCR_ANCi_SHIFT(i, b)) & ASRCNCR_ANCi_MASK(i, b))
128
129/* REG3 0x10 REG_ASRCFG */
130#define ASRCFG_INIRQi_SHIFT(i) (21 + i)
131#define ASRCFG_INIRQi_MASK(i) (1 << ASRCFG_INIRQi_SHIFT(i))
132#define ASRCFG_INIRQi (1 << ASRCFG_INIRQi_SHIFT(i))
133#define ASRCFG_NDPRi_SHIFT(i) (18 + i)
134#define ASRCFG_NDPRi_MASK(i) (1 << ASRCFG_NDPRi_SHIFT(i))
135#define ASRCFG_NDPRi (1 << ASRCFG_NDPRi_SHIFT(i))
136#define ASRCFG_POSTMODi_SHIFT(i) (8 + (i << 2))
137#define ASRCFG_POSTMODi_WIDTH 2
138#define ASRCFG_POSTMODi_MASK(i) (((1 << ASRCFG_POSTMODi_WIDTH) - 1) << ASRCFG_POSTMODi_SHIFT(i))
139#define ASRCFG_POSTMOD(i, v) ((v) << ASRCFG_POSTMODi_SHIFT(i))
140#define ASRCFG_POSTMODi_UP(i) (0 << ASRCFG_POSTMODi_SHIFT(i))
141#define ASRCFG_POSTMODi_DCON(i) (1 << ASRCFG_POSTMODi_SHIFT(i))
142#define ASRCFG_POSTMODi_DOWN(i) (2 << ASRCFG_POSTMODi_SHIFT(i))
143#define ASRCFG_PREMODi_SHIFT(i) (6 + (i << 2))
144#define ASRCFG_PREMODi_WIDTH 2
145#define ASRCFG_PREMODi_MASK(i) (((1 << ASRCFG_PREMODi_WIDTH) - 1) << ASRCFG_PREMODi_SHIFT(i))
146#define ASRCFG_PREMOD(i, v) ((v) << ASRCFG_PREMODi_SHIFT(i))
147#define ASRCFG_PREMODi_UP(i) (0 << ASRCFG_PREMODi_SHIFT(i))
148#define ASRCFG_PREMODi_DCON(i) (1 << ASRCFG_PREMODi_SHIFT(i))
149#define ASRCFG_PREMODi_DOWN(i) (2 << ASRCFG_PREMODi_SHIFT(i))
150#define ASRCFG_PREMODi_BYPASS(i) (3 << ASRCFG_PREMODi_SHIFT(i))
151
152/* REG4 0x14 REG_ASRCSR */
153#define ASRCSR_AxCSi_WIDTH 4
154#define ASRCSR_AxCSi_MASK ((1 << ASRCSR_AxCSi_WIDTH) - 1)
155#define ASRCSR_AOCSi_SHIFT(i) (12 + (i << 2))
156#define ASRCSR_AOCSi_MASK(i) (((1 << ASRCSR_AxCSi_WIDTH) - 1) << ASRCSR_AOCSi_SHIFT(i))
157#define ASRCSR_AOCS(i, v) ((v) << ASRCSR_AOCSi_SHIFT(i))
158#define ASRCSR_AICSi_SHIFT(i) (i << 2)
159#define ASRCSR_AICSi_MASK(i) (((1 << ASRCSR_AxCSi_WIDTH) - 1) << ASRCSR_AICSi_SHIFT(i))
160#define ASRCSR_AICS(i, v) ((v) << ASRCSR_AICSi_SHIFT(i))
161
162/* REG5&6 0x18 & 0x1C REG_ASRCDR1 & ASRCDR2 */
163#define ASRCDRi_AxCPi_WIDTH 3
164#define ASRCDRi_AICPi_SHIFT(i) (0 + (i % 2) * 6)
165#define ASRCDRi_AICPi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AICPi_SHIFT(i))
166#define ASRCDRi_AICP(i, v) ((v) << ASRCDRi_AICPi_SHIFT(i))
167#define ASRCDRi_AICDi_SHIFT(i) (3 + (i % 2) * 6)
168#define ASRCDRi_AICDi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AICDi_SHIFT(i))
169#define ASRCDRi_AICD(i, v) ((v) << ASRCDRi_AICDi_SHIFT(i))
170#define ASRCDRi_AOCPi_SHIFT(i) ((i < 2) ? 12 + i * 6 : 6)
171#define ASRCDRi_AOCPi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AOCPi_SHIFT(i))
172#define ASRCDRi_AOCP(i, v) ((v) << ASRCDRi_AOCPi_SHIFT(i))
173#define ASRCDRi_AOCDi_SHIFT(i) ((i < 2) ? 15 + i * 6 : 9)
174#define ASRCDRi_AOCDi_MASK(i) (((1 << ASRCDRi_AxCPi_WIDTH) - 1) << ASRCDRi_AOCDi_SHIFT(i))
175#define ASRCDRi_AOCD(i, v) ((v) << ASRCDRi_AOCDi_SHIFT(i))
176
177/* REG7 0x20 REG_ASRSTR */
178#define ASRSTR_DSLCNT_SHIFT 21
179#define ASRSTR_DSLCNT_MASK (1 << ASRSTR_DSLCNT_SHIFT)
180#define ASRSTR_DSLCNT (1 << ASRSTR_DSLCNT_SHIFT)
181#define ASRSTR_ATQOL_SHIFT 20
182#define ASRSTR_ATQOL_MASK (1 << ASRSTR_ATQOL_SHIFT)
183#define ASRSTR_ATQOL (1 << ASRSTR_ATQOL_SHIFT)
184#define ASRSTR_AOOLi_SHIFT(i) (17 + i)
185#define ASRSTR_AOOLi_MASK(i) (1 << ASRSTR_AOOLi_SHIFT(i))
186#define ASRSTR_AOOL(i) (1 << ASRSTR_AOOLi_SHIFT(i))
187#define ASRSTR_AIOLi_SHIFT(i) (14 + i)
188#define ASRSTR_AIOLi_MASK(i) (1 << ASRSTR_AIOLi_SHIFT(i))
189#define ASRSTR_AIOL(i) (1 << ASRSTR_AIOLi_SHIFT(i))
190#define ASRSTR_AODOi_SHIFT(i) (11 + i)
191#define ASRSTR_AODOi_MASK(i) (1 << ASRSTR_AODOi_SHIFT(i))
192#define ASRSTR_AODO(i) (1 << ASRSTR_AODOi_SHIFT(i))
193#define ASRSTR_AIDUi_SHIFT(i) (8 + i)
194#define ASRSTR_AIDUi_MASK(i) (1 << ASRSTR_AIDUi_SHIFT(i))
195#define ASRSTR_AIDU(i) (1 << ASRSTR_AIDUi_SHIFT(i))
196#define ASRSTR_FPWT_SHIFT 7
197#define ASRSTR_FPWT_MASK (1 << ASRSTR_FPWT_SHIFT)
198#define ASRSTR_FPWT (1 << ASRSTR_FPWT_SHIFT)
199#define ASRSTR_AOLE_SHIFT 6
200#define ASRSTR_AOLE_MASK (1 << ASRSTR_AOLE_SHIFT)
201#define ASRSTR_AOLE (1 << ASRSTR_AOLE_SHIFT)
202#define ASRSTR_AODEi_SHIFT(i) (3 + i)
203#define ASRSTR_AODFi_MASK(i) (1 << ASRSTR_AODEi_SHIFT(i))
204#define ASRSTR_AODF(i) (1 << ASRSTR_AODEi_SHIFT(i))
205#define ASRSTR_AIDEi_SHIFT(i) (0 + i)
206#define ASRSTR_AIDEi_MASK(i) (1 << ASRSTR_AIDEi_SHIFT(i))
207#define ASRSTR_AIDE(i) (1 << ASRSTR_AIDEi_SHIFT(i))
208
209/* REG10 0x54 REG_ASRTFR1 */
210#define ASRTFR1_TF_BASE_WIDTH 7
211#define ASRTFR1_TF_BASE_SHIFT 6
212#define ASRTFR1_TF_BASE_MASK (((1 << ASRTFR1_TF_BASE_WIDTH) - 1) << ASRTFR1_TF_BASE_SHIFT)
213#define ASRTFR1_TF_BASE(i) ((i) << ASRTFR1_TF_BASE_SHIFT)
214
215/*
216 * REG22 0xA0 REG_ASRMCRA
217 * REG24 0xA8 REG_ASRMCRB
218 * REG26 0xB0 REG_ASRMCRC
219 */
220#define ASRMCRi_ZEROBUFi_SHIFT 23
221#define ASRMCRi_ZEROBUFi_MASK (1 << ASRMCRi_ZEROBUFi_SHIFT)
222#define ASRMCRi_ZEROBUFi (1 << ASRMCRi_ZEROBUFi_SHIFT)
223#define ASRMCRi_EXTTHRSHi_SHIFT 22
224#define ASRMCRi_EXTTHRSHi_MASK (1 << ASRMCRi_EXTTHRSHi_SHIFT)
225#define ASRMCRi_EXTTHRSHi (1 << ASRMCRi_EXTTHRSHi_SHIFT)
226#define ASRMCRi_BUFSTALLi_SHIFT 21
227#define ASRMCRi_BUFSTALLi_MASK (1 << ASRMCRi_BUFSTALLi_SHIFT)
228#define ASRMCRi_BUFSTALLi (1 << ASRMCRi_BUFSTALLi_SHIFT)
229#define ASRMCRi_BYPASSPOLYi_SHIFT 20
230#define ASRMCRi_BYPASSPOLYi_MASK (1 << ASRMCRi_BYPASSPOLYi_SHIFT)
231#define ASRMCRi_BYPASSPOLYi (1 << ASRMCRi_BYPASSPOLYi_SHIFT)
232#define ASRMCRi_OUTFIFO_THRESHOLD_WIDTH 6
233#define ASRMCRi_OUTFIFO_THRESHOLD_SHIFT 12
234#define ASRMCRi_OUTFIFO_THRESHOLD_MASK (((1 << ASRMCRi_OUTFIFO_THRESHOLD_WIDTH) - 1) << ASRMCRi_OUTFIFO_THRESHOLD_SHIFT)
235#define ASRMCRi_OUTFIFO_THRESHOLD(v) (((v) << ASRMCRi_OUTFIFO_THRESHOLD_SHIFT) & ASRMCRi_OUTFIFO_THRESHOLD_MASK)
236#define ASRMCRi_RSYNIFi_SHIFT 11
237#define ASRMCRi_RSYNIFi_MASK (1 << ASRMCRi_RSYNIFi_SHIFT)
238#define ASRMCRi_RSYNIFi (1 << ASRMCRi_RSYNIFi_SHIFT)
239#define ASRMCRi_RSYNOFi_SHIFT 10
240#define ASRMCRi_RSYNOFi_MASK (1 << ASRMCRi_RSYNOFi_SHIFT)
241#define ASRMCRi_RSYNOFi (1 << ASRMCRi_RSYNOFi_SHIFT)
242#define ASRMCRi_INFIFO_THRESHOLD_WIDTH 6
243#define ASRMCRi_INFIFO_THRESHOLD_SHIFT 0
244#define ASRMCRi_INFIFO_THRESHOLD_MASK (((1 << ASRMCRi_INFIFO_THRESHOLD_WIDTH) - 1) << ASRMCRi_INFIFO_THRESHOLD_SHIFT)
245#define ASRMCRi_INFIFO_THRESHOLD(v) (((v) << ASRMCRi_INFIFO_THRESHOLD_SHIFT) & ASRMCRi_INFIFO_THRESHOLD_MASK)
246
247/*
248 * REG23 0xA4 REG_ASRFSTA
249 * REG25 0xAC REG_ASRFSTB
250 * REG27 0xB4 REG_ASRFSTC
251 */
252#define ASRFSTi_OAFi_SHIFT 23
253#define ASRFSTi_OAFi_MASK (1 << ASRFSTi_OAFi_SHIFT)
254#define ASRFSTi_OAFi (1 << ASRFSTi_OAFi_SHIFT)
255#define ASRFSTi_OUTPUT_FIFO_WIDTH 7
256#define ASRFSTi_OUTPUT_FIFO_SHIFT 12
257#define ASRFSTi_OUTPUT_FIFO_MASK (((1 << ASRFSTi_OUTPUT_FIFO_WIDTH) - 1) << ASRFSTi_OUTPUT_FIFO_SHIFT)
258#define ASRFSTi_IAEi_SHIFT 11
259#define ASRFSTi_IAEi_MASK (1 << ASRFSTi_OAFi_SHIFT)
260#define ASRFSTi_IAEi (1 << ASRFSTi_OAFi_SHIFT)
261#define ASRFSTi_INPUT_FIFO_WIDTH 7
262#define ASRFSTi_INPUT_FIFO_SHIFT 0
263#define ASRFSTi_INPUT_FIFO_MASK ((1 << ASRFSTi_INPUT_FIFO_WIDTH) - 1)
264
265/* REG28 0xC0 & 0xC4 & 0xC8 REG_ASRMCR1i */
266#define ASRMCR1i_IWD_WIDTH 3
267#define ASRMCR1i_IWD_SHIFT 9
268#define ASRMCR1i_IWD_MASK (((1 << ASRMCR1i_IWD_WIDTH) - 1) << ASRMCR1i_IWD_SHIFT)
269#define ASRMCR1i_IWD(v) ((v) << ASRMCR1i_IWD_SHIFT)
270#define ASRMCR1i_IMSB_SHIFT 8
271#define ASRMCR1i_IMSB_MASK (1 << ASRMCR1i_IMSB_SHIFT)
272#define ASRMCR1i_IMSB_MSB (1 << ASRMCR1i_IMSB_SHIFT)
273#define ASRMCR1i_IMSB_LSB (0 << ASRMCR1i_IMSB_SHIFT)
274#define ASRMCR1i_OMSB_SHIFT 2
275#define ASRMCR1i_OMSB_MASK (1 << ASRMCR1i_OMSB_SHIFT)
276#define ASRMCR1i_OMSB_MSB (1 << ASRMCR1i_OMSB_SHIFT)
277#define ASRMCR1i_OMSB_LSB (0 << ASRMCR1i_OMSB_SHIFT)
278#define ASRMCR1i_OSGN_SHIFT 1
279#define ASRMCR1i_OSGN_MASK (1 << ASRMCR1i_OSGN_SHIFT)
280#define ASRMCR1i_OSGN (1 << ASRMCR1i_OSGN_SHIFT)
281#define ASRMCR1i_OW16_SHIFT 0
282#define ASRMCR1i_OW16_MASK (1 << ASRMCR1i_OW16_SHIFT)
283#define ASRMCR1i_OW16(v) ((v) << ASRMCR1i_OW16_SHIFT)
284
285
286enum asrc_pair_index {
287 ASRC_INVALID_PAIR = -1,
288 ASRC_PAIR_A = 0,
289 ASRC_PAIR_B = 1,
290 ASRC_PAIR_C = 2,
291};
292
293#define ASRC_PAIR_MAX_NUM (ASRC_PAIR_C + 1)
294
295enum asrc_inclk {
296 INCLK_NONE = 0x03,
297 INCLK_ESAI_RX = 0x00,
298 INCLK_SSI1_RX = 0x01,
299 INCLK_SSI2_RX = 0x02,
300 INCLK_SSI3_RX = 0x07,
301 INCLK_SPDIF_RX = 0x04,
302 INCLK_MLB_CLK = 0x05,
303 INCLK_PAD = 0x06,
304 INCLK_ESAI_TX = 0x08,
305 INCLK_SSI1_TX = 0x09,
306 INCLK_SSI2_TX = 0x0a,
307 INCLK_SSI3_TX = 0x0b,
308 INCLK_SPDIF_TX = 0x0c,
309 INCLK_ASRCK1_CLK = 0x0f,
310};
311
312enum asrc_outclk {
313 OUTCLK_NONE = 0x03,
314 OUTCLK_ESAI_TX = 0x00,
315 OUTCLK_SSI1_TX = 0x01,
316 OUTCLK_SSI2_TX = 0x02,
317 OUTCLK_SSI3_TX = 0x07,
318 OUTCLK_SPDIF_TX = 0x04,
319 OUTCLK_MLB_CLK = 0x05,
320 OUTCLK_PAD = 0x06,
321 OUTCLK_ESAI_RX = 0x08,
322 OUTCLK_SSI1_RX = 0x09,
323 OUTCLK_SSI2_RX = 0x0a,
324 OUTCLK_SSI3_RX = 0x0b,
325 OUTCLK_SPDIF_RX = 0x0c,
326 OUTCLK_ASRCK1_CLK = 0x0f,
327};
328
329#define ASRC_CLK_MAX_NUM 16
330
331enum asrc_word_width {
332 ASRC_WIDTH_24_BIT = 0,
333 ASRC_WIDTH_16_BIT = 1,
334 ASRC_WIDTH_8_BIT = 2,
335};
336
337struct asrc_config {
338 enum asrc_pair_index pair;
339 unsigned int channel_num;
340 unsigned int buffer_num;
341 unsigned int dma_buffer_size;
342 unsigned int input_sample_rate;
343 unsigned int output_sample_rate;
344 enum asrc_word_width input_word_width;
345 enum asrc_word_width output_word_width;
346 enum asrc_inclk inclk;
347 enum asrc_outclk outclk;
348};
349
350struct asrc_req {
351 unsigned int chn_num;
352 enum asrc_pair_index index;
353};
354
355struct asrc_querybuf {
356 unsigned int buffer_index;
357 unsigned int input_length;
358 unsigned int output_length;
359 unsigned long input_offset;
360 unsigned long output_offset;
361};
362
363struct asrc_convert_buffer {
364 void *input_buffer_vaddr;
365 void *output_buffer_vaddr;
366 unsigned int input_buffer_length;
367 unsigned int output_buffer_length;
368};
369
370struct asrc_status_flags {
371 enum asrc_pair_index index;
372 unsigned int overload_error;
373};
374
375enum asrc_error_status {
376 ASRC_TASK_Q_OVERLOAD = 0x01,
377 ASRC_OUTPUT_TASK_OVERLOAD = 0x02,
378 ASRC_INPUT_TASK_OVERLOAD = 0x04,
379 ASRC_OUTPUT_BUFFER_OVERFLOW = 0x08,
380 ASRC_INPUT_BUFFER_UNDERRUN = 0x10,
381};
382
383struct dma_block {
384 dma_addr_t dma_paddr;
385 void *dma_vaddr;
386 unsigned int length;
387};
388
389/**
390 * fsl_asrc_pair: ASRC Pair private data
391 *
392 * @asrc_priv: pointer to its parent module
393 * @config: configuration profile
394 * @error: error record
395 * @index: pair index (ASRC_PAIR_A, ASRC_PAIR_B, ASRC_PAIR_C)
396 * @channels: occupied channel number
397 * @desc: input and output dma descriptors
398 * @dma_chan: inputer and output DMA channels
399 * @dma_data: private dma data
400 * @pos: hardware pointer position
401 * @private: pair private area
402 */
403struct fsl_asrc_pair {
404 struct fsl_asrc *asrc_priv;
405 struct asrc_config *config;
406 unsigned int error;
407
408 enum asrc_pair_index index;
409 unsigned int channels;
410
411 struct dma_async_tx_descriptor *desc[2];
412 struct dma_chan *dma_chan[2];
413 struct imx_dma_data dma_data;
414 unsigned int pos;
415
416 void *private;
417};
418
419/**
420 * fsl_asrc_pair: ASRC private data
421 *
422 * @dma_params_rx: DMA parameters for receive channel
423 * @dma_params_tx: DMA parameters for transmit channel
424 * @pdev: platform device pointer
425 * @regmap: regmap handler
426 * @paddr: physical address to the base address of registers
427 * @mem_clk: clock source to access register
428 * @ipg_clk: clock source to drive peripheral
429 * @asrck_clk: clock sources to driver ASRC internal logic
430 * @lock: spin lock for resource protection
431 * @pair: pair pointers
432 * @channel_bits: width of ASRCNCR register for each pair
433 * @channel_avail: non-occupied channel numbers
434 * @asrc_rate: default sample rate for ASoC Back-Ends
435 * @asrc_width: default sample width for ASoC Back-Ends
436 * @name: driver name
437 */
438struct fsl_asrc {
439 struct snd_dmaengine_dai_dma_data dma_params_rx;
440 struct snd_dmaengine_dai_dma_data dma_params_tx;
441 struct platform_device *pdev;
442 struct regmap *regmap;
443 unsigned long paddr;
444 struct clk *mem_clk;
445 struct clk *ipg_clk;
446 struct clk *asrck_clk[ASRC_CLK_MAX_NUM];
447 spinlock_t lock;
448
449 struct fsl_asrc_pair *pair[ASRC_PAIR_MAX_NUM];
450 unsigned int channel_bits;
451 unsigned int channel_avail;
452
453 int asrc_rate;
454 int asrc_width;
455
456 char name[32];
457};
458
459extern struct snd_soc_platform_driver fsl_asrc_platform;
460struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir);
461#endif /* _FSL_ASRC_H */
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
new file mode 100644
index 000000000000..5b1e73e97817
--- /dev/null
+++ b/sound/soc/fsl/fsl_asrc_dma.c
@@ -0,0 +1,386 @@
1/*
2 * Freescale ASRC ALSA SoC Platform (DMA) driver
3 *
4 * Copyright (C) 2014 Freescale Semiconductor, Inc.
5 *
6 * Author: Nicolin Chen <nicoleotsuka@gmail.com>
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.
11 */
12
13#include <linux/dma-mapping.h>
14#include <linux/module.h>
15#include <linux/platform_data/dma-imx.h>
16#include <sound/dmaengine_pcm.h>
17#include <sound/pcm_params.h>
18
19#include "fsl_asrc.h"
20
21#define FSL_ASRC_DMABUF_SIZE (256 * 1024)
22
23static struct snd_pcm_hardware snd_imx_hardware = {
24 .info = SNDRV_PCM_INFO_INTERLEAVED |
25 SNDRV_PCM_INFO_BLOCK_TRANSFER |
26 SNDRV_PCM_INFO_MMAP |
27 SNDRV_PCM_INFO_MMAP_VALID |
28 SNDRV_PCM_INFO_PAUSE |
29 SNDRV_PCM_INFO_RESUME,
30 .buffer_bytes_max = FSL_ASRC_DMABUF_SIZE,
31 .period_bytes_min = 128,
32 .period_bytes_max = 65535, /* Limited by SDMA engine */
33 .periods_min = 2,
34 .periods_max = 255,
35 .fifo_size = 0,
36};
37
38static bool filter(struct dma_chan *chan, void *param)
39{
40 if (!imx_dma_is_general_purpose(chan))
41 return false;
42
43 chan->private = param;
44
45 return true;
46}
47
48static void fsl_asrc_dma_complete(void *arg)
49{
50 struct snd_pcm_substream *substream = arg;
51 struct snd_pcm_runtime *runtime = substream->runtime;
52 struct fsl_asrc_pair *pair = runtime->private_data;
53
54 pair->pos += snd_pcm_lib_period_bytes(substream);
55 if (pair->pos >= snd_pcm_lib_buffer_bytes(substream))
56 pair->pos = 0;
57
58 snd_pcm_period_elapsed(substream);
59}
60
61static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream *substream)
62{
63 u8 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? OUT : IN;
64 struct snd_soc_pcm_runtime *rtd = substream->private_data;
65 struct snd_pcm_runtime *runtime = substream->runtime;
66 struct fsl_asrc_pair *pair = runtime->private_data;
67 struct device *dev = rtd->platform->dev;
68 unsigned long flags = DMA_CTRL_ACK;
69
70 /* Prepare and submit Front-End DMA channel */
71 if (!substream->runtime->no_period_wakeup)
72 flags |= DMA_PREP_INTERRUPT;
73
74 pair->pos = 0;
75 pair->desc[!dir] = dmaengine_prep_dma_cyclic(
76 pair->dma_chan[!dir], runtime->dma_addr,
77 snd_pcm_lib_buffer_bytes(substream),
78 snd_pcm_lib_period_bytes(substream),
79 dir == OUT ? DMA_TO_DEVICE : DMA_FROM_DEVICE, flags);
80 if (!pair->desc[!dir]) {
81 dev_err(dev, "failed to prepare slave DMA for Front-End\n");
82 return -ENOMEM;
83 }
84
85 pair->desc[!dir]->callback = fsl_asrc_dma_complete;
86 pair->desc[!dir]->callback_param = substream;
87
88 dmaengine_submit(pair->desc[!dir]);
89
90 /* Prepare and submit Back-End DMA channel */
91 pair->desc[dir] = dmaengine_prep_dma_cyclic(
92 pair->dma_chan[dir], 0xffff, 64, 64, DMA_DEV_TO_DEV, 0);
93 if (!pair->desc[dir]) {
94 dev_err(dev, "failed to prepare slave DMA for Back-End\n");
95 return -ENOMEM;
96 }
97
98 dmaengine_submit(pair->desc[dir]);
99
100 return 0;
101}
102
103static int fsl_asrc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
104{
105 struct snd_pcm_runtime *runtime = substream->runtime;
106 struct fsl_asrc_pair *pair = runtime->private_data;
107 int ret;
108
109 switch (cmd) {
110 case SNDRV_PCM_TRIGGER_START:
111 case SNDRV_PCM_TRIGGER_RESUME:
112 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
113 ret = fsl_asrc_dma_prepare_and_submit(substream);
114 if (ret)
115 return ret;
116 dma_async_issue_pending(pair->dma_chan[IN]);
117 dma_async_issue_pending(pair->dma_chan[OUT]);
118 break;
119 case SNDRV_PCM_TRIGGER_STOP:
120 case SNDRV_PCM_TRIGGER_SUSPEND:
121 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
122 dmaengine_terminate_all(pair->dma_chan[OUT]);
123 dmaengine_terminate_all(pair->dma_chan[IN]);
124 break;
125 default:
126 return -EINVAL;
127 }
128
129 return 0;
130}
131
132static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream,
133 struct snd_pcm_hw_params *params)
134{
135 enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
136 struct snd_soc_pcm_runtime *rtd = substream->private_data;
137 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
138 struct snd_dmaengine_dai_dma_data *dma_params_fe = NULL;
139 struct snd_dmaengine_dai_dma_data *dma_params_be = NULL;
140 struct snd_pcm_runtime *runtime = substream->runtime;
141 struct fsl_asrc_pair *pair = runtime->private_data;
142 struct fsl_asrc *asrc_priv = pair->asrc_priv;
143 struct dma_slave_config config_fe, config_be;
144 enum asrc_pair_index index = pair->index;
145 struct device *dev = rtd->platform->dev;
146 int stream = substream->stream;
147 struct imx_dma_data *tmp_data;
148 struct snd_soc_dpcm *dpcm;
149 struct dma_chan *tmp_chan;
150 struct device *dev_be;
151 u8 dir = tx ? OUT : IN;
152 dma_cap_mask_t mask;
153 int ret;
154
155 /* Fetch the Back-End dma_data from DPCM */
156 list_for_each_entry(dpcm, &rtd->dpcm[stream].be_clients, list_be) {
157 struct snd_soc_pcm_runtime *be = dpcm->be;
158 struct snd_pcm_substream *substream_be;
159 struct snd_soc_dai *dai = be->cpu_dai;
160
161 if (dpcm->fe != rtd)
162 continue;
163
164 substream_be = snd_soc_dpcm_get_substream(be, stream);
165 dma_params_be = snd_soc_dai_get_dma_data(dai, substream_be);
166 dev_be = dai->dev;
167 break;
168 }
169
170 if (!dma_params_be) {
171 dev_err(dev, "failed to get the substream of Back-End\n");
172 return -EINVAL;
173 }
174
175 /* Override dma_data of the Front-End and config its dmaengine */
176 dma_params_fe = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
177 dma_params_fe->addr = asrc_priv->paddr + REG_ASRDx(!dir, index);
178 dma_params_fe->maxburst = dma_params_be->maxburst;
179
180 pair->dma_chan[!dir] = fsl_asrc_get_dma_channel(pair, !dir);
181 if (!pair->dma_chan[!dir]) {
182 dev_err(dev, "failed to request DMA channel\n");
183 return -EINVAL;
184 }
185
186 memset(&config_fe, 0, sizeof(config_fe));
187 ret = snd_dmaengine_pcm_prepare_slave_config(substream, params, &config_fe);
188 if (ret) {
189 dev_err(dev, "failed to prepare DMA config for Front-End\n");
190 return ret;
191 }
192
193 ret = dmaengine_slave_config(pair->dma_chan[!dir], &config_fe);
194 if (ret) {
195 dev_err(dev, "failed to config DMA channel for Front-End\n");
196 return ret;
197 }
198
199 /* Request and config DMA channel for Back-End */
200 dma_cap_zero(mask);
201 dma_cap_set(DMA_SLAVE, mask);
202 dma_cap_set(DMA_CYCLIC, mask);
203
204 /* Get DMA request of Back-End */
205 tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
206 tmp_data = tmp_chan->private;
207 pair->dma_data.dma_request = tmp_data->dma_request;
208 dma_release_channel(tmp_chan);
209
210 /* Get DMA request of Front-End */
211 tmp_chan = fsl_asrc_get_dma_channel(pair, dir);
212 tmp_data = tmp_chan->private;
213 pair->dma_data.dma_request2 = tmp_data->dma_request;
214 pair->dma_data.peripheral_type = tmp_data->peripheral_type;
215 pair->dma_data.priority = tmp_data->priority;
216 dma_release_channel(tmp_chan);
217
218 pair->dma_chan[dir] = dma_request_channel(mask, filter, &pair->dma_data);
219 if (!pair->dma_chan[dir]) {
220 dev_err(dev, "failed to request DMA channel for Back-End\n");
221 return -EINVAL;
222 }
223
224 if (asrc_priv->asrc_width == 16)
225 buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
226 else
227 buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
228
229 config_be.direction = DMA_DEV_TO_DEV;
230 config_be.src_addr_width = buswidth;
231 config_be.src_maxburst = dma_params_be->maxburst;
232 config_be.dst_addr_width = buswidth;
233 config_be.dst_maxburst = dma_params_be->maxburst;
234
235 if (tx) {
236 config_be.src_addr = asrc_priv->paddr + REG_ASRDO(index);
237 config_be.dst_addr = dma_params_be->addr;
238 } else {
239 config_be.dst_addr = asrc_priv->paddr + REG_ASRDI(index);
240 config_be.src_addr = dma_params_be->addr;
241 }
242
243 ret = dmaengine_slave_config(pair->dma_chan[dir], &config_be);
244 if (ret) {
245 dev_err(dev, "failed to config DMA channel for Back-End\n");
246 return ret;
247 }
248
249 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
250
251 return 0;
252}
253
254static int fsl_asrc_dma_hw_free(struct snd_pcm_substream *substream)
255{
256 struct snd_pcm_runtime *runtime = substream->runtime;
257 struct fsl_asrc_pair *pair = runtime->private_data;
258
259 snd_pcm_set_runtime_buffer(substream, NULL);
260
261 if (pair->dma_chan[IN])
262 dma_release_channel(pair->dma_chan[IN]);
263
264 if (pair->dma_chan[OUT])
265 dma_release_channel(pair->dma_chan[OUT]);
266
267 pair->dma_chan[IN] = NULL;
268 pair->dma_chan[OUT] = NULL;
269
270 return 0;
271}
272
273static int fsl_asrc_dma_startup(struct snd_pcm_substream *substream)
274{
275 struct snd_soc_pcm_runtime *rtd = substream->private_data;
276 struct snd_pcm_runtime *runtime = substream->runtime;
277 struct device *dev = rtd->platform->dev;
278 struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
279 struct fsl_asrc_pair *pair;
280
281 pair = kzalloc(sizeof(struct fsl_asrc_pair), GFP_KERNEL);
282 if (!pair) {
283 dev_err(dev, "failed to allocate pair\n");
284 return -ENOMEM;
285 }
286
287 pair->asrc_priv = asrc_priv;
288
289 runtime->private_data = pair;
290
291 snd_pcm_hw_constraint_integer(substream->runtime,
292 SNDRV_PCM_HW_PARAM_PERIODS);
293 snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
294
295 return 0;
296}
297
298static int fsl_asrc_dma_shutdown(struct snd_pcm_substream *substream)
299{
300 struct snd_pcm_runtime *runtime = substream->runtime;
301 struct fsl_asrc_pair *pair = runtime->private_data;
302 struct fsl_asrc *asrc_priv = pair->asrc_priv;
303
304 if (pair && asrc_priv->pair[pair->index] == pair)
305 asrc_priv->pair[pair->index] = NULL;
306
307 kfree(pair);
308
309 return 0;
310}
311
312static snd_pcm_uframes_t fsl_asrc_dma_pcm_pointer(struct snd_pcm_substream *substream)
313{
314 struct snd_pcm_runtime *runtime = substream->runtime;
315 struct fsl_asrc_pair *pair = runtime->private_data;
316
317 return bytes_to_frames(substream->runtime, pair->pos);
318}
319
320static struct snd_pcm_ops fsl_asrc_dma_pcm_ops = {
321 .ioctl = snd_pcm_lib_ioctl,
322 .hw_params = fsl_asrc_dma_hw_params,
323 .hw_free = fsl_asrc_dma_hw_free,
324 .trigger = fsl_asrc_dma_trigger,
325 .open = fsl_asrc_dma_startup,
326 .close = fsl_asrc_dma_shutdown,
327 .pointer = fsl_asrc_dma_pcm_pointer,
328};
329
330static int fsl_asrc_dma_pcm_new(struct snd_soc_pcm_runtime *rtd)
331{
332 struct snd_card *card = rtd->card->snd_card;
333 struct snd_pcm_substream *substream;
334 struct snd_pcm *pcm = rtd->pcm;
335 int ret, i;
336
337 ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
338 if (ret) {
339 dev_err(card->dev, "failed to set DMA mask\n");
340 return ret;
341 }
342
343 for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) {
344 substream = pcm->streams[i].substream;
345 if (!substream)
346 continue;
347
348 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
349 FSL_ASRC_DMABUF_SIZE, &substream->dma_buffer);
350 if (ret) {
351 dev_err(card->dev, "failed to allocate DMA buffer\n");
352 goto err;
353 }
354 }
355
356 return 0;
357
358err:
359 if (--i == 0 && pcm->streams[i].substream)
360 snd_dma_free_pages(&pcm->streams[i].substream->dma_buffer);
361
362 return ret;
363}
364
365static void fsl_asrc_dma_pcm_free(struct snd_pcm *pcm)
366{
367 struct snd_pcm_substream *substream;
368 int i;
369
370 for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) {
371 substream = pcm->streams[i].substream;
372 if (!substream)
373 continue;
374
375 snd_dma_free_pages(&substream->dma_buffer);
376 substream->dma_buffer.area = NULL;
377 substream->dma_buffer.addr = 0;
378 }
379}
380
381struct snd_soc_platform_driver fsl_asrc_platform = {
382 .ops = &fsl_asrc_dma_pcm_ops,
383 .pcm_new = fsl_asrc_dma_pcm_new,
384 .pcm_free = fsl_asrc_dma_pcm_free,
385};
386EXPORT_SYMBOL_GPL(fsl_asrc_platform);