1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * This driver supports the digital controls for the internal codec
4 * found in Allwinner's A33 SoCs.
5 *
6 * (C) Copyright 2010-2016
7 * Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com>
8 * huangxin <huangxin@Reuuimllatech.com>
9 * Myl��ne Josserand <mylene.josserand@free-electrons.com>
10 */
11
12#include <linux/module.h>
13#include <linux/delay.h>
14#include <linux/clk.h>
15#include <linux/io.h>
16#include <linux/of.h>
17#include <linux/pm_runtime.h>
18#include <linux/regmap.h>
19#include <linux/log2.h>
20
21#include <sound/pcm_params.h>
22#include <sound/soc.h>
23#include <sound/soc-dapm.h>
24#include <sound/tlv.h>
25
26#define SUN8I_SYSCLK_CTL				0x00c
27#define SUN8I_SYSCLK_CTL_AIF1CLK_ENA			11
28#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL		(0x2 << 8)
29#define SUN8I_SYSCLK_CTL_AIF2CLK_ENA			7
30#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL		(0x2 << 4)
31#define SUN8I_SYSCLK_CTL_SYSCLK_ENA			3
32#define SUN8I_SYSCLK_CTL_SYSCLK_SRC			0
33#define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK		(0x0 << 0)
34#define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF2CLK		(0x1 << 0)
35#define SUN8I_MOD_CLK_ENA				0x010
36#define SUN8I_MOD_CLK_ENA_AIF1				15
37#define SUN8I_MOD_CLK_ENA_AIF2				14
38#define SUN8I_MOD_CLK_ENA_AIF3				13
39#define SUN8I_MOD_CLK_ENA_ADC				3
40#define SUN8I_MOD_CLK_ENA_DAC				2
41#define SUN8I_MOD_RST_CTL				0x014
42#define SUN8I_MOD_RST_CTL_AIF1				15
43#define SUN8I_MOD_RST_CTL_AIF2				14
44#define SUN8I_MOD_RST_CTL_AIF3				13
45#define SUN8I_MOD_RST_CTL_ADC				3
46#define SUN8I_MOD_RST_CTL_DAC				2
47#define SUN8I_SYS_SR_CTRL				0x018
48#define SUN8I_SYS_SR_CTRL_AIF1_FS			12
49#define SUN8I_SYS_SR_CTRL_AIF2_FS			8
50#define SUN8I_AIF_CLK_CTRL(n)				(0x040 * (1 + (n)))
51#define SUN8I_AIF_CLK_CTRL_MSTR_MOD			15
52#define SUN8I_AIF_CLK_CTRL_CLK_INV			13
53#define SUN8I_AIF_CLK_CTRL_BCLK_DIV			9
54#define SUN8I_AIF_CLK_CTRL_LRCK_DIV			6
55#define SUN8I_AIF_CLK_CTRL_WORD_SIZ			4
56#define SUN8I_AIF_CLK_CTRL_DATA_FMT			2
57#define SUN8I_AIF1_ADCDAT_CTRL				0x044
58#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA		15
59#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA		14
60#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC		10
61#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC		8
62#define SUN8I_AIF1_DACDAT_CTRL				0x048
63#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA		15
64#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA		14
65#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC		10
66#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC		8
67#define SUN8I_AIF1_MXR_SRC				0x04c
68#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L	15
69#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL	14
70#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL		13
71#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR	12
72#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R	11
73#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR	10
74#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR		9
75#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL	8
76#define SUN8I_AIF1_VOL_CTRL1				0x050
77#define SUN8I_AIF1_VOL_CTRL1_AD0L_VOL			8
78#define SUN8I_AIF1_VOL_CTRL1_AD0R_VOL			0
79#define SUN8I_AIF1_VOL_CTRL3				0x058
80#define SUN8I_AIF1_VOL_CTRL3_DA0L_VOL			8
81#define SUN8I_AIF1_VOL_CTRL3_DA0R_VOL			0
82#define SUN8I_AIF2_ADCDAT_CTRL				0x084
83#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA		15
84#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA		14
85#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC		10
86#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC		8
87#define SUN8I_AIF2_DACDAT_CTRL				0x088
88#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_ENA		15
89#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_ENA		14
90#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC		10
91#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC		8
92#define SUN8I_AIF2_MXR_SRC				0x08c
93#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L	15
94#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L	14
95#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR	13
96#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL		12
97#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R	11
98#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R	10
99#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL	9
100#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR		8
101#define SUN8I_AIF2_VOL_CTRL1				0x090
102#define SUN8I_AIF2_VOL_CTRL1_ADCL_VOL			8
103#define SUN8I_AIF2_VOL_CTRL1_ADCR_VOL			0
104#define SUN8I_AIF2_VOL_CTRL2				0x098
105#define SUN8I_AIF2_VOL_CTRL2_DACL_VOL			8
106#define SUN8I_AIF2_VOL_CTRL2_DACR_VOL			0
107#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1		(0x0 << 0)
108#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2		(0x1 << 0)
109#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1CLK	(0x2 << 0)
110#define SUN8I_AIF3_PATH_CTRL				0x0cc
111#define SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC		10
112#define SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC		8
113#define SUN8I_AIF3_PATH_CTRL_AIF3_PINS_TRI		7
114#define SUN8I_ADC_DIG_CTRL				0x100
115#define SUN8I_ADC_DIG_CTRL_ENAD				15
116#define SUN8I_ADC_DIG_CTRL_ADOUT_DTS			2
117#define SUN8I_ADC_DIG_CTRL_ADOUT_DLY			1
118#define SUN8I_ADC_VOL_CTRL				0x104
119#define SUN8I_ADC_VOL_CTRL_ADCL_VOL			8
120#define SUN8I_ADC_VOL_CTRL_ADCR_VOL			0
121#define SUN8I_DAC_DIG_CTRL				0x120
122#define SUN8I_DAC_DIG_CTRL_ENDA				15
123#define SUN8I_DAC_VOL_CTRL				0x124
124#define SUN8I_DAC_VOL_CTRL_DACL_VOL			8
125#define SUN8I_DAC_VOL_CTRL_DACR_VOL			0
126#define SUN8I_DAC_MXR_SRC				0x130
127#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L		15
128#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L		14
129#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL		13
130#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL		12
131#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R		11
132#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R		10
133#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR		9
134#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR		8
135
136#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK	GENMASK(9, 8)
137#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK	GENMASK(5, 4)
138#define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK		GENMASK(15, 12)
139#define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK		GENMASK(11, 8)
140#define SUN8I_AIF_CLK_CTRL_CLK_INV_MASK		GENMASK(14, 13)
141#define SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK	GENMASK(12, 9)
142#define SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK	GENMASK(8, 6)
143#define SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK	GENMASK(5, 4)
144#define SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK	GENMASK(3, 2)
145#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK	GENMASK(1, 0)
146
147#define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000
148
149#define SUN8I_CODEC_PCM_FORMATS	(SNDRV_PCM_FMTBIT_S8     |\
150				 SNDRV_PCM_FMTBIT_S16_LE |\
151				 SNDRV_PCM_FMTBIT_S20_LE |\
152				 SNDRV_PCM_FMTBIT_S24_LE |\
153				 SNDRV_PCM_FMTBIT_S20_3LE|\
154				 SNDRV_PCM_FMTBIT_S24_3LE)
155
156#define SUN8I_CODEC_PCM_RATES	(SNDRV_PCM_RATE_8000_48000|\
157				 SNDRV_PCM_RATE_88200     |\
158				 SNDRV_PCM_RATE_96000     |\
159				 SNDRV_PCM_RATE_176400    |\
160				 SNDRV_PCM_RATE_192000    |\
161				 SNDRV_PCM_RATE_KNOT)
162
163enum {
164	SUN8I_CODEC_AIF1,
165	SUN8I_CODEC_AIF2,
166	SUN8I_CODEC_AIF3,
167	SUN8I_CODEC_NAIFS
168};
169
170struct sun8i_codec_aif {
171	unsigned int	lrck_div_order;
172	unsigned int	sample_rate;
173	unsigned int	slots;
174	unsigned int	slot_width;
175	unsigned int	active_streams	: 2;
176	unsigned int	open_streams	: 2;
177};
178
179struct sun8i_codec_quirks {
180	bool legacy_widgets	: 1;
181	bool lrck_inversion	: 1;
182};
183
184struct sun8i_codec {
185	struct regmap			*regmap;
186	struct clk			*clk_module;
187	const struct sun8i_codec_quirks	*quirks;
188	struct sun8i_codec_aif		aifs[SUN8I_CODEC_NAIFS];
189	unsigned int			sysclk_rate;
190	int				sysclk_refcnt;
191};
192
193static struct snd_soc_dai_driver sun8i_codec_dais[];
194
195static int sun8i_codec_runtime_resume(struct device *dev)
196{
197	struct sun8i_codec *scodec = dev_get_drvdata(dev);
198	int ret;
199
200	regcache_cache_only(scodec->regmap, false);
201
202	ret = regcache_sync(scodec->regmap);
203	if (ret) {
204		dev_err(dev, "Failed to sync regmap cache\n");
205		return ret;
206	}
207
208	return 0;
209}
210
211static int sun8i_codec_runtime_suspend(struct device *dev)
212{
213	struct sun8i_codec *scodec = dev_get_drvdata(dev);
214
215	regcache_cache_only(scodec->regmap, true);
216	regcache_mark_dirty(scodec->regmap);
217
218	return 0;
219}
220
221static int sun8i_codec_get_hw_rate(unsigned int sample_rate)
222{
223	switch (sample_rate) {
224	case 7350:
225	case 8000:
226		return 0x0;
227	case 11025:
228		return 0x1;
229	case 12000:
230		return 0x2;
231	case 14700:
232	case 16000:
233		return 0x3;
234	case 22050:
235		return 0x4;
236	case 24000:
237		return 0x5;
238	case 29400:
239	case 32000:
240		return 0x6;
241	case 44100:
242		return 0x7;
243	case 48000:
244		return 0x8;
245	case 88200:
246	case 96000:
247		return 0x9;
248	case 176400:
249	case 192000:
250		return 0xa;
251	default:
252		return -EINVAL;
253	}
254}
255
256static int sun8i_codec_update_sample_rate(struct sun8i_codec *scodec)
257{
258	unsigned int max_rate = 0;
259	int hw_rate, i;
260
261	for (i = SUN8I_CODEC_AIF1; i < SUN8I_CODEC_NAIFS; ++i) {
262		struct sun8i_codec_aif *aif = &scodec->aifs[i];
263
264		if (aif->active_streams)
265			max_rate = max(max_rate, aif->sample_rate);
266	}
267
268	/* Set the sample rate for ADC->DAC passthrough when no AIF is active. */
269	if (!max_rate)
270		max_rate = SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE;
271
272	hw_rate = sun8i_codec_get_hw_rate(max_rate);
273	if (hw_rate < 0)
274		return hw_rate;
275
276	regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
277			   SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,
278			   hw_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
279
280	return 0;
281}
282
283static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
284{
285	struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
286	u32 dsp_format, format, invert, value;
287
288	/* clock masters */
289	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
290	case SND_SOC_DAIFMT_CBC_CFC: /* Codec slave, DAI master */
291		value = 0x1;
292		break;
293	case SND_SOC_DAIFMT_CBP_CFP: /* Codec Master, DAI slave */
294		value = 0x0;
295		break;
296	default:
297		return -EINVAL;
298	}
299
300	if (dai->id == SUN8I_CODEC_AIF3) {
301		/* AIF3 only supports master mode. */
302		if (value)
303			return -EINVAL;
304
305		/* Use the AIF2 BCLK and LRCK for AIF3. */
306		regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
307				   SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK,
308				   SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2);
309	} else {
310		regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
311				   BIT(SUN8I_AIF_CLK_CTRL_MSTR_MOD),
312				   value << SUN8I_AIF_CLK_CTRL_MSTR_MOD);
313	}
314
315	/* DAI format */
316	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
317	case SND_SOC_DAIFMT_I2S:
318		format = 0x0;
319		break;
320	case SND_SOC_DAIFMT_LEFT_J:
321		format = 0x1;
322		break;
323	case SND_SOC_DAIFMT_RIGHT_J:
324		format = 0x2;
325		break;
326	case SND_SOC_DAIFMT_DSP_A:
327		format = 0x3;
328		dsp_format = 0x0; /* Set LRCK_INV to 0 */
329		break;
330	case SND_SOC_DAIFMT_DSP_B:
331		format = 0x3;
332		dsp_format = 0x1; /* Set LRCK_INV to 1 */
333		break;
334	default:
335		return -EINVAL;
336	}
337
338	if (dai->id == SUN8I_CODEC_AIF3) {
339		/* AIF3 only supports DSP mode. */
340		if (format != 3)
341			return -EINVAL;
342	} else {
343		regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
344				   SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK,
345				   format << SUN8I_AIF_CLK_CTRL_DATA_FMT);
346	}
347
348	/* clock inversion */
349	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
350	case SND_SOC_DAIFMT_NB_NF: /* Normal */
351		invert = 0x0;
352		break;
353	case SND_SOC_DAIFMT_NB_IF: /* Inverted LRCK */
354		invert = 0x1;
355		break;
356	case SND_SOC_DAIFMT_IB_NF: /* Inverted BCLK */
357		invert = 0x2;
358		break;
359	case SND_SOC_DAIFMT_IB_IF: /* Both inverted */
360		invert = 0x3;
361		break;
362	default:
363		return -EINVAL;
364	}
365
366	if (format == 0x3) {
367		/* Inverted LRCK is not available in DSP mode. */
368		if (invert & BIT(0))
369			return -EINVAL;
370
371		/* Instead, the bit selects between DSP A/B formats. */
372		invert |= dsp_format;
373	} else {
374		/*
375		 * It appears that the DAI and the codec in the A33 SoC don't
376		 * share the same polarity for the LRCK signal when they mean
377		 * 'normal' and 'inverted' in the datasheet.
378		 *
379		 * Since the DAI here is our regular i2s driver that have been
380		 * tested with way more codecs than just this one, it means
381		 * that the codec probably gets it backward, and we have to
382		 * invert the value here.
383		 */
384		invert ^= scodec->quirks->lrck_inversion;
385	}
386
387	regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
388			   SUN8I_AIF_CLK_CTRL_CLK_INV_MASK,
389			   invert << SUN8I_AIF_CLK_CTRL_CLK_INV);
390
391	return 0;
392}
393
394static int sun8i_codec_set_tdm_slot(struct snd_soc_dai *dai,
395				    unsigned int tx_mask, unsigned int rx_mask,
396				    int slots, int slot_width)
397{
398	struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
399	struct sun8i_codec_aif *aif = &scodec->aifs[dai->id];
400
401	if (slot_width && !is_power_of_2(slot_width))
402		return -EINVAL;
403
404	aif->slots = slots;
405	aif->slot_width = slot_width;
406
407	return 0;
408}
409
410static const unsigned int sun8i_codec_rates[] = {
411	  7350,   8000,  11025,  12000,  14700,  16000,  22050,  24000,
412	 29400,  32000,  44100,  48000,  88200,  96000, 176400, 192000,
413};
414
415static const struct snd_pcm_hw_constraint_list sun8i_codec_all_rates = {
416	.list	= sun8i_codec_rates,
417	.count	= ARRAY_SIZE(sun8i_codec_rates),
418};
419
420static const struct snd_pcm_hw_constraint_list sun8i_codec_22M_rates = {
421	.list	= sun8i_codec_rates,
422	.count	= ARRAY_SIZE(sun8i_codec_rates),
423	.mask	= 0x5555,
424};
425
426static const struct snd_pcm_hw_constraint_list sun8i_codec_24M_rates = {
427	.list	= sun8i_codec_rates,
428	.count	= ARRAY_SIZE(sun8i_codec_rates),
429	.mask	= 0xaaaa,
430};
431
432static int sun8i_codec_startup(struct snd_pcm_substream *substream,
433			       struct snd_soc_dai *dai)
434{
435	struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
436	const struct snd_pcm_hw_constraint_list *list;
437
438	/* hw_constraints is not relevant for codec2codec DAIs. */
439	if (dai->id != SUN8I_CODEC_AIF1)
440		return 0;
441
442	if (!scodec->sysclk_refcnt)
443		list = &sun8i_codec_all_rates;
444	else if (scodec->sysclk_rate == 22579200)
445		list = &sun8i_codec_22M_rates;
446	else if (scodec->sysclk_rate == 24576000)
447		list = &sun8i_codec_24M_rates;
448	else
449		return -EINVAL;
450
451	return snd_pcm_hw_constraint_list(substream->runtime, 0,
452					  SNDRV_PCM_HW_PARAM_RATE, list);
453}
454
455struct sun8i_codec_clk_div {
456	u8	div;
457	u8	val;
458};
459
460static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = {
461	{ .div = 1,	.val = 0 },
462	{ .div = 2,	.val = 1 },
463	{ .div = 4,	.val = 2 },
464	{ .div = 6,	.val = 3 },
465	{ .div = 8,	.val = 4 },
466	{ .div = 12,	.val = 5 },
467	{ .div = 16,	.val = 6 },
468	{ .div = 24,	.val = 7 },
469	{ .div = 32,	.val = 8 },
470	{ .div = 48,	.val = 9 },
471	{ .div = 64,	.val = 10 },
472	{ .div = 96,	.val = 11 },
473	{ .div = 128,	.val = 12 },
474	{ .div = 192,	.val = 13 },
475};
476
477static int sun8i_codec_get_bclk_div(unsigned int sysclk_rate,
478				    unsigned int lrck_div_order,
479				    unsigned int sample_rate)
480{
481	unsigned int div = sysclk_rate / sample_rate >> lrck_div_order;
482	int i;
483
484	for (i = 0; i < ARRAY_SIZE(sun8i_codec_bclk_div); i++) {
485		const struct sun8i_codec_clk_div *bdiv = &sun8i_codec_bclk_div[i];
486
487		if (bdiv->div == div)
488			return bdiv->val;
489	}
490
491	return -EINVAL;
492}
493
494static int sun8i_codec_get_lrck_div_order(unsigned int slots,
495					  unsigned int slot_width)
496{
497	unsigned int div = slots * slot_width;
498
499	if (div < 16 || div > 256)
500		return -EINVAL;
501
502	return order_base_2(div);
503}
504
505static unsigned int sun8i_codec_get_sysclk_rate(unsigned int sample_rate)
506{
507	return (sample_rate % 4000) ? 22579200 : 24576000;
508}
509
510static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
511				 struct snd_pcm_hw_params *params,
512				 struct snd_soc_dai *dai)
513{
514	struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
515	struct sun8i_codec_aif *aif = &scodec->aifs[dai->id];
516	unsigned int sample_rate = params_rate(params);
517	unsigned int slots = aif->slots ?: params_channels(params);
518	unsigned int slot_width = aif->slot_width ?: params_width(params);
519	unsigned int sysclk_rate = sun8i_codec_get_sysclk_rate(sample_rate);
520	int bclk_div, lrck_div_order, ret, word_size;
521	u32 clk_reg;
522
523	/* word size */
524	switch (params_width(params)) {
525	case 8:
526		word_size = 0x0;
527		break;
528	case 16:
529		word_size = 0x1;
530		break;
531	case 20:
532		word_size = 0x2;
533		break;
534	case 24:
535		word_size = 0x3;
536		break;
537	default:
538		return -EINVAL;
539	}
540
541	regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
542			   SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK,
543			   word_size << SUN8I_AIF_CLK_CTRL_WORD_SIZ);
544
545	/* LRCK divider (BCLK/LRCK ratio) */
546	lrck_div_order = sun8i_codec_get_lrck_div_order(slots, slot_width);
547	if (lrck_div_order < 0)
548		return lrck_div_order;
549
550	if (dai->id == SUN8I_CODEC_AIF2 || dai->id == SUN8I_CODEC_AIF3) {
551		/* AIF2 and AIF3 share AIF2's BCLK and LRCK generation circuitry. */
552		int partner = (SUN8I_CODEC_AIF2 + SUN8I_CODEC_AIF3) - dai->id;
553		const struct sun8i_codec_aif *partner_aif = &scodec->aifs[partner];
554		const char *partner_name = sun8i_codec_dais[partner].name;
555
556		if (partner_aif->open_streams &&
557		    (lrck_div_order != partner_aif->lrck_div_order ||
558		     sample_rate != partner_aif->sample_rate)) {
559			dev_err(dai->dev,
560				"%s sample and bit rates must match %s when both are used\n",
561				dai->name, partner_name);
562			return -EBUSY;
563		}
564
565		clk_reg = SUN8I_AIF_CLK_CTRL(SUN8I_CODEC_AIF2);
566	} else {
567		clk_reg = SUN8I_AIF_CLK_CTRL(dai->id);
568	}
569
570	regmap_update_bits(scodec->regmap, clk_reg,
571			   SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK,
572			   (lrck_div_order - 4) << SUN8I_AIF_CLK_CTRL_LRCK_DIV);
573
574	/* BCLK divider (SYSCLK/BCLK ratio) */
575	bclk_div = sun8i_codec_get_bclk_div(sysclk_rate, lrck_div_order, sample_rate);
576	if (bclk_div < 0)
577		return bclk_div;
578
579	regmap_update_bits(scodec->regmap, clk_reg,
580			   SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK,
581			   bclk_div << SUN8I_AIF_CLK_CTRL_BCLK_DIV);
582
583	/*
584	 * SYSCLK rate
585	 *
586	 * Clock rate protection is reference counted; but hw_params may be
587	 * called many times per substream, without matching calls to hw_free.
588	 * Protect the clock rate once per AIF, on the first hw_params call
589	 * for the first substream. clk_set_rate() will allow clock rate
590	 * changes on subsequent calls if only one AIF has open streams.
591	 */
592	ret = (aif->open_streams ? clk_set_rate : clk_set_rate_exclusive)(scodec->clk_module,
593									  sysclk_rate);
594	if (ret == -EBUSY)
595		dev_err(dai->dev,
596			"%s sample rate (%u Hz) conflicts with other audio streams\n",
597			dai->name, sample_rate);
598	if (ret < 0)
599		return ret;
600
601	if (!aif->open_streams)
602		scodec->sysclk_refcnt++;
603	scodec->sysclk_rate = sysclk_rate;
604
605	aif->lrck_div_order = lrck_div_order;
606	aif->sample_rate = sample_rate;
607	aif->open_streams |= BIT(substream->stream);
608
609	return sun8i_codec_update_sample_rate(scodec);
610}
611
612static int sun8i_codec_hw_free(struct snd_pcm_substream *substream,
613			       struct snd_soc_dai *dai)
614{
615	struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
616	struct sun8i_codec_aif *aif = &scodec->aifs[dai->id];
617
618	/* Drop references when the last substream for the AIF is freed. */
619	if (aif->open_streams != BIT(substream->stream))
620		goto done;
621
622	clk_rate_exclusive_put(scodec->clk_module);
623	scodec->sysclk_refcnt--;
624	aif->lrck_div_order = 0;
625	aif->sample_rate = 0;
626
627done:
628	aif->open_streams &= ~BIT(substream->stream);
629	return 0;
630}
631
632static const struct snd_soc_dai_ops sun8i_codec_dai_ops = {
633	.set_fmt	= sun8i_codec_set_fmt,
634	.set_tdm_slot	= sun8i_codec_set_tdm_slot,
635	.startup	= sun8i_codec_startup,
636	.hw_params	= sun8i_codec_hw_params,
637	.hw_free	= sun8i_codec_hw_free,
638};
639
640static struct snd_soc_dai_driver sun8i_codec_dais[] = {
641	{
642		.name	= "sun8i-codec-aif1",
643		.id	= SUN8I_CODEC_AIF1,
644		.ops	= &sun8i_codec_dai_ops,
645		/* capture capabilities */
646		.capture = {
647			.stream_name	= "AIF1 Capture",
648			.channels_min	= 1,
649			.channels_max	= 2,
650			.rates		= SUN8I_CODEC_PCM_RATES,
651			.formats	= SUN8I_CODEC_PCM_FORMATS,
652			.sig_bits	= 24,
653		},
654		/* playback capabilities */
655		.playback = {
656			.stream_name	= "AIF1 Playback",
657			.channels_min	= 1,
658			.channels_max	= 2,
659			.rates		= SUN8I_CODEC_PCM_RATES,
660			.formats	= SUN8I_CODEC_PCM_FORMATS,
661		},
662		.symmetric_rate		= true,
663		.symmetric_channels	= true,
664		.symmetric_sample_bits	= true,
665	},
666	{
667		.name	= "sun8i-codec-aif2",
668		.id	= SUN8I_CODEC_AIF2,
669		.ops	= &sun8i_codec_dai_ops,
670		/* capture capabilities */
671		.capture = {
672			.stream_name	= "AIF2 Capture",
673			.channels_min	= 1,
674			.channels_max	= 2,
675			.rates		= SUN8I_CODEC_PCM_RATES,
676			.formats	= SUN8I_CODEC_PCM_FORMATS,
677			.sig_bits	= 24,
678		},
679		/* playback capabilities */
680		.playback = {
681			.stream_name	= "AIF2 Playback",
682			.channels_min	= 1,
683			.channels_max	= 2,
684			.rates		= SUN8I_CODEC_PCM_RATES,
685			.formats	= SUN8I_CODEC_PCM_FORMATS,
686		},
687		.symmetric_rate		= true,
688		.symmetric_channels	= true,
689		.symmetric_sample_bits	= true,
690	},
691	{
692		.name	= "sun8i-codec-aif3",
693		.id	= SUN8I_CODEC_AIF3,
694		.ops	= &sun8i_codec_dai_ops,
695		/* capture capabilities */
696		.capture = {
697			.stream_name	= "AIF3 Capture",
698			.channels_min	= 1,
699			.channels_max	= 1,
700			.rates		= SUN8I_CODEC_PCM_RATES,
701			.formats	= SUN8I_CODEC_PCM_FORMATS,
702			.sig_bits	= 24,
703		},
704		/* playback capabilities */
705		.playback = {
706			.stream_name	= "AIF3 Playback",
707			.channels_min	= 1,
708			.channels_max	= 1,
709			.rates		= SUN8I_CODEC_PCM_RATES,
710			.formats	= SUN8I_CODEC_PCM_FORMATS,
711		},
712		.symmetric_rate		= true,
713		.symmetric_channels	= true,
714		.symmetric_sample_bits	= true,
715	},
716};
717
718static const DECLARE_TLV_DB_SCALE(sun8i_codec_vol_scale, -12000, 75, 1);
719
720static const struct snd_kcontrol_new sun8i_codec_controls[] = {
721	SOC_DOUBLE_TLV("AIF1 AD0 Capture Volume",
722		       SUN8I_AIF1_VOL_CTRL1,
723		       SUN8I_AIF1_VOL_CTRL1_AD0L_VOL,
724		       SUN8I_AIF1_VOL_CTRL1_AD0R_VOL,
725		       0xc0, 0, sun8i_codec_vol_scale),
726	SOC_DOUBLE_TLV("AIF1 DA0 Playback Volume",
727		       SUN8I_AIF1_VOL_CTRL3,
728		       SUN8I_AIF1_VOL_CTRL3_DA0L_VOL,
729		       SUN8I_AIF1_VOL_CTRL3_DA0R_VOL,
730		       0xc0, 0, sun8i_codec_vol_scale),
731	SOC_DOUBLE_TLV("AIF2 ADC Capture Volume",
732		       SUN8I_AIF2_VOL_CTRL1,
733		       SUN8I_AIF2_VOL_CTRL1_ADCL_VOL,
734		       SUN8I_AIF2_VOL_CTRL1_ADCR_VOL,
735		       0xc0, 0, sun8i_codec_vol_scale),
736	SOC_DOUBLE_TLV("AIF2 DAC Playback Volume",
737		       SUN8I_AIF2_VOL_CTRL2,
738		       SUN8I_AIF2_VOL_CTRL2_DACL_VOL,
739		       SUN8I_AIF2_VOL_CTRL2_DACR_VOL,
740		       0xc0, 0, sun8i_codec_vol_scale),
741	SOC_DOUBLE_TLV("ADC Capture Volume",
742		       SUN8I_ADC_VOL_CTRL,
743		       SUN8I_ADC_VOL_CTRL_ADCL_VOL,
744		       SUN8I_ADC_VOL_CTRL_ADCR_VOL,
745		       0xc0, 0, sun8i_codec_vol_scale),
746	SOC_DOUBLE_TLV("DAC Playback Volume",
747		       SUN8I_DAC_VOL_CTRL,
748		       SUN8I_DAC_VOL_CTRL_DACL_VOL,
749		       SUN8I_DAC_VOL_CTRL_DACR_VOL,
750		       0xc0, 0, sun8i_codec_vol_scale),
751};
752
753static int sun8i_codec_aif_event(struct snd_soc_dapm_widget *w,
754				 struct snd_kcontrol *kcontrol, int event)
755{
756	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
757	struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component);
758	struct sun8i_codec_aif *aif = &scodec->aifs[w->sname[3] - '1'];
759	int stream = w->id == snd_soc_dapm_aif_out;
760
761	if (SND_SOC_DAPM_EVENT_ON(event))
762		aif->active_streams |= BIT(stream);
763	else
764		aif->active_streams &= ~BIT(stream);
765
766	return sun8i_codec_update_sample_rate(scodec);
767}
768
769static const char *const sun8i_aif_stereo_mux_enum_values[] = {
770	"Stereo", "Reverse Stereo", "Sum Mono", "Mix Mono"
771};
772
773static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum,
774			    SUN8I_AIF1_ADCDAT_CTRL,
775			    SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC,
776			    SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC,
777			    sun8i_aif_stereo_mux_enum_values);
778
779static const struct snd_kcontrol_new sun8i_aif1_ad0_stereo_mux_control =
780	SOC_DAPM_ENUM("AIF1 AD0 Stereo Capture Route",
781		      sun8i_aif1_ad0_stereo_mux_enum);
782
783static SOC_ENUM_DOUBLE_DECL(sun8i_aif2_adc_stereo_mux_enum,
784			    SUN8I_AIF2_ADCDAT_CTRL,
785			    SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC,
786			    SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC,
787			    sun8i_aif_stereo_mux_enum_values);
788
789static const struct snd_kcontrol_new sun8i_aif2_adc_stereo_mux_control =
790	SOC_DAPM_ENUM("AIF2 ADC Stereo Capture Route",
791		      sun8i_aif2_adc_stereo_mux_enum);
792
793static const char *const sun8i_aif3_adc_mux_enum_values[] = {
794	"None", "AIF2 ADCL", "AIF2 ADCR"
795};
796
797static SOC_ENUM_SINGLE_DECL(sun8i_aif3_adc_mux_enum,
798			    SUN8I_AIF3_PATH_CTRL,
799			    SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC,
800			    sun8i_aif3_adc_mux_enum_values);
801
802static const struct snd_kcontrol_new sun8i_aif3_adc_mux_control =
803	SOC_DAPM_ENUM("AIF3 ADC Source Capture Route",
804		      sun8i_aif3_adc_mux_enum);
805
806static const struct snd_kcontrol_new sun8i_aif1_ad0_mixer_controls[] = {
807	SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital ADC Capture Switch",
808			SUN8I_AIF1_MXR_SRC,
809			SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L,
810			SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R, 1, 0),
811	SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch",
812			SUN8I_AIF1_MXR_SRC,
813			SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL,
814			SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR, 1, 0),
815	SOC_DAPM_DOUBLE("AIF1 Data Digital ADC Capture Switch",
816			SUN8I_AIF1_MXR_SRC,
817			SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL,
818			SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR, 1, 0),
819	SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch",
820			SUN8I_AIF1_MXR_SRC,
821			SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR,
822			SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL, 1, 0),
823};
824
825static const struct snd_kcontrol_new sun8i_aif2_adc_mixer_controls[] = {
826	SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA0 Capture Switch",
827			SUN8I_AIF2_MXR_SRC,
828			SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L,
829			SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R, 1, 0),
830	SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA1 Capture Switch",
831			SUN8I_AIF2_MXR_SRC,
832			SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L,
833			SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R, 1, 0),
834	SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF2 DAC Rev Capture Switch",
835			SUN8I_AIF2_MXR_SRC,
836			SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR,
837			SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL, 1, 0),
838	SOC_DAPM_DOUBLE("AIF2 ADC Mixer ADC Capture Switch",
839			SUN8I_AIF2_MXR_SRC,
840			SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL,
841			SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR, 1, 0),
842};
843
844static const char *const sun8i_aif2_dac_mux_enum_values[] = {
845	"AIF2", "AIF3+2", "AIF2+3"
846};
847
848static SOC_ENUM_SINGLE_DECL(sun8i_aif2_dac_mux_enum,
849			    SUN8I_AIF3_PATH_CTRL,
850			    SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC,
851			    sun8i_aif2_dac_mux_enum_values);
852
853static const struct snd_kcontrol_new sun8i_aif2_dac_mux_control =
854	SOC_DAPM_ENUM("AIF2 DAC Source Playback Route",
855		      sun8i_aif2_dac_mux_enum);
856
857static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_da0_stereo_mux_enum,
858			    SUN8I_AIF1_DACDAT_CTRL,
859			    SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC,
860			    SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC,
861			    sun8i_aif_stereo_mux_enum_values);
862
863static const struct snd_kcontrol_new sun8i_aif1_da0_stereo_mux_control =
864	SOC_DAPM_ENUM("AIF1 DA0 Stereo Playback Route",
865		      sun8i_aif1_da0_stereo_mux_enum);
866
867static SOC_ENUM_DOUBLE_DECL(sun8i_aif2_dac_stereo_mux_enum,
868			    SUN8I_AIF2_DACDAT_CTRL,
869			    SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC,
870			    SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC,
871			    sun8i_aif_stereo_mux_enum_values);
872
873static const struct snd_kcontrol_new sun8i_aif2_dac_stereo_mux_control =
874	SOC_DAPM_ENUM("AIF2 DAC Stereo Playback Route",
875		      sun8i_aif2_dac_stereo_mux_enum);
876
877static const struct snd_kcontrol_new sun8i_dac_mixer_controls[] = {
878	SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital DAC Playback Switch",
879			SUN8I_DAC_MXR_SRC,
880			SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L,
881			SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R, 1, 0),
882	SOC_DAPM_DOUBLE("AIF1 Slot 1 Digital DAC Playback Switch",
883			SUN8I_DAC_MXR_SRC,
884			SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L,
885			SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R, 1, 0),
886	SOC_DAPM_DOUBLE("AIF2 Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,
887			SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL,
888			SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR, 1, 0),
889	SOC_DAPM_DOUBLE("ADC Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,
890			SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL,
891			SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR, 1, 0),
892};
893
894static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = {
895	/* System Clocks */
896	SND_SOC_DAPM_CLOCK_SUPPLY("mod"),
897
898	SND_SOC_DAPM_SUPPLY("AIF1CLK",
899			    SUN8I_SYSCLK_CTL,
900			    SUN8I_SYSCLK_CTL_AIF1CLK_ENA, 0, NULL, 0),
901	SND_SOC_DAPM_SUPPLY("AIF2CLK",
902			    SUN8I_SYSCLK_CTL,
903			    SUN8I_SYSCLK_CTL_AIF2CLK_ENA, 0, NULL, 0),
904	SND_SOC_DAPM_SUPPLY("SYSCLK",
905			    SUN8I_SYSCLK_CTL,
906			    SUN8I_SYSCLK_CTL_SYSCLK_ENA, 0, NULL, 0),
907
908	/* Module Clocks */
909	SND_SOC_DAPM_SUPPLY("CLK AIF1",
910			    SUN8I_MOD_CLK_ENA,
911			    SUN8I_MOD_CLK_ENA_AIF1, 0, NULL, 0),
912	SND_SOC_DAPM_SUPPLY("CLK AIF2",
913			    SUN8I_MOD_CLK_ENA,
914			    SUN8I_MOD_CLK_ENA_AIF2, 0, NULL, 0),
915	SND_SOC_DAPM_SUPPLY("CLK AIF3",
916			    SUN8I_MOD_CLK_ENA,
917			    SUN8I_MOD_CLK_ENA_AIF3, 0, NULL, 0),
918	SND_SOC_DAPM_SUPPLY("CLK ADC",
919			    SUN8I_MOD_CLK_ENA,
920			    SUN8I_MOD_CLK_ENA_ADC, 0, NULL, 0),
921	SND_SOC_DAPM_SUPPLY("CLK DAC",
922			    SUN8I_MOD_CLK_ENA,
923			    SUN8I_MOD_CLK_ENA_DAC, 0, NULL, 0),
924
925	/* Module Resets */
926	SND_SOC_DAPM_SUPPLY("RST AIF1",
927			    SUN8I_MOD_RST_CTL,
928			    SUN8I_MOD_RST_CTL_AIF1, 0, NULL, 0),
929	SND_SOC_DAPM_SUPPLY("RST AIF2",
930			    SUN8I_MOD_RST_CTL,
931			    SUN8I_MOD_RST_CTL_AIF2, 0, NULL, 0),
932	SND_SOC_DAPM_SUPPLY("RST AIF3",
933			    SUN8I_MOD_RST_CTL,
934			    SUN8I_MOD_RST_CTL_AIF3, 0, NULL, 0),
935	SND_SOC_DAPM_SUPPLY("RST ADC",
936			    SUN8I_MOD_RST_CTL,
937			    SUN8I_MOD_RST_CTL_ADC, 0, NULL, 0),
938	SND_SOC_DAPM_SUPPLY("RST DAC",
939			    SUN8I_MOD_RST_CTL,
940			    SUN8I_MOD_RST_CTL_DAC, 0, NULL, 0),
941
942	/* Module Supplies */
943	SND_SOC_DAPM_SUPPLY("ADC",
944			    SUN8I_ADC_DIG_CTRL,
945			    SUN8I_ADC_DIG_CTRL_ENAD, 0, NULL, 0),
946	SND_SOC_DAPM_SUPPLY("DAC",
947			    SUN8I_DAC_DIG_CTRL,
948			    SUN8I_DAC_DIG_CTRL_ENDA, 0, NULL, 0),
949
950	/* AIF "ADC" Outputs */
951	SND_SOC_DAPM_AIF_OUT_E("AIF1 AD0L", "AIF1 Capture", 0,
952			       SUN8I_AIF1_ADCDAT_CTRL,
953			       SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA, 0,
954			       sun8i_codec_aif_event,
955			       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
956	SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "AIF1 Capture", 1,
957			     SUN8I_AIF1_ADCDAT_CTRL,
958			     SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA, 0),
959
960	SND_SOC_DAPM_AIF_OUT_E("AIF2 ADCL", "AIF2 Capture", 0,
961			       SUN8I_AIF2_ADCDAT_CTRL,
962			       SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA, 0,
963			       sun8i_codec_aif_event,
964			       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
965	SND_SOC_DAPM_AIF_OUT("AIF2 ADCR", "AIF2 Capture", 1,
966			     SUN8I_AIF2_ADCDAT_CTRL,
967			     SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA, 0),
968
969	SND_SOC_DAPM_AIF_OUT_E("AIF3 ADC", "AIF3 Capture", 0,
970			       SND_SOC_NOPM, 0, 0,
971			       sun8i_codec_aif_event,
972			       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
973
974	/* AIF "ADC" Mono/Stereo Muxes */
975	SND_SOC_DAPM_MUX("AIF1 AD0L Stereo Mux", SND_SOC_NOPM, 0, 0,
976			 &sun8i_aif1_ad0_stereo_mux_control),
977	SND_SOC_DAPM_MUX("AIF1 AD0R Stereo Mux", SND_SOC_NOPM, 0, 0,
978			 &sun8i_aif1_ad0_stereo_mux_control),
979
980	SND_SOC_DAPM_MUX("AIF2 ADCL Stereo Mux", SND_SOC_NOPM, 0, 0,
981			 &sun8i_aif2_adc_stereo_mux_control),
982	SND_SOC_DAPM_MUX("AIF2 ADCR Stereo Mux", SND_SOC_NOPM, 0, 0,
983			 &sun8i_aif2_adc_stereo_mux_control),
984
985	/* AIF "ADC" Output Muxes */
986	SND_SOC_DAPM_MUX("AIF3 ADC Source Capture Route", SND_SOC_NOPM, 0, 0,
987			 &sun8i_aif3_adc_mux_control),
988
989	/* AIF "ADC" Mixers */
990	SOC_MIXER_ARRAY("AIF1 AD0L Mixer", SND_SOC_NOPM, 0, 0,
991			sun8i_aif1_ad0_mixer_controls),
992	SOC_MIXER_ARRAY("AIF1 AD0R Mixer", SND_SOC_NOPM, 0, 0,
993			sun8i_aif1_ad0_mixer_controls),
994
995	SOC_MIXER_ARRAY("AIF2 ADCL Mixer", SND_SOC_NOPM, 0, 0,
996			sun8i_aif2_adc_mixer_controls),
997	SOC_MIXER_ARRAY("AIF2 ADCR Mixer", SND_SOC_NOPM, 0, 0,
998			sun8i_aif2_adc_mixer_controls),
999
1000	/* AIF "DAC" Input Muxes */
1001	SND_SOC_DAPM_MUX("AIF2 DACL Source", SND_SOC_NOPM, 0, 0,
1002			 &sun8i_aif2_dac_mux_control),
1003	SND_SOC_DAPM_MUX("AIF2 DACR Source", SND_SOC_NOPM, 0, 0,
1004			 &sun8i_aif2_dac_mux_control),
1005
1006	/* AIF "DAC" Mono/Stereo Muxes */
1007	SND_SOC_DAPM_MUX("AIF1 DA0L Stereo Mux", SND_SOC_NOPM, 0, 0,
1008			 &sun8i_aif1_da0_stereo_mux_control),
1009	SND_SOC_DAPM_MUX("AIF1 DA0R Stereo Mux", SND_SOC_NOPM, 0, 0,
1010			 &sun8i_aif1_da0_stereo_mux_control),
1011
1012	SND_SOC_DAPM_MUX("AIF2 DACL Stereo Mux", SND_SOC_NOPM, 0, 0,
1013			 &sun8i_aif2_dac_stereo_mux_control),
1014	SND_SOC_DAPM_MUX("AIF2 DACR Stereo Mux", SND_SOC_NOPM, 0, 0,
1015			 &sun8i_aif2_dac_stereo_mux_control),
1016
1017	/* AIF "DAC" Inputs */
1018	SND_SOC_DAPM_AIF_IN_E("AIF1 DA0L", "AIF1 Playback", 0,
1019			      SUN8I_AIF1_DACDAT_CTRL,
1020			      SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA, 0,
1021			      sun8i_codec_aif_event,
1022			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1023	SND_SOC_DAPM_AIF_IN("AIF1 DA0R", "AIF1 Playback", 1,
1024			    SUN8I_AIF1_DACDAT_CTRL,
1025			    SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA, 0),
1026
1027	SND_SOC_DAPM_AIF_IN_E("AIF2 DACL", "AIF2 Playback", 0,
1028			      SUN8I_AIF2_DACDAT_CTRL,
1029			      SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_ENA, 0,
1030			      sun8i_codec_aif_event,
1031			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1032	SND_SOC_DAPM_AIF_IN("AIF2 DACR", "AIF2 Playback", 1,
1033			    SUN8I_AIF2_DACDAT_CTRL,
1034			    SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_ENA, 0),
1035
1036	SND_SOC_DAPM_AIF_IN_E("AIF3 DAC", "AIF3 Playback", 0,
1037			      SND_SOC_NOPM, 0, 0,
1038			      sun8i_codec_aif_event,
1039			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1040
1041	/* ADC Inputs (connected to analog codec DAPM context) */
1042	SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 0, 0),
1043	SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0),
1044
1045	/* DAC Outputs (connected to analog codec DAPM context) */
1046	SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
1047	SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
1048
1049	/* DAC Mixers */
1050	SOC_MIXER_ARRAY("DACL Mixer", SND_SOC_NOPM, 0, 0,
1051			sun8i_dac_mixer_controls),
1052	SOC_MIXER_ARRAY("DACR Mixer", SND_SOC_NOPM, 0, 0,
1053			sun8i_dac_mixer_controls),
1054};
1055
1056static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = {
1057	/* Clock Routes */
1058	{ "AIF1CLK", NULL, "mod" },
1059
1060	{ "SYSCLK", NULL, "AIF1CLK" },
1061
1062	{ "CLK AIF1", NULL, "AIF1CLK" },
1063	{ "CLK AIF1", NULL, "SYSCLK" },
1064	{ "RST AIF1", NULL, "CLK AIF1" },
1065	{ "AIF1 AD0L", NULL, "RST AIF1" },
1066	{ "AIF1 AD0R", NULL, "RST AIF1" },
1067	{ "AIF1 DA0L", NULL, "RST AIF1" },
1068	{ "AIF1 DA0R", NULL, "RST AIF1" },
1069
1070	{ "CLK AIF2", NULL, "AIF2CLK" },
1071	{ "CLK AIF2", NULL, "SYSCLK" },
1072	{ "RST AIF2", NULL, "CLK AIF2" },
1073	{ "AIF2 ADCL", NULL, "RST AIF2" },
1074	{ "AIF2 ADCR", NULL, "RST AIF2" },
1075	{ "AIF2 DACL", NULL, "RST AIF2" },
1076	{ "AIF2 DACR", NULL, "RST AIF2" },
1077
1078	{ "CLK AIF3", NULL, "AIF1CLK" },
1079	{ "CLK AIF3", NULL, "SYSCLK" },
1080	{ "RST AIF3", NULL, "CLK AIF3" },
1081	{ "AIF3 ADC", NULL, "RST AIF3" },
1082	{ "AIF3 DAC", NULL, "RST AIF3" },
1083
1084	{ "CLK ADC", NULL, "SYSCLK" },
1085	{ "RST ADC", NULL, "CLK ADC" },
1086	{ "ADC", NULL, "RST ADC" },
1087	{ "ADCL", NULL, "ADC" },
1088	{ "ADCR", NULL, "ADC" },
1089
1090	{ "CLK DAC", NULL, "SYSCLK" },
1091	{ "RST DAC", NULL, "CLK DAC" },
1092	{ "DAC", NULL, "RST DAC" },
1093	{ "DACL", NULL, "DAC" },
1094	{ "DACR", NULL, "DAC" },
1095
1096	/* AIF "ADC" Output Routes */
1097	{ "AIF1 AD0L", NULL, "AIF1 AD0L Stereo Mux" },
1098	{ "AIF1 AD0R", NULL, "AIF1 AD0R Stereo Mux" },
1099
1100	{ "AIF2 ADCL", NULL, "AIF2 ADCL Stereo Mux" },
1101	{ "AIF2 ADCR", NULL, "AIF2 ADCR Stereo Mux" },
1102
1103	{ "AIF3 ADC", NULL, "AIF3 ADC Source Capture Route" },
1104
1105	/* AIF "ADC" Mono/Stereo Mux Routes */
1106	{ "AIF1 AD0L Stereo Mux", "Stereo", "AIF1 AD0L Mixer" },
1107	{ "AIF1 AD0L Stereo Mux", "Reverse Stereo", "AIF1 AD0R Mixer" },
1108	{ "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" },
1109	{ "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" },
1110	{ "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" },
1111	{ "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" },
1112
1113	{ "AIF1 AD0R Stereo Mux", "Stereo", "AIF1 AD0R Mixer" },
1114	{ "AIF1 AD0R Stereo Mux", "Reverse Stereo", "AIF1 AD0L Mixer" },
1115	{ "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" },
1116	{ "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" },
1117	{ "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" },
1118	{ "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" },
1119
1120	{ "AIF2 ADCL Stereo Mux", "Stereo", "AIF2 ADCL Mixer" },
1121	{ "AIF2 ADCL Stereo Mux", "Reverse Stereo", "AIF2 ADCR Mixer" },
1122	{ "AIF2 ADCL Stereo Mux", "Sum Mono", "AIF2 ADCL Mixer" },
1123	{ "AIF2 ADCL Stereo Mux", "Sum Mono", "AIF2 ADCR Mixer" },
1124	{ "AIF2 ADCL Stereo Mux", "Mix Mono", "AIF2 ADCL Mixer" },
1125	{ "AIF2 ADCL Stereo Mux", "Mix Mono", "AIF2 ADCR Mixer" },
1126
1127	{ "AIF2 ADCR Stereo Mux", "Stereo", "AIF2 ADCR Mixer" },
1128	{ "AIF2 ADCR Stereo Mux", "Reverse Stereo", "AIF2 ADCL Mixer" },
1129	{ "AIF2 ADCR Stereo Mux", "Sum Mono", "AIF2 ADCL Mixer" },
1130	{ "AIF2 ADCR Stereo Mux", "Sum Mono", "AIF2 ADCR Mixer" },
1131	{ "AIF2 ADCR Stereo Mux", "Mix Mono", "AIF2 ADCL Mixer" },
1132	{ "AIF2 ADCR Stereo Mux", "Mix Mono", "AIF2 ADCR Mixer" },
1133
1134	/* AIF "ADC" Output Mux Routes */
1135	{ "AIF3 ADC Source Capture Route", "AIF2 ADCL", "AIF2 ADCL Mixer" },
1136	{ "AIF3 ADC Source Capture Route", "AIF2 ADCR", "AIF2 ADCR Mixer" },
1137
1138	/* AIF "ADC" Mixer Routes */
1139	{ "AIF1 AD0L Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0L Stereo Mux" },
1140	{ "AIF1 AD0L Mixer", "AIF2 Digital ADC Capture Switch", "AIF2 DACL Source" },
1141	{ "AIF1 AD0L Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCL" },
1142	{ "AIF1 AD0L Mixer", "AIF2 Inv Digital ADC Capture Switch", "AIF2 DACR Source" },
1143
1144	{ "AIF1 AD0R Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0R Stereo Mux" },
1145	{ "AIF1 AD0R Mixer", "AIF2 Digital ADC Capture Switch", "AIF2 DACR Source" },
1146	{ "AIF1 AD0R Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCR" },
1147	{ "AIF1 AD0R Mixer", "AIF2 Inv Digital ADC Capture Switch", "AIF2 DACL Source" },
1148
1149	{ "AIF2 ADCL Mixer", "AIF2 ADC Mixer AIF1 DA0 Capture Switch", "AIF1 DA0L Stereo Mux" },
1150	{ "AIF2 ADCL Mixer", "AIF2 ADC Mixer AIF2 DAC Rev Capture Switch", "AIF2 DACR Source" },
1151	{ "AIF2 ADCL Mixer", "AIF2 ADC Mixer ADC Capture Switch", "ADCL" },
1152
1153	{ "AIF2 ADCR Mixer", "AIF2 ADC Mixer AIF1 DA0 Capture Switch", "AIF1 DA0R Stereo Mux" },
1154	{ "AIF2 ADCR Mixer", "AIF2 ADC Mixer AIF2 DAC Rev Capture Switch", "AIF2 DACL Source" },
1155	{ "AIF2 ADCR Mixer", "AIF2 ADC Mixer ADC Capture Switch", "ADCR" },
1156
1157	/* AIF "DAC" Input Mux Routes */
1158	{ "AIF2 DACL Source", "AIF2", "AIF2 DACL Stereo Mux" },
1159	{ "AIF2 DACL Source", "AIF3+2", "AIF3 DAC" },
1160	{ "AIF2 DACL Source", "AIF2+3", "AIF2 DACL Stereo Mux" },
1161
1162	{ "AIF2 DACR Source", "AIF2", "AIF2 DACR Stereo Mux" },
1163	{ "AIF2 DACR Source", "AIF3+2", "AIF2 DACR Stereo Mux" },
1164	{ "AIF2 DACR Source", "AIF2+3", "AIF3 DAC" },
1165
1166	/* AIF "DAC" Mono/Stereo Mux Routes */
1167	{ "AIF1 DA0L Stereo Mux", "Stereo", "AIF1 DA0L" },
1168	{ "AIF1 DA0L Stereo Mux", "Reverse Stereo", "AIF1 DA0R" },
1169	{ "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0L" },
1170	{ "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0R" },
1171	{ "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0L" },
1172	{ "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0R" },
1173
1174	{ "AIF1 DA0R Stereo Mux", "Stereo", "AIF1 DA0R" },
1175	{ "AIF1 DA0R Stereo Mux", "Reverse Stereo", "AIF1 DA0L" },
1176	{ "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0L" },
1177	{ "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0R" },
1178	{ "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0L" },
1179	{ "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0R" },
1180
1181	{ "AIF2 DACL Stereo Mux", "Stereo", "AIF2 DACL" },
1182	{ "AIF2 DACL Stereo Mux", "Reverse Stereo", "AIF2 DACR" },
1183	{ "AIF2 DACL Stereo Mux", "Sum Mono", "AIF2 DACL" },
1184	{ "AIF2 DACL Stereo Mux", "Sum Mono", "AIF2 DACR" },
1185	{ "AIF2 DACL Stereo Mux", "Mix Mono", "AIF2 DACL" },
1186	{ "AIF2 DACL Stereo Mux", "Mix Mono", "AIF2 DACR" },
1187
1188	{ "AIF2 DACR Stereo Mux", "Stereo", "AIF2 DACR" },
1189	{ "AIF2 DACR Stereo Mux", "Reverse Stereo", "AIF2 DACL" },
1190	{ "AIF2 DACR Stereo Mux", "Sum Mono", "AIF2 DACL" },
1191	{ "AIF2 DACR Stereo Mux", "Sum Mono", "AIF2 DACR" },
1192	{ "AIF2 DACR Stereo Mux", "Mix Mono", "AIF2 DACL" },
1193	{ "AIF2 DACR Stereo Mux", "Mix Mono", "AIF2 DACR" },
1194
1195	/* DAC Output Routes */
1196	{ "DACL", NULL, "DACL Mixer" },
1197	{ "DACR", NULL, "DACR Mixer" },
1198
1199	/* DAC Mixer Routes */
1200	{ "DACL Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0L Stereo Mux" },
1201	{ "DACL Mixer", "AIF2 Digital DAC Playback Switch", "AIF2 DACL Source" },
1202	{ "DACL Mixer", "ADC Digital DAC Playback Switch", "ADCL" },
1203
1204	{ "DACR Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0R Stereo Mux" },
1205	{ "DACR Mixer", "AIF2 Digital DAC Playback Switch", "AIF2 DACR Source" },
1206	{ "DACR Mixer", "ADC Digital DAC Playback Switch", "ADCR" },
1207};
1208
1209static const struct snd_soc_dapm_widget sun8i_codec_legacy_widgets[] = {
1210	/* Legacy ADC Inputs (connected to analog codec DAPM context) */
1211	SND_SOC_DAPM_ADC("AIF1 Slot 0 Left ADC", NULL, SND_SOC_NOPM, 0, 0),
1212	SND_SOC_DAPM_ADC("AIF1 Slot 0 Right ADC", NULL, SND_SOC_NOPM, 0, 0),
1213
1214	/* Legacy DAC Outputs (connected to analog codec DAPM context) */
1215	SND_SOC_DAPM_DAC("AIF1 Slot 0 Left", NULL, SND_SOC_NOPM, 0, 0),
1216	SND_SOC_DAPM_DAC("AIF1 Slot 0 Right", NULL, SND_SOC_NOPM, 0, 0),
1217};
1218
1219static const struct snd_soc_dapm_route sun8i_codec_legacy_routes[] = {
1220	/* Legacy ADC Routes */
1221	{ "ADCL", NULL, "AIF1 Slot 0 Left ADC" },
1222	{ "ADCR", NULL, "AIF1 Slot 0 Right ADC" },
1223
1224	/* Legacy DAC Routes */
1225	{ "AIF1 Slot 0 Left", NULL, "DACL" },
1226	{ "AIF1 Slot 0 Right", NULL, "DACR" },
1227};
1228
1229static int sun8i_codec_component_probe(struct snd_soc_component *component)
1230{
1231	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
1232	struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component);
1233	int ret;
1234
1235	/* Add widgets for backward compatibility with old device trees. */
1236	if (scodec->quirks->legacy_widgets) {
1237		ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_legacy_widgets,
1238						ARRAY_SIZE(sun8i_codec_legacy_widgets));
1239		if (ret)
1240			return ret;
1241
1242		ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_legacy_routes,
1243					      ARRAY_SIZE(sun8i_codec_legacy_routes));
1244		if (ret)
1245			return ret;
1246	}
1247
1248	/*
1249	 * AIF1CLK and AIF2CLK share a pair of clock parents: PLL_AUDIO ("mod")
1250	 * and MCLK (from the CPU DAI connected to AIF1). MCLK's parent is also
1251	 * PLL_AUDIO, so using it adds no additional flexibility. Use PLL_AUDIO
1252	 * directly to simplify the clock tree.
1253	 */
1254	regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL,
1255			   SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK |
1256			   SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK,
1257			   SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL |
1258			   SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL);
1259
1260	/* Use AIF1CLK as the SYSCLK parent since AIF1 is used most often. */
1261	regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL,
1262			   BIT(SUN8I_SYSCLK_CTL_SYSCLK_SRC),
1263			   SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK);
1264
1265	/* Program the default sample rate. */
1266	sun8i_codec_update_sample_rate(scodec);
1267
1268	return 0;
1269}
1270
1271static const struct snd_soc_component_driver sun8i_soc_component = {
1272	.controls		= sun8i_codec_controls,
1273	.num_controls		= ARRAY_SIZE(sun8i_codec_controls),
1274	.dapm_widgets		= sun8i_codec_dapm_widgets,
1275	.num_dapm_widgets	= ARRAY_SIZE(sun8i_codec_dapm_widgets),
1276	.dapm_routes		= sun8i_codec_dapm_routes,
1277	.num_dapm_routes	= ARRAY_SIZE(sun8i_codec_dapm_routes),
1278	.probe			= sun8i_codec_component_probe,
1279	.idle_bias_on		= 1,
1280	.endianness		= 1,
1281};
1282
1283static const struct regmap_config sun8i_codec_regmap_config = {
1284	.reg_bits	= 32,
1285	.reg_stride	= 4,
1286	.val_bits	= 32,
1287	.max_register	= SUN8I_DAC_MXR_SRC,
1288
1289	.cache_type	= REGCACHE_FLAT,
1290};
1291
1292static int sun8i_codec_probe(struct platform_device *pdev)
1293{
1294	struct sun8i_codec *scodec;
1295	void __iomem *base;
1296	int ret;
1297
1298	scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL);
1299	if (!scodec)
1300		return -ENOMEM;
1301
1302	scodec->clk_module = devm_clk_get(&pdev->dev, "mod");
1303	if (IS_ERR(scodec->clk_module)) {
1304		dev_err(&pdev->dev, "Failed to get the module clock\n");
1305		return PTR_ERR(scodec->clk_module);
1306	}
1307
1308	base = devm_platform_ioremap_resource(pdev, 0);
1309	if (IS_ERR(base)) {
1310		dev_err(&pdev->dev, "Failed to map the registers\n");
1311		return PTR_ERR(base);
1312	}
1313
1314	scodec->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "bus", base,
1315						   &sun8i_codec_regmap_config);
1316	if (IS_ERR(scodec->regmap)) {
1317		dev_err(&pdev->dev, "Failed to create our regmap\n");
1318		return PTR_ERR(scodec->regmap);
1319	}
1320
1321	scodec->quirks = of_device_get_match_data(&pdev->dev);
1322
1323	platform_set_drvdata(pdev, scodec);
1324
1325	pm_runtime_enable(&pdev->dev);
1326	if (!pm_runtime_enabled(&pdev->dev)) {
1327		ret = sun8i_codec_runtime_resume(&pdev->dev);
1328		if (ret)
1329			goto err_pm_disable;
1330	}
1331
1332	ret = devm_snd_soc_register_component(&pdev->dev, &sun8i_soc_component,
1333					      sun8i_codec_dais,
1334					      ARRAY_SIZE(sun8i_codec_dais));
1335	if (ret) {
1336		dev_err(&pdev->dev, "Failed to register codec\n");
1337		goto err_suspend;
1338	}
1339
1340	return ret;
1341
1342err_suspend:
1343	if (!pm_runtime_status_suspended(&pdev->dev))
1344		sun8i_codec_runtime_suspend(&pdev->dev);
1345
1346err_pm_disable:
1347	pm_runtime_disable(&pdev->dev);
1348
1349	return ret;
1350}
1351
1352static void sun8i_codec_remove(struct platform_device *pdev)
1353{
1354	pm_runtime_disable(&pdev->dev);
1355	if (!pm_runtime_status_suspended(&pdev->dev))
1356		sun8i_codec_runtime_suspend(&pdev->dev);
1357}
1358
1359static const struct sun8i_codec_quirks sun8i_a33_quirks = {
1360	.legacy_widgets	= true,
1361	.lrck_inversion	= true,
1362};
1363
1364static const struct sun8i_codec_quirks sun50i_a64_quirks = {
1365};
1366
1367static const struct of_device_id sun8i_codec_of_match[] = {
1368	{ .compatible = "allwinner,sun8i-a33-codec", .data = &sun8i_a33_quirks },
1369	{ .compatible = "allwinner,sun50i-a64-codec", .data = &sun50i_a64_quirks },
1370	{}
1371};
1372MODULE_DEVICE_TABLE(of, sun8i_codec_of_match);
1373
1374static const struct dev_pm_ops sun8i_codec_pm_ops = {
1375	SET_RUNTIME_PM_OPS(sun8i_codec_runtime_suspend,
1376			   sun8i_codec_runtime_resume, NULL)
1377};
1378
1379static struct platform_driver sun8i_codec_driver = {
1380	.driver = {
1381		.name = "sun8i-codec",
1382		.of_match_table = sun8i_codec_of_match,
1383		.pm = &sun8i_codec_pm_ops,
1384	},
1385	.probe = sun8i_codec_probe,
1386	.remove_new = sun8i_codec_remove,
1387};
1388module_platform_driver(sun8i_codec_driver);
1389
1390MODULE_DESCRIPTION("Allwinner A33 (sun8i) codec driver");
1391MODULE_AUTHOR("Myl��ne Josserand <mylene.josserand@free-electrons.com>");
1392MODULE_LICENSE("GPL");
1393MODULE_ALIAS("platform:sun8i-codec");
1394