xref: /openbmc/linux/sound/soc/fsl/fsl_asrc.c (revision 3117bb3109dc223e186302f5dc8ce9ed04adca90)
1*3117bb31SNicolin Chen /*
2*3117bb31SNicolin Chen  * Freescale ASRC ALSA SoC Digital Audio Interface (DAI) driver
3*3117bb31SNicolin Chen  *
4*3117bb31SNicolin Chen  * Copyright (C) 2014 Freescale Semiconductor, Inc.
5*3117bb31SNicolin Chen  *
6*3117bb31SNicolin Chen  * Author: Nicolin Chen <nicoleotsuka@gmail.com>
7*3117bb31SNicolin Chen  *
8*3117bb31SNicolin Chen  * This file is licensed under the terms of the GNU General Public License
9*3117bb31SNicolin Chen  * version 2. This program is licensed "as is" without any warranty of any
10*3117bb31SNicolin Chen  * kind, whether express or implied.
11*3117bb31SNicolin Chen  */
12*3117bb31SNicolin Chen 
13*3117bb31SNicolin Chen #include <linux/clk.h>
14*3117bb31SNicolin Chen #include <linux/delay.h>
15*3117bb31SNicolin Chen #include <linux/dma-mapping.h>
16*3117bb31SNicolin Chen #include <linux/module.h>
17*3117bb31SNicolin Chen #include <linux/of_platform.h>
18*3117bb31SNicolin Chen #include <linux/platform_data/dma-imx.h>
19*3117bb31SNicolin Chen #include <linux/pm_runtime.h>
20*3117bb31SNicolin Chen #include <sound/dmaengine_pcm.h>
21*3117bb31SNicolin Chen #include <sound/pcm_params.h>
22*3117bb31SNicolin Chen 
23*3117bb31SNicolin Chen #include "fsl_asrc.h"
24*3117bb31SNicolin Chen 
25*3117bb31SNicolin Chen #define IDEAL_RATIO_DECIMAL_DEPTH 26
26*3117bb31SNicolin Chen 
27*3117bb31SNicolin Chen #define pair_err(fmt, ...) \
28*3117bb31SNicolin Chen 	dev_err(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
29*3117bb31SNicolin Chen 
30*3117bb31SNicolin Chen #define pair_dbg(fmt, ...) \
31*3117bb31SNicolin Chen 	dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
32*3117bb31SNicolin Chen 
33*3117bb31SNicolin Chen /* Sample rates are aligned with that defined in pcm.h file */
34*3117bb31SNicolin Chen static const u8 process_option[][8][2] = {
35*3117bb31SNicolin Chen 	/* 32kHz 44.1kHz 48kHz   64kHz   88.2kHz 96kHz   176kHz  192kHz */
36*3117bb31SNicolin Chen 	{{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},	/* 5512Hz */
37*3117bb31SNicolin Chen 	{{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},	/* 8kHz */
38*3117bb31SNicolin Chen 	{{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},	/* 11025Hz */
39*3117bb31SNicolin Chen 	{{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},	/* 16kHz */
40*3117bb31SNicolin Chen 	{{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},	/* 22050Hz */
41*3117bb31SNicolin Chen 	{{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},},	/* 32kHz */
42*3117bb31SNicolin Chen 	{{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},},	/* 44.1kHz */
43*3117bb31SNicolin Chen 	{{0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},},	/* 48kHz */
44*3117bb31SNicolin Chen 	{{1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},},	/* 64kHz */
45*3117bb31SNicolin Chen 	{{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},},	/* 88.2kHz */
46*3117bb31SNicolin Chen 	{{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},},	/* 96kHz */
47*3117bb31SNicolin Chen 	{{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},},	/* 176kHz */
48*3117bb31SNicolin Chen 	{{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},},	/* 192kHz */
49*3117bb31SNicolin Chen };
50*3117bb31SNicolin Chen 
51*3117bb31SNicolin Chen /* Corresponding to process_option */
52*3117bb31SNicolin Chen static int supported_input_rate[] = {
53*3117bb31SNicolin Chen 	5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200,
54*3117bb31SNicolin Chen 	96000, 176400, 192000,
55*3117bb31SNicolin Chen };
56*3117bb31SNicolin Chen 
57*3117bb31SNicolin Chen static int supported_asrc_rate[] = {
58*3117bb31SNicolin Chen 	32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000,
59*3117bb31SNicolin Chen };
60*3117bb31SNicolin Chen 
61*3117bb31SNicolin Chen /**
62*3117bb31SNicolin Chen  * The following tables map the relationship between asrc_inclk/asrc_outclk in
63*3117bb31SNicolin Chen  * fsl_asrc.h and the registers of ASRCSR
64*3117bb31SNicolin Chen  */
65*3117bb31SNicolin Chen static unsigned char input_clk_map_imx35[] = {
66*3117bb31SNicolin Chen 	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
67*3117bb31SNicolin Chen };
68*3117bb31SNicolin Chen 
69*3117bb31SNicolin Chen static unsigned char output_clk_map_imx35[] = {
70*3117bb31SNicolin Chen 	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
71*3117bb31SNicolin Chen };
72*3117bb31SNicolin Chen 
73*3117bb31SNicolin Chen /* i.MX53 uses the same map for input and output */
74*3117bb31SNicolin Chen static unsigned char input_clk_map_imx53[] = {
75*3117bb31SNicolin Chen /*	0x0  0x1  0x2  0x3  0x4  0x5  0x6  0x7  0x8  0x9  0xa  0xb  0xc  0xd  0xe  0xf */
76*3117bb31SNicolin Chen 	0x0, 0x1, 0x2, 0x7, 0x4, 0x5, 0x6, 0x3, 0x8, 0x9, 0xa, 0xb, 0xc, 0xf, 0xe, 0xd,
77*3117bb31SNicolin Chen };
78*3117bb31SNicolin Chen 
79*3117bb31SNicolin Chen static unsigned char output_clk_map_imx53[] = {
80*3117bb31SNicolin Chen /*	0x0  0x1  0x2  0x3  0x4  0x5  0x6  0x7  0x8  0x9  0xa  0xb  0xc  0xd  0xe  0xf */
81*3117bb31SNicolin Chen 	0x8, 0x9, 0xa, 0x7, 0xc, 0x5, 0x6, 0xb, 0x0, 0x1, 0x2, 0x3, 0x4, 0xf, 0xe, 0xd,
82*3117bb31SNicolin Chen };
83*3117bb31SNicolin Chen 
84*3117bb31SNicolin Chen static unsigned char *clk_map[2];
85*3117bb31SNicolin Chen 
86*3117bb31SNicolin Chen /**
87*3117bb31SNicolin Chen  * Request ASRC pair
88*3117bb31SNicolin Chen  *
89*3117bb31SNicolin Chen  * It assigns pair by the order of A->C->B because allocation of pair B,
90*3117bb31SNicolin Chen  * within range [ANCA, ANCA+ANCB-1], depends on the channels of pair A
91*3117bb31SNicolin Chen  * while pair A and pair C are comparatively independent.
92*3117bb31SNicolin Chen  */
93*3117bb31SNicolin Chen static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair)
94*3117bb31SNicolin Chen {
95*3117bb31SNicolin Chen 	enum asrc_pair_index index = ASRC_INVALID_PAIR;
96*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = pair->asrc_priv;
97*3117bb31SNicolin Chen 	struct device *dev = &asrc_priv->pdev->dev;
98*3117bb31SNicolin Chen 	unsigned long lock_flags;
99*3117bb31SNicolin Chen 	int i, ret = 0;
100*3117bb31SNicolin Chen 
101*3117bb31SNicolin Chen 	spin_lock_irqsave(&asrc_priv->lock, lock_flags);
102*3117bb31SNicolin Chen 
103*3117bb31SNicolin Chen 	for (i = ASRC_PAIR_A; i < ASRC_PAIR_MAX_NUM; i++) {
104*3117bb31SNicolin Chen 		if (asrc_priv->pair[i] != NULL)
105*3117bb31SNicolin Chen 			continue;
106*3117bb31SNicolin Chen 
107*3117bb31SNicolin Chen 		index = i;
108*3117bb31SNicolin Chen 
109*3117bb31SNicolin Chen 		if (i != ASRC_PAIR_B)
110*3117bb31SNicolin Chen 			break;
111*3117bb31SNicolin Chen 	}
112*3117bb31SNicolin Chen 
113*3117bb31SNicolin Chen 	if (index == ASRC_INVALID_PAIR) {
114*3117bb31SNicolin Chen 		dev_err(dev, "all pairs are busy now\n");
115*3117bb31SNicolin Chen 		ret = -EBUSY;
116*3117bb31SNicolin Chen 	} else if (asrc_priv->channel_avail < channels) {
117*3117bb31SNicolin Chen 		dev_err(dev, "can't afford required channels: %d\n", channels);
118*3117bb31SNicolin Chen 		ret = -EINVAL;
119*3117bb31SNicolin Chen 	} else {
120*3117bb31SNicolin Chen 		asrc_priv->channel_avail -= channels;
121*3117bb31SNicolin Chen 		asrc_priv->pair[index] = pair;
122*3117bb31SNicolin Chen 		pair->channels = channels;
123*3117bb31SNicolin Chen 		pair->index = index;
124*3117bb31SNicolin Chen 	}
125*3117bb31SNicolin Chen 
126*3117bb31SNicolin Chen 	spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
127*3117bb31SNicolin Chen 
128*3117bb31SNicolin Chen 	return ret;
129*3117bb31SNicolin Chen }
130*3117bb31SNicolin Chen 
131*3117bb31SNicolin Chen /**
132*3117bb31SNicolin Chen  * Release ASRC pair
133*3117bb31SNicolin Chen  *
134*3117bb31SNicolin Chen  * It clears the resource from asrc_priv and releases the occupied channels.
135*3117bb31SNicolin Chen  */
136*3117bb31SNicolin Chen static void fsl_asrc_release_pair(struct fsl_asrc_pair *pair)
137*3117bb31SNicolin Chen {
138*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = pair->asrc_priv;
139*3117bb31SNicolin Chen 	enum asrc_pair_index index = pair->index;
140*3117bb31SNicolin Chen 	unsigned long lock_flags;
141*3117bb31SNicolin Chen 
142*3117bb31SNicolin Chen 	/* Make sure the pair is disabled */
143*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
144*3117bb31SNicolin Chen 			   ASRCTR_ASRCEi_MASK(index), 0);
145*3117bb31SNicolin Chen 
146*3117bb31SNicolin Chen 	spin_lock_irqsave(&asrc_priv->lock, lock_flags);
147*3117bb31SNicolin Chen 
148*3117bb31SNicolin Chen 	asrc_priv->channel_avail += pair->channels;
149*3117bb31SNicolin Chen 	asrc_priv->pair[index] = NULL;
150*3117bb31SNicolin Chen 	pair->error = 0;
151*3117bb31SNicolin Chen 
152*3117bb31SNicolin Chen 	spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
153*3117bb31SNicolin Chen }
154*3117bb31SNicolin Chen 
155*3117bb31SNicolin Chen /**
156*3117bb31SNicolin Chen  * Configure input and output thresholds
157*3117bb31SNicolin Chen  */
158*3117bb31SNicolin Chen static void fsl_asrc_set_watermarks(struct fsl_asrc_pair *pair, u32 in, u32 out)
159*3117bb31SNicolin Chen {
160*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = pair->asrc_priv;
161*3117bb31SNicolin Chen 	enum asrc_pair_index index = pair->index;
162*3117bb31SNicolin Chen 
163*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index),
164*3117bb31SNicolin Chen 			   ASRMCRi_EXTTHRSHi_MASK |
165*3117bb31SNicolin Chen 			   ASRMCRi_INFIFO_THRESHOLD_MASK |
166*3117bb31SNicolin Chen 			   ASRMCRi_OUTFIFO_THRESHOLD_MASK,
167*3117bb31SNicolin Chen 			   ASRMCRi_EXTTHRSHi |
168*3117bb31SNicolin Chen 			   ASRMCRi_INFIFO_THRESHOLD(in) |
169*3117bb31SNicolin Chen 			   ASRMCRi_OUTFIFO_THRESHOLD(out));
170*3117bb31SNicolin Chen }
171*3117bb31SNicolin Chen 
172*3117bb31SNicolin Chen /**
173*3117bb31SNicolin Chen  * Calculate the total divisor between asrck clock rate and sample rate
174*3117bb31SNicolin Chen  *
175*3117bb31SNicolin Chen  * It follows the formula clk_rate = samplerate * (2 ^ prescaler) * divider
176*3117bb31SNicolin Chen  */
177*3117bb31SNicolin Chen static u32 fsl_asrc_cal_asrck_divisor(struct fsl_asrc_pair *pair, u32 div)
178*3117bb31SNicolin Chen {
179*3117bb31SNicolin Chen 	u32 ps;
180*3117bb31SNicolin Chen 
181*3117bb31SNicolin Chen 	/* Calculate the divisors: prescaler [2^0, 2^7], divder [1, 8] */
182*3117bb31SNicolin Chen 	for (ps = 0; div > 8; ps++)
183*3117bb31SNicolin Chen 		div >>= 1;
184*3117bb31SNicolin Chen 
185*3117bb31SNicolin Chen 	return ((div - 1) << ASRCDRi_AxCPi_WIDTH) | ps;
186*3117bb31SNicolin Chen }
187*3117bb31SNicolin Chen 
188*3117bb31SNicolin Chen /**
189*3117bb31SNicolin Chen  * Calculate and set the ratio for Ideal Ratio mode only
190*3117bb31SNicolin Chen  *
191*3117bb31SNicolin Chen  * The ratio is a 32-bit fixed point value with 26 fractional bits.
192*3117bb31SNicolin Chen  */
193*3117bb31SNicolin Chen static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair,
194*3117bb31SNicolin Chen 				    int inrate, int outrate)
195*3117bb31SNicolin Chen {
196*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = pair->asrc_priv;
197*3117bb31SNicolin Chen 	enum asrc_pair_index index = pair->index;
198*3117bb31SNicolin Chen 	unsigned long ratio;
199*3117bb31SNicolin Chen 	int i;
200*3117bb31SNicolin Chen 
201*3117bb31SNicolin Chen 	if (!outrate) {
202*3117bb31SNicolin Chen 		pair_err("output rate should not be zero\n");
203*3117bb31SNicolin Chen 		return -EINVAL;
204*3117bb31SNicolin Chen 	}
205*3117bb31SNicolin Chen 
206*3117bb31SNicolin Chen 	/* Calculate the intergal part of the ratio */
207*3117bb31SNicolin Chen 	ratio = (inrate / outrate) << IDEAL_RATIO_DECIMAL_DEPTH;
208*3117bb31SNicolin Chen 
209*3117bb31SNicolin Chen 	/* ... and then the 26 depth decimal part */
210*3117bb31SNicolin Chen 	inrate %= outrate;
211*3117bb31SNicolin Chen 
212*3117bb31SNicolin Chen 	for (i = 1; i <= IDEAL_RATIO_DECIMAL_DEPTH; i++) {
213*3117bb31SNicolin Chen 		inrate <<= 1;
214*3117bb31SNicolin Chen 
215*3117bb31SNicolin Chen 		if (inrate < outrate)
216*3117bb31SNicolin Chen 			continue;
217*3117bb31SNicolin Chen 
218*3117bb31SNicolin Chen 		ratio |= 1 << (IDEAL_RATIO_DECIMAL_DEPTH - i);
219*3117bb31SNicolin Chen 		inrate -= outrate;
220*3117bb31SNicolin Chen 
221*3117bb31SNicolin Chen 		if (!inrate)
222*3117bb31SNicolin Chen 			break;
223*3117bb31SNicolin Chen 	}
224*3117bb31SNicolin Chen 
225*3117bb31SNicolin Chen 	regmap_write(asrc_priv->regmap, REG_ASRIDRL(index), ratio);
226*3117bb31SNicolin Chen 	regmap_write(asrc_priv->regmap, REG_ASRIDRH(index), ratio >> 24);
227*3117bb31SNicolin Chen 
228*3117bb31SNicolin Chen 	return 0;
229*3117bb31SNicolin Chen }
230*3117bb31SNicolin Chen 
231*3117bb31SNicolin Chen /**
232*3117bb31SNicolin Chen  * Configure the assigned ASRC pair
233*3117bb31SNicolin Chen  *
234*3117bb31SNicolin Chen  * It configures those ASRC registers according to a configuration instance
235*3117bb31SNicolin Chen  * of struct asrc_config which includes in/output sample rate, width, channel
236*3117bb31SNicolin Chen  * and clock settings.
237*3117bb31SNicolin Chen  */
238*3117bb31SNicolin Chen static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
239*3117bb31SNicolin Chen {
240*3117bb31SNicolin Chen 	struct asrc_config *config = pair->config;
241*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = pair->asrc_priv;
242*3117bb31SNicolin Chen 	enum asrc_pair_index index = pair->index;
243*3117bb31SNicolin Chen 	u32 inrate = config->input_sample_rate, indiv;
244*3117bb31SNicolin Chen 	u32 outrate = config->output_sample_rate, outdiv;
245*3117bb31SNicolin Chen 	bool ideal = config->inclk == INCLK_NONE;
246*3117bb31SNicolin Chen 	u32 clk_index[2], div[2];
247*3117bb31SNicolin Chen 	int in, out, channels;
248*3117bb31SNicolin Chen 	struct clk *clk;
249*3117bb31SNicolin Chen 
250*3117bb31SNicolin Chen 	if (!config) {
251*3117bb31SNicolin Chen 		pair_err("invalid pair config\n");
252*3117bb31SNicolin Chen 		return -EINVAL;
253*3117bb31SNicolin Chen 	}
254*3117bb31SNicolin Chen 
255*3117bb31SNicolin Chen 	/* Validate channels */
256*3117bb31SNicolin Chen 	if (config->channel_num < 1 || config->channel_num > 10) {
257*3117bb31SNicolin Chen 		pair_err("does not support %d channels\n", config->channel_num);
258*3117bb31SNicolin Chen 		return -EINVAL;
259*3117bb31SNicolin Chen 	}
260*3117bb31SNicolin Chen 
261*3117bb31SNicolin Chen 	/* Validate output width */
262*3117bb31SNicolin Chen 	if (config->output_word_width == ASRC_WIDTH_8_BIT) {
263*3117bb31SNicolin Chen 		pair_err("does not support 8bit width output\n");
264*3117bb31SNicolin Chen 		return -EINVAL;
265*3117bb31SNicolin Chen 	}
266*3117bb31SNicolin Chen 
267*3117bb31SNicolin Chen 	/* Validate input and output sample rates */
268*3117bb31SNicolin Chen 	for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++)
269*3117bb31SNicolin Chen 		if (inrate == supported_input_rate[in])
270*3117bb31SNicolin Chen 			break;
271*3117bb31SNicolin Chen 
272*3117bb31SNicolin Chen 	if (in == ARRAY_SIZE(supported_input_rate)) {
273*3117bb31SNicolin Chen 		pair_err("unsupported input sample rate: %dHz\n", inrate);
274*3117bb31SNicolin Chen 		return -EINVAL;
275*3117bb31SNicolin Chen 	}
276*3117bb31SNicolin Chen 
277*3117bb31SNicolin Chen 	for (out = 0; out < ARRAY_SIZE(supported_asrc_rate); out++)
278*3117bb31SNicolin Chen 		if (outrate == supported_asrc_rate[out])
279*3117bb31SNicolin Chen 			break;
280*3117bb31SNicolin Chen 
281*3117bb31SNicolin Chen 	if (out == ARRAY_SIZE(supported_asrc_rate)) {
282*3117bb31SNicolin Chen 		pair_err("unsupported output sample rate: %dHz\n", outrate);
283*3117bb31SNicolin Chen 		return -EINVAL;
284*3117bb31SNicolin Chen 	}
285*3117bb31SNicolin Chen 
286*3117bb31SNicolin Chen 	/* Validate input and output clock sources */
287*3117bb31SNicolin Chen 	clk_index[IN] = clk_map[IN][config->inclk];
288*3117bb31SNicolin Chen 	clk_index[OUT] = clk_map[OUT][config->outclk];
289*3117bb31SNicolin Chen 
290*3117bb31SNicolin Chen 	/* We only have output clock for ideal ratio mode */
291*3117bb31SNicolin Chen 	clk = asrc_priv->asrck_clk[clk_index[ideal ? OUT : IN]];
292*3117bb31SNicolin Chen 
293*3117bb31SNicolin Chen 	div[IN] = clk_get_rate(clk) / inrate;
294*3117bb31SNicolin Chen 	if (div[IN] == 0) {
295*3117bb31SNicolin Chen 		pair_err("failed to support input sample rate %dHz by asrck_%x\n",
296*3117bb31SNicolin Chen 				inrate, clk_index[ideal ? OUT : IN]);
297*3117bb31SNicolin Chen 		return -EINVAL;
298*3117bb31SNicolin Chen 	}
299*3117bb31SNicolin Chen 
300*3117bb31SNicolin Chen 	clk = asrc_priv->asrck_clk[clk_index[OUT]];
301*3117bb31SNicolin Chen 
302*3117bb31SNicolin Chen 	/* Use fixed output rate for Ideal Ratio mode (INCLK_NONE) */
303*3117bb31SNicolin Chen 	if (ideal)
304*3117bb31SNicolin Chen 		div[OUT] = clk_get_rate(clk) / IDEAL_RATIO_RATE;
305*3117bb31SNicolin Chen 	else
306*3117bb31SNicolin Chen 		div[OUT] = clk_get_rate(clk) / outrate;
307*3117bb31SNicolin Chen 
308*3117bb31SNicolin Chen 	if (div[OUT] == 0) {
309*3117bb31SNicolin Chen 		pair_err("failed to support output sample rate %dHz by asrck_%x\n",
310*3117bb31SNicolin Chen 				outrate, clk_index[OUT]);
311*3117bb31SNicolin Chen 		return -EINVAL;
312*3117bb31SNicolin Chen 	}
313*3117bb31SNicolin Chen 
314*3117bb31SNicolin Chen 	/* Set the channel number */
315*3117bb31SNicolin Chen 	channels = config->channel_num;
316*3117bb31SNicolin Chen 
317*3117bb31SNicolin Chen 	if (asrc_priv->channel_bits < 4)
318*3117bb31SNicolin Chen 		channels /= 2;
319*3117bb31SNicolin Chen 
320*3117bb31SNicolin Chen 	/* Update channels for current pair */
321*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRCNCR,
322*3117bb31SNicolin Chen 			   ASRCNCR_ANCi_MASK(index, asrc_priv->channel_bits),
323*3117bb31SNicolin Chen 			   ASRCNCR_ANCi(index, channels, asrc_priv->channel_bits));
324*3117bb31SNicolin Chen 
325*3117bb31SNicolin Chen 	/* Default setting: Automatic selection for processing mode */
326*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
327*3117bb31SNicolin Chen 			   ASRCTR_ATSi_MASK(index), ASRCTR_ATS(index));
328*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
329*3117bb31SNicolin Chen 			   ASRCTR_USRi_MASK(index), 0);
330*3117bb31SNicolin Chen 
331*3117bb31SNicolin Chen 	/* Set the input and output clock sources */
332*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRCSR,
333*3117bb31SNicolin Chen 			   ASRCSR_AICSi_MASK(index) | ASRCSR_AOCSi_MASK(index),
334*3117bb31SNicolin Chen 			   ASRCSR_AICS(index, clk_index[IN]) |
335*3117bb31SNicolin Chen 			   ASRCSR_AOCS(index, clk_index[OUT]));
336*3117bb31SNicolin Chen 
337*3117bb31SNicolin Chen 	/* Calculate the input clock divisors */
338*3117bb31SNicolin Chen 	indiv = fsl_asrc_cal_asrck_divisor(pair, div[IN]);
339*3117bb31SNicolin Chen 	outdiv = fsl_asrc_cal_asrck_divisor(pair, div[OUT]);
340*3117bb31SNicolin Chen 
341*3117bb31SNicolin Chen 	/* Suppose indiv and outdiv includes prescaler, so add its MASK too */
342*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRCDR(index),
343*3117bb31SNicolin Chen 			   ASRCDRi_AOCPi_MASK(index) | ASRCDRi_AICPi_MASK(index) |
344*3117bb31SNicolin Chen 			   ASRCDRi_AOCDi_MASK(index) | ASRCDRi_AICDi_MASK(index),
345*3117bb31SNicolin Chen 			   ASRCDRi_AOCP(index, outdiv) | ASRCDRi_AICP(index, indiv));
346*3117bb31SNicolin Chen 
347*3117bb31SNicolin Chen 	/* Implement word_width configurations */
348*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRMCR1(index),
349*3117bb31SNicolin Chen 			   ASRMCR1i_OW16_MASK | ASRMCR1i_IWD_MASK,
350*3117bb31SNicolin Chen 			   ASRMCR1i_OW16(config->output_word_width) |
351*3117bb31SNicolin Chen 			   ASRMCR1i_IWD(config->input_word_width));
352*3117bb31SNicolin Chen 
353*3117bb31SNicolin Chen 	/* Enable BUFFER STALL */
354*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index),
355*3117bb31SNicolin Chen 			   ASRMCRi_BUFSTALLi_MASK, ASRMCRi_BUFSTALLi);
356*3117bb31SNicolin Chen 
357*3117bb31SNicolin Chen 	/* Set default thresholds for input and output FIFO */
358*3117bb31SNicolin Chen 	fsl_asrc_set_watermarks(pair, ASRC_INPUTFIFO_THRESHOLD,
359*3117bb31SNicolin Chen 				ASRC_INPUTFIFO_THRESHOLD);
360*3117bb31SNicolin Chen 
361*3117bb31SNicolin Chen 	/* Configure the followings only for Ideal Ratio mode */
362*3117bb31SNicolin Chen 	if (!ideal)
363*3117bb31SNicolin Chen 		return 0;
364*3117bb31SNicolin Chen 
365*3117bb31SNicolin Chen 	/* Clear ASTSx bit to use Ideal Ratio mode */
366*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
367*3117bb31SNicolin Chen 			   ASRCTR_ATSi_MASK(index), 0);
368*3117bb31SNicolin Chen 
369*3117bb31SNicolin Chen 	/* Enable Ideal Ratio mode */
370*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
371*3117bb31SNicolin Chen 			   ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index),
372*3117bb31SNicolin Chen 			   ASRCTR_IDR(index) | ASRCTR_USR(index));
373*3117bb31SNicolin Chen 
374*3117bb31SNicolin Chen 	/* Apply configurations for pre- and post-processing */
375*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRCFG,
376*3117bb31SNicolin Chen 			   ASRCFG_PREMODi_MASK(index) |	ASRCFG_POSTMODi_MASK(index),
377*3117bb31SNicolin Chen 			   ASRCFG_PREMOD(index, process_option[in][out][0]) |
378*3117bb31SNicolin Chen 			   ASRCFG_POSTMOD(index, process_option[in][out][1]));
379*3117bb31SNicolin Chen 
380*3117bb31SNicolin Chen 	return fsl_asrc_set_ideal_ratio(pair, inrate, outrate);
381*3117bb31SNicolin Chen }
382*3117bb31SNicolin Chen 
383*3117bb31SNicolin Chen /**
384*3117bb31SNicolin Chen  * Start the assigned ASRC pair
385*3117bb31SNicolin Chen  *
386*3117bb31SNicolin Chen  * It enables the assigned pair and makes it stopped at the stall level.
387*3117bb31SNicolin Chen  */
388*3117bb31SNicolin Chen static void fsl_asrc_start_pair(struct fsl_asrc_pair *pair)
389*3117bb31SNicolin Chen {
390*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = pair->asrc_priv;
391*3117bb31SNicolin Chen 	enum asrc_pair_index index = pair->index;
392*3117bb31SNicolin Chen 	int reg, retry = 10, i;
393*3117bb31SNicolin Chen 
394*3117bb31SNicolin Chen 	/* Enable the current pair */
395*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
396*3117bb31SNicolin Chen 			   ASRCTR_ASRCEi_MASK(index), ASRCTR_ASRCE(index));
397*3117bb31SNicolin Chen 
398*3117bb31SNicolin Chen 	/* Wait for status of initialization */
399*3117bb31SNicolin Chen 	do {
400*3117bb31SNicolin Chen 		udelay(5);
401*3117bb31SNicolin Chen 		regmap_read(asrc_priv->regmap, REG_ASRCFG, &reg);
402*3117bb31SNicolin Chen 		reg &= ASRCFG_INIRQi_MASK(index);
403*3117bb31SNicolin Chen 	} while (!reg && --retry);
404*3117bb31SNicolin Chen 
405*3117bb31SNicolin Chen 	/* Make the input fifo to ASRC STALL level */
406*3117bb31SNicolin Chen 	regmap_read(asrc_priv->regmap, REG_ASRCNCR, &reg);
407*3117bb31SNicolin Chen 	for (i = 0; i < pair->channels * 4; i++)
408*3117bb31SNicolin Chen 		regmap_write(asrc_priv->regmap, REG_ASRDI(index), 0);
409*3117bb31SNicolin Chen 
410*3117bb31SNicolin Chen 	/* Enable overload interrupt */
411*3117bb31SNicolin Chen 	regmap_write(asrc_priv->regmap, REG_ASRIER, ASRIER_AOLIE);
412*3117bb31SNicolin Chen }
413*3117bb31SNicolin Chen 
414*3117bb31SNicolin Chen /**
415*3117bb31SNicolin Chen  * Stop the assigned ASRC pair
416*3117bb31SNicolin Chen  */
417*3117bb31SNicolin Chen static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair)
418*3117bb31SNicolin Chen {
419*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = pair->asrc_priv;
420*3117bb31SNicolin Chen 	enum asrc_pair_index index = pair->index;
421*3117bb31SNicolin Chen 
422*3117bb31SNicolin Chen 	/* Stop the current pair */
423*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
424*3117bb31SNicolin Chen 			   ASRCTR_ASRCEi_MASK(index), 0);
425*3117bb31SNicolin Chen }
426*3117bb31SNicolin Chen 
427*3117bb31SNicolin Chen /**
428*3117bb31SNicolin Chen  * Get DMA channel according to the pair and direction.
429*3117bb31SNicolin Chen  */
430*3117bb31SNicolin Chen struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir)
431*3117bb31SNicolin Chen {
432*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = pair->asrc_priv;
433*3117bb31SNicolin Chen 	enum asrc_pair_index index = pair->index;
434*3117bb31SNicolin Chen 	char name[4];
435*3117bb31SNicolin Chen 
436*3117bb31SNicolin Chen 	sprintf(name, "%cx%c", dir == IN ? 'r' : 't', index + 'a');
437*3117bb31SNicolin Chen 
438*3117bb31SNicolin Chen 	return dma_request_slave_channel(&asrc_priv->pdev->dev, name);
439*3117bb31SNicolin Chen }
440*3117bb31SNicolin Chen EXPORT_SYMBOL_GPL(fsl_asrc_get_dma_channel);
441*3117bb31SNicolin Chen 
442*3117bb31SNicolin Chen static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
443*3117bb31SNicolin Chen 				  struct snd_pcm_hw_params *params,
444*3117bb31SNicolin Chen 				  struct snd_soc_dai *dai)
445*3117bb31SNicolin Chen {
446*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai);
447*3117bb31SNicolin Chen 	int width = snd_pcm_format_width(params_format(params));
448*3117bb31SNicolin Chen 	struct snd_pcm_runtime *runtime = substream->runtime;
449*3117bb31SNicolin Chen 	struct fsl_asrc_pair *pair = runtime->private_data;
450*3117bb31SNicolin Chen 	unsigned int channels = params_channels(params);
451*3117bb31SNicolin Chen 	unsigned int rate = params_rate(params);
452*3117bb31SNicolin Chen 	struct asrc_config config;
453*3117bb31SNicolin Chen 	int word_width, ret;
454*3117bb31SNicolin Chen 
455*3117bb31SNicolin Chen 	ret = fsl_asrc_request_pair(channels, pair);
456*3117bb31SNicolin Chen 	if (ret) {
457*3117bb31SNicolin Chen 		dev_err(dai->dev, "fail to request asrc pair\n");
458*3117bb31SNicolin Chen 		return ret;
459*3117bb31SNicolin Chen 	}
460*3117bb31SNicolin Chen 
461*3117bb31SNicolin Chen 	pair->config = &config;
462*3117bb31SNicolin Chen 
463*3117bb31SNicolin Chen 	if (width == 16)
464*3117bb31SNicolin Chen 		width = ASRC_WIDTH_16_BIT;
465*3117bb31SNicolin Chen 	else
466*3117bb31SNicolin Chen 		width = ASRC_WIDTH_24_BIT;
467*3117bb31SNicolin Chen 
468*3117bb31SNicolin Chen 	if (asrc_priv->asrc_width == 16)
469*3117bb31SNicolin Chen 		word_width = ASRC_WIDTH_16_BIT;
470*3117bb31SNicolin Chen 	else
471*3117bb31SNicolin Chen 		word_width = ASRC_WIDTH_24_BIT;
472*3117bb31SNicolin Chen 
473*3117bb31SNicolin Chen 	config.pair = pair->index;
474*3117bb31SNicolin Chen 	config.channel_num = channels;
475*3117bb31SNicolin Chen 	config.inclk = INCLK_NONE;
476*3117bb31SNicolin Chen 	config.outclk = OUTCLK_ASRCK1_CLK;
477*3117bb31SNicolin Chen 
478*3117bb31SNicolin Chen 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
479*3117bb31SNicolin Chen 		config.input_word_width   = width;
480*3117bb31SNicolin Chen 		config.output_word_width  = word_width;
481*3117bb31SNicolin Chen 		config.input_sample_rate  = rate;
482*3117bb31SNicolin Chen 		config.output_sample_rate = asrc_priv->asrc_rate;
483*3117bb31SNicolin Chen 	} else {
484*3117bb31SNicolin Chen 		config.input_word_width   = word_width;
485*3117bb31SNicolin Chen 		config.output_word_width  = width;
486*3117bb31SNicolin Chen 		config.input_sample_rate  = asrc_priv->asrc_rate;
487*3117bb31SNicolin Chen 		config.output_sample_rate = rate;
488*3117bb31SNicolin Chen 	}
489*3117bb31SNicolin Chen 
490*3117bb31SNicolin Chen 	ret = fsl_asrc_config_pair(pair);
491*3117bb31SNicolin Chen 	if (ret) {
492*3117bb31SNicolin Chen 		dev_err(dai->dev, "fail to config asrc pair\n");
493*3117bb31SNicolin Chen 		return ret;
494*3117bb31SNicolin Chen 	}
495*3117bb31SNicolin Chen 
496*3117bb31SNicolin Chen 	return 0;
497*3117bb31SNicolin Chen }
498*3117bb31SNicolin Chen 
499*3117bb31SNicolin Chen static int fsl_asrc_dai_hw_free(struct snd_pcm_substream *substream,
500*3117bb31SNicolin Chen 				struct snd_soc_dai *dai)
501*3117bb31SNicolin Chen {
502*3117bb31SNicolin Chen 	struct snd_pcm_runtime *runtime = substream->runtime;
503*3117bb31SNicolin Chen 	struct fsl_asrc_pair *pair = runtime->private_data;
504*3117bb31SNicolin Chen 
505*3117bb31SNicolin Chen 	if (pair)
506*3117bb31SNicolin Chen 		fsl_asrc_release_pair(pair);
507*3117bb31SNicolin Chen 
508*3117bb31SNicolin Chen 	return 0;
509*3117bb31SNicolin Chen }
510*3117bb31SNicolin Chen 
511*3117bb31SNicolin Chen static int fsl_asrc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
512*3117bb31SNicolin Chen 				struct snd_soc_dai *dai)
513*3117bb31SNicolin Chen {
514*3117bb31SNicolin Chen 	struct snd_pcm_runtime *runtime = substream->runtime;
515*3117bb31SNicolin Chen 	struct fsl_asrc_pair *pair = runtime->private_data;
516*3117bb31SNicolin Chen 
517*3117bb31SNicolin Chen 	switch (cmd) {
518*3117bb31SNicolin Chen 	case SNDRV_PCM_TRIGGER_START:
519*3117bb31SNicolin Chen 	case SNDRV_PCM_TRIGGER_RESUME:
520*3117bb31SNicolin Chen 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
521*3117bb31SNicolin Chen 		fsl_asrc_start_pair(pair);
522*3117bb31SNicolin Chen 		break;
523*3117bb31SNicolin Chen 	case SNDRV_PCM_TRIGGER_STOP:
524*3117bb31SNicolin Chen 	case SNDRV_PCM_TRIGGER_SUSPEND:
525*3117bb31SNicolin Chen 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
526*3117bb31SNicolin Chen 		fsl_asrc_stop_pair(pair);
527*3117bb31SNicolin Chen 		break;
528*3117bb31SNicolin Chen 	default:
529*3117bb31SNicolin Chen 		return -EINVAL;
530*3117bb31SNicolin Chen 	}
531*3117bb31SNicolin Chen 
532*3117bb31SNicolin Chen 	return 0;
533*3117bb31SNicolin Chen }
534*3117bb31SNicolin Chen 
535*3117bb31SNicolin Chen static struct snd_soc_dai_ops fsl_asrc_dai_ops = {
536*3117bb31SNicolin Chen 	.hw_params    = fsl_asrc_dai_hw_params,
537*3117bb31SNicolin Chen 	.hw_free      = fsl_asrc_dai_hw_free,
538*3117bb31SNicolin Chen 	.trigger      = fsl_asrc_dai_trigger,
539*3117bb31SNicolin Chen };
540*3117bb31SNicolin Chen 
541*3117bb31SNicolin Chen static int fsl_asrc_dai_probe(struct snd_soc_dai *dai)
542*3117bb31SNicolin Chen {
543*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai);
544*3117bb31SNicolin Chen 
545*3117bb31SNicolin Chen 	snd_soc_dai_init_dma_data(dai, &asrc_priv->dma_params_tx,
546*3117bb31SNicolin Chen 				  &asrc_priv->dma_params_rx);
547*3117bb31SNicolin Chen 
548*3117bb31SNicolin Chen 	return 0;
549*3117bb31SNicolin Chen }
550*3117bb31SNicolin Chen 
551*3117bb31SNicolin Chen #define FSL_ASRC_RATES		 SNDRV_PCM_RATE_8000_192000
552*3117bb31SNicolin Chen #define FSL_ASRC_FORMATS	(SNDRV_PCM_FMTBIT_S24_LE | \
553*3117bb31SNicolin Chen 				 SNDRV_PCM_FMTBIT_S16_LE | \
554*3117bb31SNicolin Chen 				 SNDRV_PCM_FORMAT_S20_3LE)
555*3117bb31SNicolin Chen 
556*3117bb31SNicolin Chen static struct snd_soc_dai_driver fsl_asrc_dai = {
557*3117bb31SNicolin Chen 	.probe = fsl_asrc_dai_probe,
558*3117bb31SNicolin Chen 	.playback = {
559*3117bb31SNicolin Chen 		.stream_name = "ASRC-Playback",
560*3117bb31SNicolin Chen 		.channels_min = 1,
561*3117bb31SNicolin Chen 		.channels_max = 10,
562*3117bb31SNicolin Chen 		.rates = FSL_ASRC_RATES,
563*3117bb31SNicolin Chen 		.formats = FSL_ASRC_FORMATS,
564*3117bb31SNicolin Chen 	},
565*3117bb31SNicolin Chen 	.capture = {
566*3117bb31SNicolin Chen 		.stream_name = "ASRC-Capture",
567*3117bb31SNicolin Chen 		.channels_min = 1,
568*3117bb31SNicolin Chen 		.channels_max = 10,
569*3117bb31SNicolin Chen 		.rates = FSL_ASRC_RATES,
570*3117bb31SNicolin Chen 		.formats = FSL_ASRC_FORMATS,
571*3117bb31SNicolin Chen 	},
572*3117bb31SNicolin Chen 	.ops = &fsl_asrc_dai_ops,
573*3117bb31SNicolin Chen };
574*3117bb31SNicolin Chen 
575*3117bb31SNicolin Chen static const struct snd_soc_component_driver fsl_asrc_component = {
576*3117bb31SNicolin Chen 	.name = "fsl-asrc-dai",
577*3117bb31SNicolin Chen };
578*3117bb31SNicolin Chen 
579*3117bb31SNicolin Chen static bool fsl_asrc_readable_reg(struct device *dev, unsigned int reg)
580*3117bb31SNicolin Chen {
581*3117bb31SNicolin Chen 	switch (reg) {
582*3117bb31SNicolin Chen 	case REG_ASRCTR:
583*3117bb31SNicolin Chen 	case REG_ASRIER:
584*3117bb31SNicolin Chen 	case REG_ASRCNCR:
585*3117bb31SNicolin Chen 	case REG_ASRCFG:
586*3117bb31SNicolin Chen 	case REG_ASRCSR:
587*3117bb31SNicolin Chen 	case REG_ASRCDR1:
588*3117bb31SNicolin Chen 	case REG_ASRCDR2:
589*3117bb31SNicolin Chen 	case REG_ASRSTR:
590*3117bb31SNicolin Chen 	case REG_ASRPM1:
591*3117bb31SNicolin Chen 	case REG_ASRPM2:
592*3117bb31SNicolin Chen 	case REG_ASRPM3:
593*3117bb31SNicolin Chen 	case REG_ASRPM4:
594*3117bb31SNicolin Chen 	case REG_ASRPM5:
595*3117bb31SNicolin Chen 	case REG_ASRTFR1:
596*3117bb31SNicolin Chen 	case REG_ASRCCR:
597*3117bb31SNicolin Chen 	case REG_ASRDOA:
598*3117bb31SNicolin Chen 	case REG_ASRDOB:
599*3117bb31SNicolin Chen 	case REG_ASRDOC:
600*3117bb31SNicolin Chen 	case REG_ASRIDRHA:
601*3117bb31SNicolin Chen 	case REG_ASRIDRLA:
602*3117bb31SNicolin Chen 	case REG_ASRIDRHB:
603*3117bb31SNicolin Chen 	case REG_ASRIDRLB:
604*3117bb31SNicolin Chen 	case REG_ASRIDRHC:
605*3117bb31SNicolin Chen 	case REG_ASRIDRLC:
606*3117bb31SNicolin Chen 	case REG_ASR76K:
607*3117bb31SNicolin Chen 	case REG_ASR56K:
608*3117bb31SNicolin Chen 	case REG_ASRMCRA:
609*3117bb31SNicolin Chen 	case REG_ASRFSTA:
610*3117bb31SNicolin Chen 	case REG_ASRMCRB:
611*3117bb31SNicolin Chen 	case REG_ASRFSTB:
612*3117bb31SNicolin Chen 	case REG_ASRMCRC:
613*3117bb31SNicolin Chen 	case REG_ASRFSTC:
614*3117bb31SNicolin Chen 	case REG_ASRMCR1A:
615*3117bb31SNicolin Chen 	case REG_ASRMCR1B:
616*3117bb31SNicolin Chen 	case REG_ASRMCR1C:
617*3117bb31SNicolin Chen 		return true;
618*3117bb31SNicolin Chen 	default:
619*3117bb31SNicolin Chen 		return false;
620*3117bb31SNicolin Chen 	}
621*3117bb31SNicolin Chen }
622*3117bb31SNicolin Chen 
623*3117bb31SNicolin Chen static bool fsl_asrc_volatile_reg(struct device *dev, unsigned int reg)
624*3117bb31SNicolin Chen {
625*3117bb31SNicolin Chen 	switch (reg) {
626*3117bb31SNicolin Chen 	case REG_ASRSTR:
627*3117bb31SNicolin Chen 	case REG_ASRDIA:
628*3117bb31SNicolin Chen 	case REG_ASRDIB:
629*3117bb31SNicolin Chen 	case REG_ASRDIC:
630*3117bb31SNicolin Chen 	case REG_ASRDOA:
631*3117bb31SNicolin Chen 	case REG_ASRDOB:
632*3117bb31SNicolin Chen 	case REG_ASRDOC:
633*3117bb31SNicolin Chen 	case REG_ASRFSTA:
634*3117bb31SNicolin Chen 	case REG_ASRFSTB:
635*3117bb31SNicolin Chen 	case REG_ASRFSTC:
636*3117bb31SNicolin Chen 	case REG_ASRCFG:
637*3117bb31SNicolin Chen 		return true;
638*3117bb31SNicolin Chen 	default:
639*3117bb31SNicolin Chen 		return false;
640*3117bb31SNicolin Chen 	}
641*3117bb31SNicolin Chen }
642*3117bb31SNicolin Chen 
643*3117bb31SNicolin Chen static bool fsl_asrc_writeable_reg(struct device *dev, unsigned int reg)
644*3117bb31SNicolin Chen {
645*3117bb31SNicolin Chen 	switch (reg) {
646*3117bb31SNicolin Chen 	case REG_ASRCTR:
647*3117bb31SNicolin Chen 	case REG_ASRIER:
648*3117bb31SNicolin Chen 	case REG_ASRCNCR:
649*3117bb31SNicolin Chen 	case REG_ASRCFG:
650*3117bb31SNicolin Chen 	case REG_ASRCSR:
651*3117bb31SNicolin Chen 	case REG_ASRCDR1:
652*3117bb31SNicolin Chen 	case REG_ASRCDR2:
653*3117bb31SNicolin Chen 	case REG_ASRSTR:
654*3117bb31SNicolin Chen 	case REG_ASRPM1:
655*3117bb31SNicolin Chen 	case REG_ASRPM2:
656*3117bb31SNicolin Chen 	case REG_ASRPM3:
657*3117bb31SNicolin Chen 	case REG_ASRPM4:
658*3117bb31SNicolin Chen 	case REG_ASRPM5:
659*3117bb31SNicolin Chen 	case REG_ASRTFR1:
660*3117bb31SNicolin Chen 	case REG_ASRCCR:
661*3117bb31SNicolin Chen 	case REG_ASRDIA:
662*3117bb31SNicolin Chen 	case REG_ASRDIB:
663*3117bb31SNicolin Chen 	case REG_ASRDIC:
664*3117bb31SNicolin Chen 	case REG_ASRIDRHA:
665*3117bb31SNicolin Chen 	case REG_ASRIDRLA:
666*3117bb31SNicolin Chen 	case REG_ASRIDRHB:
667*3117bb31SNicolin Chen 	case REG_ASRIDRLB:
668*3117bb31SNicolin Chen 	case REG_ASRIDRHC:
669*3117bb31SNicolin Chen 	case REG_ASRIDRLC:
670*3117bb31SNicolin Chen 	case REG_ASR76K:
671*3117bb31SNicolin Chen 	case REG_ASR56K:
672*3117bb31SNicolin Chen 	case REG_ASRMCRA:
673*3117bb31SNicolin Chen 	case REG_ASRMCRB:
674*3117bb31SNicolin Chen 	case REG_ASRMCRC:
675*3117bb31SNicolin Chen 	case REG_ASRMCR1A:
676*3117bb31SNicolin Chen 	case REG_ASRMCR1B:
677*3117bb31SNicolin Chen 	case REG_ASRMCR1C:
678*3117bb31SNicolin Chen 		return true;
679*3117bb31SNicolin Chen 	default:
680*3117bb31SNicolin Chen 		return false;
681*3117bb31SNicolin Chen 	}
682*3117bb31SNicolin Chen }
683*3117bb31SNicolin Chen 
684*3117bb31SNicolin Chen static struct regmap_config fsl_asrc_regmap_config = {
685*3117bb31SNicolin Chen 	.reg_bits = 32,
686*3117bb31SNicolin Chen 	.reg_stride = 4,
687*3117bb31SNicolin Chen 	.val_bits = 32,
688*3117bb31SNicolin Chen 
689*3117bb31SNicolin Chen 	.max_register = REG_ASRMCR1C,
690*3117bb31SNicolin Chen 	.readable_reg = fsl_asrc_readable_reg,
691*3117bb31SNicolin Chen 	.volatile_reg = fsl_asrc_volatile_reg,
692*3117bb31SNicolin Chen 	.writeable_reg = fsl_asrc_writeable_reg,
693*3117bb31SNicolin Chen 	.cache_type = REGCACHE_RBTREE,
694*3117bb31SNicolin Chen };
695*3117bb31SNicolin Chen 
696*3117bb31SNicolin Chen /**
697*3117bb31SNicolin Chen  * Initialize ASRC registers with a default configurations
698*3117bb31SNicolin Chen  */
699*3117bb31SNicolin Chen static int fsl_asrc_init(struct fsl_asrc *asrc_priv)
700*3117bb31SNicolin Chen {
701*3117bb31SNicolin Chen 	/* Halt ASRC internal FP when input FIFO needs data for pair A, B, C */
702*3117bb31SNicolin Chen 	regmap_write(asrc_priv->regmap, REG_ASRCTR, ASRCTR_ASRCEN);
703*3117bb31SNicolin Chen 
704*3117bb31SNicolin Chen 	/* Disable interrupt by default */
705*3117bb31SNicolin Chen 	regmap_write(asrc_priv->regmap, REG_ASRIER, 0x0);
706*3117bb31SNicolin Chen 
707*3117bb31SNicolin Chen 	/* Apply recommended settings for parameters from Reference Manual */
708*3117bb31SNicolin Chen 	regmap_write(asrc_priv->regmap, REG_ASRPM1, 0x7fffff);
709*3117bb31SNicolin Chen 	regmap_write(asrc_priv->regmap, REG_ASRPM2, 0x255555);
710*3117bb31SNicolin Chen 	regmap_write(asrc_priv->regmap, REG_ASRPM3, 0xff7280);
711*3117bb31SNicolin Chen 	regmap_write(asrc_priv->regmap, REG_ASRPM4, 0xff7280);
712*3117bb31SNicolin Chen 	regmap_write(asrc_priv->regmap, REG_ASRPM5, 0xff7280);
713*3117bb31SNicolin Chen 
714*3117bb31SNicolin Chen 	/* Base address for task queue FIFO. Set to 0x7C */
715*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRTFR1,
716*3117bb31SNicolin Chen 			   ASRTFR1_TF_BASE_MASK, ASRTFR1_TF_BASE(0xfc));
717*3117bb31SNicolin Chen 
718*3117bb31SNicolin Chen 	/* Set the processing clock for 76KHz to 133M */
719*3117bb31SNicolin Chen 	regmap_write(asrc_priv->regmap, REG_ASR76K, 0x06D6);
720*3117bb31SNicolin Chen 
721*3117bb31SNicolin Chen 	/* Set the processing clock for 56KHz to 133M */
722*3117bb31SNicolin Chen 	return regmap_write(asrc_priv->regmap, REG_ASR56K, 0x0947);
723*3117bb31SNicolin Chen }
724*3117bb31SNicolin Chen 
725*3117bb31SNicolin Chen /**
726*3117bb31SNicolin Chen  * Interrupt handler for ASRC
727*3117bb31SNicolin Chen  */
728*3117bb31SNicolin Chen static irqreturn_t fsl_asrc_isr(int irq, void *dev_id)
729*3117bb31SNicolin Chen {
730*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = (struct fsl_asrc *)dev_id;
731*3117bb31SNicolin Chen 	struct device *dev = &asrc_priv->pdev->dev;
732*3117bb31SNicolin Chen 	enum asrc_pair_index index;
733*3117bb31SNicolin Chen 	u32 status;
734*3117bb31SNicolin Chen 
735*3117bb31SNicolin Chen 	regmap_read(asrc_priv->regmap, REG_ASRSTR, &status);
736*3117bb31SNicolin Chen 
737*3117bb31SNicolin Chen 	/* Clean overload error */
738*3117bb31SNicolin Chen 	regmap_write(asrc_priv->regmap, REG_ASRSTR, ASRSTR_AOLE);
739*3117bb31SNicolin Chen 
740*3117bb31SNicolin Chen 	/*
741*3117bb31SNicolin Chen 	 * We here use dev_dbg() for all exceptions because ASRC itself does
742*3117bb31SNicolin Chen 	 * not care if FIFO overflowed or underrun while a warning in the
743*3117bb31SNicolin Chen 	 * interrupt would result a ridged conversion.
744*3117bb31SNicolin Chen 	 */
745*3117bb31SNicolin Chen 	for (index = ASRC_PAIR_A; index < ASRC_PAIR_MAX_NUM; index++) {
746*3117bb31SNicolin Chen 		if (!asrc_priv->pair[index])
747*3117bb31SNicolin Chen 			continue;
748*3117bb31SNicolin Chen 
749*3117bb31SNicolin Chen 		if (status & ASRSTR_ATQOL) {
750*3117bb31SNicolin Chen 			asrc_priv->pair[index]->error |= ASRC_TASK_Q_OVERLOAD;
751*3117bb31SNicolin Chen 			dev_dbg(dev, "ASRC Task Queue FIFO overload\n");
752*3117bb31SNicolin Chen 		}
753*3117bb31SNicolin Chen 
754*3117bb31SNicolin Chen 		if (status & ASRSTR_AOOL(index)) {
755*3117bb31SNicolin Chen 			asrc_priv->pair[index]->error |= ASRC_OUTPUT_TASK_OVERLOAD;
756*3117bb31SNicolin Chen 			pair_dbg("Output Task Overload\n");
757*3117bb31SNicolin Chen 		}
758*3117bb31SNicolin Chen 
759*3117bb31SNicolin Chen 		if (status & ASRSTR_AIOL(index)) {
760*3117bb31SNicolin Chen 			asrc_priv->pair[index]->error |= ASRC_INPUT_TASK_OVERLOAD;
761*3117bb31SNicolin Chen 			pair_dbg("Input Task Overload\n");
762*3117bb31SNicolin Chen 		}
763*3117bb31SNicolin Chen 
764*3117bb31SNicolin Chen 		if (status & ASRSTR_AODO(index)) {
765*3117bb31SNicolin Chen 			asrc_priv->pair[index]->error |= ASRC_OUTPUT_BUFFER_OVERFLOW;
766*3117bb31SNicolin Chen 			pair_dbg("Output Data Buffer has overflowed\n");
767*3117bb31SNicolin Chen 		}
768*3117bb31SNicolin Chen 
769*3117bb31SNicolin Chen 		if (status & ASRSTR_AIDU(index)) {
770*3117bb31SNicolin Chen 			asrc_priv->pair[index]->error |= ASRC_INPUT_BUFFER_UNDERRUN;
771*3117bb31SNicolin Chen 			pair_dbg("Input Data Buffer has underflowed\n");
772*3117bb31SNicolin Chen 		}
773*3117bb31SNicolin Chen 	}
774*3117bb31SNicolin Chen 
775*3117bb31SNicolin Chen 	return IRQ_HANDLED;
776*3117bb31SNicolin Chen }
777*3117bb31SNicolin Chen 
778*3117bb31SNicolin Chen static int fsl_asrc_probe(struct platform_device *pdev)
779*3117bb31SNicolin Chen {
780*3117bb31SNicolin Chen 	struct device_node *np = pdev->dev.of_node;
781*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv;
782*3117bb31SNicolin Chen 	struct resource *res;
783*3117bb31SNicolin Chen 	void __iomem *regs;
784*3117bb31SNicolin Chen 	int irq, ret, i;
785*3117bb31SNicolin Chen 	char tmp[16];
786*3117bb31SNicolin Chen 
787*3117bb31SNicolin Chen 	asrc_priv = devm_kzalloc(&pdev->dev, sizeof(*asrc_priv), GFP_KERNEL);
788*3117bb31SNicolin Chen 	if (!asrc_priv)
789*3117bb31SNicolin Chen 		return -ENOMEM;
790*3117bb31SNicolin Chen 
791*3117bb31SNicolin Chen 	asrc_priv->pdev = pdev;
792*3117bb31SNicolin Chen 	strcpy(asrc_priv->name, np->name);
793*3117bb31SNicolin Chen 
794*3117bb31SNicolin Chen 	/* Get the addresses and IRQ */
795*3117bb31SNicolin Chen 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
796*3117bb31SNicolin Chen 	regs = devm_ioremap_resource(&pdev->dev, res);
797*3117bb31SNicolin Chen 	if (IS_ERR(regs))
798*3117bb31SNicolin Chen 		return PTR_ERR(regs);
799*3117bb31SNicolin Chen 
800*3117bb31SNicolin Chen 	asrc_priv->paddr = res->start;
801*3117bb31SNicolin Chen 
802*3117bb31SNicolin Chen 	/* Register regmap and let it prepare core clock */
803*3117bb31SNicolin Chen 	if (of_property_read_bool(np, "big-endian"))
804*3117bb31SNicolin Chen 		fsl_asrc_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG;
805*3117bb31SNicolin Chen 
806*3117bb31SNicolin Chen 	asrc_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "mem", regs,
807*3117bb31SNicolin Chen 						      &fsl_asrc_regmap_config);
808*3117bb31SNicolin Chen 	if (IS_ERR(asrc_priv->regmap)) {
809*3117bb31SNicolin Chen 		dev_err(&pdev->dev, "failed to init regmap\n");
810*3117bb31SNicolin Chen 		return PTR_ERR(asrc_priv->regmap);
811*3117bb31SNicolin Chen 	}
812*3117bb31SNicolin Chen 
813*3117bb31SNicolin Chen 	irq = platform_get_irq(pdev, 0);
814*3117bb31SNicolin Chen 	if (irq < 0) {
815*3117bb31SNicolin Chen 		dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
816*3117bb31SNicolin Chen 		return irq;
817*3117bb31SNicolin Chen 	}
818*3117bb31SNicolin Chen 
819*3117bb31SNicolin Chen 	ret = devm_request_irq(&pdev->dev, irq, fsl_asrc_isr, 0,
820*3117bb31SNicolin Chen 			       asrc_priv->name, asrc_priv);
821*3117bb31SNicolin Chen 	if (ret) {
822*3117bb31SNicolin Chen 		dev_err(&pdev->dev, "failed to claim irq %u: %d\n", irq, ret);
823*3117bb31SNicolin Chen 		return ret;
824*3117bb31SNicolin Chen 	}
825*3117bb31SNicolin Chen 
826*3117bb31SNicolin Chen 	asrc_priv->mem_clk = devm_clk_get(&pdev->dev, "mem");
827*3117bb31SNicolin Chen 	if (IS_ERR(asrc_priv->mem_clk)) {
828*3117bb31SNicolin Chen 		dev_err(&pdev->dev, "failed to get mem clock\n");
829*3117bb31SNicolin Chen 		return PTR_ERR(asrc_priv->ipg_clk);
830*3117bb31SNicolin Chen 	}
831*3117bb31SNicolin Chen 
832*3117bb31SNicolin Chen 	asrc_priv->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
833*3117bb31SNicolin Chen 	if (IS_ERR(asrc_priv->ipg_clk)) {
834*3117bb31SNicolin Chen 		dev_err(&pdev->dev, "failed to get ipg clock\n");
835*3117bb31SNicolin Chen 		return PTR_ERR(asrc_priv->ipg_clk);
836*3117bb31SNicolin Chen 	}
837*3117bb31SNicolin Chen 
838*3117bb31SNicolin Chen 	for (i = 0; i < ASRC_CLK_MAX_NUM; i++) {
839*3117bb31SNicolin Chen 		sprintf(tmp, "asrck_%x", i);
840*3117bb31SNicolin Chen 		asrc_priv->asrck_clk[i] = devm_clk_get(&pdev->dev, tmp);
841*3117bb31SNicolin Chen 		if (IS_ERR(asrc_priv->asrck_clk[i])) {
842*3117bb31SNicolin Chen 			dev_err(&pdev->dev, "failed to get %s clock\n", tmp);
843*3117bb31SNicolin Chen 			return PTR_ERR(asrc_priv->asrck_clk[i]);
844*3117bb31SNicolin Chen 		}
845*3117bb31SNicolin Chen 	}
846*3117bb31SNicolin Chen 
847*3117bb31SNicolin Chen 	if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx35-asrc")) {
848*3117bb31SNicolin Chen 		asrc_priv->channel_bits = 3;
849*3117bb31SNicolin Chen 		clk_map[IN] = input_clk_map_imx35;
850*3117bb31SNicolin Chen 		clk_map[OUT] = output_clk_map_imx35;
851*3117bb31SNicolin Chen 	} else {
852*3117bb31SNicolin Chen 		asrc_priv->channel_bits = 4;
853*3117bb31SNicolin Chen 		clk_map[IN] = input_clk_map_imx53;
854*3117bb31SNicolin Chen 		clk_map[OUT] = output_clk_map_imx53;
855*3117bb31SNicolin Chen 	}
856*3117bb31SNicolin Chen 
857*3117bb31SNicolin Chen 	ret = fsl_asrc_init(asrc_priv);
858*3117bb31SNicolin Chen 	if (ret) {
859*3117bb31SNicolin Chen 		dev_err(&pdev->dev, "failed to init asrc %d\n", ret);
860*3117bb31SNicolin Chen 		return -EINVAL;
861*3117bb31SNicolin Chen 	}
862*3117bb31SNicolin Chen 
863*3117bb31SNicolin Chen 	asrc_priv->channel_avail = 10;
864*3117bb31SNicolin Chen 
865*3117bb31SNicolin Chen 	ret = of_property_read_u32(np, "fsl,asrc-rate",
866*3117bb31SNicolin Chen 				   &asrc_priv->asrc_rate);
867*3117bb31SNicolin Chen 	if (ret) {
868*3117bb31SNicolin Chen 		dev_err(&pdev->dev, "failed to get output rate\n");
869*3117bb31SNicolin Chen 		return -EINVAL;
870*3117bb31SNicolin Chen 	}
871*3117bb31SNicolin Chen 
872*3117bb31SNicolin Chen 	ret = of_property_read_u32(np, "fsl,asrc-width",
873*3117bb31SNicolin Chen 				   &asrc_priv->asrc_width);
874*3117bb31SNicolin Chen 	if (ret) {
875*3117bb31SNicolin Chen 		dev_err(&pdev->dev, "failed to get output width\n");
876*3117bb31SNicolin Chen 		return -EINVAL;
877*3117bb31SNicolin Chen 	}
878*3117bb31SNicolin Chen 
879*3117bb31SNicolin Chen 	if (asrc_priv->asrc_width != 16 && asrc_priv->asrc_width != 24) {
880*3117bb31SNicolin Chen 		dev_warn(&pdev->dev, "unsupported width, switching to 24bit\n");
881*3117bb31SNicolin Chen 		asrc_priv->asrc_width = 24;
882*3117bb31SNicolin Chen 	}
883*3117bb31SNicolin Chen 
884*3117bb31SNicolin Chen 	platform_set_drvdata(pdev, asrc_priv);
885*3117bb31SNicolin Chen 	pm_runtime_enable(&pdev->dev);
886*3117bb31SNicolin Chen 	spin_lock_init(&asrc_priv->lock);
887*3117bb31SNicolin Chen 
888*3117bb31SNicolin Chen 	ret = devm_snd_soc_register_component(&pdev->dev, &fsl_asrc_component,
889*3117bb31SNicolin Chen 					      &fsl_asrc_dai, 1);
890*3117bb31SNicolin Chen 	if (ret) {
891*3117bb31SNicolin Chen 		dev_err(&pdev->dev, "failed to register ASoC DAI\n");
892*3117bb31SNicolin Chen 		return ret;
893*3117bb31SNicolin Chen 	}
894*3117bb31SNicolin Chen 
895*3117bb31SNicolin Chen 	ret = devm_snd_soc_register_platform(&pdev->dev, &fsl_asrc_platform);
896*3117bb31SNicolin Chen 	if (ret) {
897*3117bb31SNicolin Chen 		dev_err(&pdev->dev, "failed to register ASoC platform\n");
898*3117bb31SNicolin Chen 		return ret;
899*3117bb31SNicolin Chen 	}
900*3117bb31SNicolin Chen 
901*3117bb31SNicolin Chen 	dev_info(&pdev->dev, "driver registered\n");
902*3117bb31SNicolin Chen 
903*3117bb31SNicolin Chen 	return 0;
904*3117bb31SNicolin Chen }
905*3117bb31SNicolin Chen 
906*3117bb31SNicolin Chen #if CONFIG_PM_RUNTIME
907*3117bb31SNicolin Chen static int fsl_asrc_runtime_resume(struct device *dev)
908*3117bb31SNicolin Chen {
909*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
910*3117bb31SNicolin Chen 	int i;
911*3117bb31SNicolin Chen 
912*3117bb31SNicolin Chen 	clk_prepare_enable(asrc_priv->mem_clk);
913*3117bb31SNicolin Chen 	clk_prepare_enable(asrc_priv->ipg_clk);
914*3117bb31SNicolin Chen 	for (i = 0; i < ASRC_CLK_MAX_NUM; i++)
915*3117bb31SNicolin Chen 		clk_prepare_enable(asrc_priv->asrck_clk[i]);
916*3117bb31SNicolin Chen 
917*3117bb31SNicolin Chen 	return 0;
918*3117bb31SNicolin Chen }
919*3117bb31SNicolin Chen 
920*3117bb31SNicolin Chen static int fsl_asrc_runtime_suspend(struct device *dev)
921*3117bb31SNicolin Chen {
922*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
923*3117bb31SNicolin Chen 	int i;
924*3117bb31SNicolin Chen 
925*3117bb31SNicolin Chen 	for (i = 0; i < ASRC_CLK_MAX_NUM; i++)
926*3117bb31SNicolin Chen 		clk_disable_unprepare(asrc_priv->asrck_clk[i]);
927*3117bb31SNicolin Chen 	clk_disable_unprepare(asrc_priv->ipg_clk);
928*3117bb31SNicolin Chen 	clk_disable_unprepare(asrc_priv->mem_clk);
929*3117bb31SNicolin Chen 
930*3117bb31SNicolin Chen 	return 0;
931*3117bb31SNicolin Chen }
932*3117bb31SNicolin Chen #endif /* CONFIG_PM_RUNTIME */
933*3117bb31SNicolin Chen 
934*3117bb31SNicolin Chen #if CONFIG_PM_SLEEP
935*3117bb31SNicolin Chen static int fsl_asrc_suspend(struct device *dev)
936*3117bb31SNicolin Chen {
937*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
938*3117bb31SNicolin Chen 
939*3117bb31SNicolin Chen 	regcache_cache_only(asrc_priv->regmap, true);
940*3117bb31SNicolin Chen 	regcache_mark_dirty(asrc_priv->regmap);
941*3117bb31SNicolin Chen 
942*3117bb31SNicolin Chen 	return 0;
943*3117bb31SNicolin Chen }
944*3117bb31SNicolin Chen 
945*3117bb31SNicolin Chen static int fsl_asrc_resume(struct device *dev)
946*3117bb31SNicolin Chen {
947*3117bb31SNicolin Chen 	struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
948*3117bb31SNicolin Chen 	u32 asrctr;
949*3117bb31SNicolin Chen 
950*3117bb31SNicolin Chen 	/* Stop all pairs provisionally */
951*3117bb31SNicolin Chen 	regmap_read(asrc_priv->regmap, REG_ASRCTR, &asrctr);
952*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
953*3117bb31SNicolin Chen 			   ASRCTR_ASRCEi_ALL_MASK, 0);
954*3117bb31SNicolin Chen 
955*3117bb31SNicolin Chen 	/* Restore all registers */
956*3117bb31SNicolin Chen 	regcache_cache_only(asrc_priv->regmap, false);
957*3117bb31SNicolin Chen 	regcache_sync(asrc_priv->regmap);
958*3117bb31SNicolin Chen 
959*3117bb31SNicolin Chen 	/* Restart enabled pairs */
960*3117bb31SNicolin Chen 	regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
961*3117bb31SNicolin Chen 			   ASRCTR_ASRCEi_ALL_MASK, asrctr);
962*3117bb31SNicolin Chen 
963*3117bb31SNicolin Chen 	return 0;
964*3117bb31SNicolin Chen }
965*3117bb31SNicolin Chen #endif /* CONFIG_PM_SLEEP */
966*3117bb31SNicolin Chen 
967*3117bb31SNicolin Chen static const struct dev_pm_ops fsl_asrc_pm = {
968*3117bb31SNicolin Chen 	SET_RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, NULL)
969*3117bb31SNicolin Chen 	SET_SYSTEM_SLEEP_PM_OPS(fsl_asrc_suspend, fsl_asrc_resume)
970*3117bb31SNicolin Chen };
971*3117bb31SNicolin Chen 
972*3117bb31SNicolin Chen static const struct of_device_id fsl_asrc_ids[] = {
973*3117bb31SNicolin Chen 	{ .compatible = "fsl,imx35-asrc", },
974*3117bb31SNicolin Chen 	{ .compatible = "fsl,imx53-asrc", },
975*3117bb31SNicolin Chen 	{}
976*3117bb31SNicolin Chen };
977*3117bb31SNicolin Chen MODULE_DEVICE_TABLE(of, fsl_asrc_ids);
978*3117bb31SNicolin Chen 
979*3117bb31SNicolin Chen static struct platform_driver fsl_asrc_driver = {
980*3117bb31SNicolin Chen 	.probe = fsl_asrc_probe,
981*3117bb31SNicolin Chen 	.driver = {
982*3117bb31SNicolin Chen 		.name = "fsl-asrc",
983*3117bb31SNicolin Chen 		.of_match_table = fsl_asrc_ids,
984*3117bb31SNicolin Chen 		.pm = &fsl_asrc_pm,
985*3117bb31SNicolin Chen 	},
986*3117bb31SNicolin Chen };
987*3117bb31SNicolin Chen module_platform_driver(fsl_asrc_driver);
988*3117bb31SNicolin Chen 
989*3117bb31SNicolin Chen MODULE_DESCRIPTION("Freescale ASRC ASoC driver");
990*3117bb31SNicolin Chen MODULE_AUTHOR("Nicolin Chen <nicoleotsuka@gmail.com>");
991*3117bb31SNicolin Chen MODULE_ALIAS("platform:fsl-asrc");
992*3117bb31SNicolin Chen MODULE_LICENSE("GPL v2");
993