xref: /OK3568_Linux_fs/kernel/sound/soc/sunxi/sun50i-codec-analog.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * This driver supports the analog controls for the internal codec
4*4882a593Smuzhiyun  * found in Allwinner's A64 SoC.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright (C) 2016 Chen-Yu Tsai <wens@csie.org>
7*4882a593Smuzhiyun  * Copyright (C) 2017 Marcus Cooper <codekipper@gmail.com>
8*4882a593Smuzhiyun  * Copyright (C) 2018 Vasily Khoruzhick <anarsoul@gmail.com>
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * Based on sun8i-codec-analog.c
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <linux/io.h>
15*4882a593Smuzhiyun #include <linux/kernel.h>
16*4882a593Smuzhiyun #include <linux/module.h>
17*4882a593Smuzhiyun #include <linux/of.h>
18*4882a593Smuzhiyun #include <linux/of_device.h>
19*4882a593Smuzhiyun #include <linux/platform_device.h>
20*4882a593Smuzhiyun #include <linux/regmap.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #include <sound/soc.h>
23*4882a593Smuzhiyun #include <sound/soc-dapm.h>
24*4882a593Smuzhiyun #include <sound/tlv.h>
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #include "sun8i-adda-pr-regmap.h"
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /* Codec analog control register offsets and bit fields */
29*4882a593Smuzhiyun #define SUN50I_ADDA_HP_CTRL		0x00
30*4882a593Smuzhiyun #define SUN50I_ADDA_HP_CTRL_PA_CLK_GATE		7
31*4882a593Smuzhiyun #define SUN50I_ADDA_HP_CTRL_HPPA_EN		6
32*4882a593Smuzhiyun #define SUN50I_ADDA_HP_CTRL_HPVOL		0
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define SUN50I_ADDA_OL_MIX_CTRL		0x01
35*4882a593Smuzhiyun #define SUN50I_ADDA_OL_MIX_CTRL_MIC1		6
36*4882a593Smuzhiyun #define SUN50I_ADDA_OL_MIX_CTRL_MIC2		5
37*4882a593Smuzhiyun #define SUN50I_ADDA_OL_MIX_CTRL_PHONE		4
38*4882a593Smuzhiyun #define SUN50I_ADDA_OL_MIX_CTRL_PHONEN		3
39*4882a593Smuzhiyun #define SUN50I_ADDA_OL_MIX_CTRL_LINEINL		2
40*4882a593Smuzhiyun #define SUN50I_ADDA_OL_MIX_CTRL_DACL		1
41*4882a593Smuzhiyun #define SUN50I_ADDA_OL_MIX_CTRL_DACR		0
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun #define SUN50I_ADDA_OR_MIX_CTRL		0x02
44*4882a593Smuzhiyun #define SUN50I_ADDA_OR_MIX_CTRL_MIC1		6
45*4882a593Smuzhiyun #define SUN50I_ADDA_OR_MIX_CTRL_MIC2		5
46*4882a593Smuzhiyun #define SUN50I_ADDA_OR_MIX_CTRL_PHONE		4
47*4882a593Smuzhiyun #define SUN50I_ADDA_OR_MIX_CTRL_PHONEP		3
48*4882a593Smuzhiyun #define SUN50I_ADDA_OR_MIX_CTRL_LINEINR		2
49*4882a593Smuzhiyun #define SUN50I_ADDA_OR_MIX_CTRL_DACR		1
50*4882a593Smuzhiyun #define SUN50I_ADDA_OR_MIX_CTRL_DACL		0
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun #define SUN50I_ADDA_EARPIECE_CTRL0	0x03
53*4882a593Smuzhiyun #define SUN50I_ADDA_EARPIECE_CTRL0_EAR_RAMP_TIME	4
54*4882a593Smuzhiyun #define SUN50I_ADDA_EARPIECE_CTRL0_ESPSR		0
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun #define SUN50I_ADDA_EARPIECE_CTRL1	0x04
57*4882a593Smuzhiyun #define SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_EN	7
58*4882a593Smuzhiyun #define SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_MUTE	6
59*4882a593Smuzhiyun #define SUN50I_ADDA_EARPIECE_CTRL1_ESP_VOL	0
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun #define SUN50I_ADDA_LINEOUT_CTRL0	0x05
62*4882a593Smuzhiyun #define SUN50I_ADDA_LINEOUT_CTRL0_LEN		7
63*4882a593Smuzhiyun #define SUN50I_ADDA_LINEOUT_CTRL0_REN		6
64*4882a593Smuzhiyun #define SUN50I_ADDA_LINEOUT_CTRL0_LSRC_SEL	5
65*4882a593Smuzhiyun #define SUN50I_ADDA_LINEOUT_CTRL0_RSRC_SEL	4
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun #define SUN50I_ADDA_LINEOUT_CTRL1	0x06
68*4882a593Smuzhiyun #define SUN50I_ADDA_LINEOUT_CTRL1_VOL		0
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun #define SUN50I_ADDA_MIC1_CTRL		0x07
71*4882a593Smuzhiyun #define SUN50I_ADDA_MIC1_CTRL_MIC1G		4
72*4882a593Smuzhiyun #define SUN50I_ADDA_MIC1_CTRL_MIC1AMPEN		3
73*4882a593Smuzhiyun #define SUN50I_ADDA_MIC1_CTRL_MIC1BOOST		0
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun #define SUN50I_ADDA_MIC2_CTRL		0x08
76*4882a593Smuzhiyun #define SUN50I_ADDA_MIC2_CTRL_MIC2G		4
77*4882a593Smuzhiyun #define SUN50I_ADDA_MIC2_CTRL_MIC2AMPEN		3
78*4882a593Smuzhiyun #define SUN50I_ADDA_MIC2_CTRL_MIC2BOOST		0
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun #define SUN50I_ADDA_LINEIN_CTRL		0x09
81*4882a593Smuzhiyun #define SUN50I_ADDA_LINEIN_CTRL_LINEING		0
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun #define SUN50I_ADDA_MIX_DAC_CTRL	0x0a
84*4882a593Smuzhiyun #define SUN50I_ADDA_MIX_DAC_CTRL_DACAREN	7
85*4882a593Smuzhiyun #define SUN50I_ADDA_MIX_DAC_CTRL_DACALEN	6
86*4882a593Smuzhiyun #define SUN50I_ADDA_MIX_DAC_CTRL_RMIXEN		5
87*4882a593Smuzhiyun #define SUN50I_ADDA_MIX_DAC_CTRL_LMIXEN		4
88*4882a593Smuzhiyun #define SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE	3
89*4882a593Smuzhiyun #define SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE	2
90*4882a593Smuzhiyun #define SUN50I_ADDA_MIX_DAC_CTRL_RHPIS		1
91*4882a593Smuzhiyun #define SUN50I_ADDA_MIX_DAC_CTRL_LHPIS		0
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun #define SUN50I_ADDA_L_ADCMIX_SRC	0x0b
94*4882a593Smuzhiyun #define SUN50I_ADDA_L_ADCMIX_SRC_MIC1		6
95*4882a593Smuzhiyun #define SUN50I_ADDA_L_ADCMIX_SRC_MIC2		5
96*4882a593Smuzhiyun #define SUN50I_ADDA_L_ADCMIX_SRC_PHONE		4
97*4882a593Smuzhiyun #define SUN50I_ADDA_L_ADCMIX_SRC_PHONEN		3
98*4882a593Smuzhiyun #define SUN50I_ADDA_L_ADCMIX_SRC_LINEINL	2
99*4882a593Smuzhiyun #define SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL		1
100*4882a593Smuzhiyun #define SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR		0
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun #define SUN50I_ADDA_R_ADCMIX_SRC	0x0c
103*4882a593Smuzhiyun #define SUN50I_ADDA_R_ADCMIX_SRC_MIC1		6
104*4882a593Smuzhiyun #define SUN50I_ADDA_R_ADCMIX_SRC_MIC2		5
105*4882a593Smuzhiyun #define SUN50I_ADDA_R_ADCMIX_SRC_PHONE		4
106*4882a593Smuzhiyun #define SUN50I_ADDA_R_ADCMIX_SRC_PHONEP		3
107*4882a593Smuzhiyun #define SUN50I_ADDA_R_ADCMIX_SRC_LINEINR	2
108*4882a593Smuzhiyun #define SUN50I_ADDA_R_ADCMIX_SRC_OMIXR		1
109*4882a593Smuzhiyun #define SUN50I_ADDA_R_ADCMIX_SRC_OMIXL		0
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun #define SUN50I_ADDA_ADC_CTRL		0x0d
112*4882a593Smuzhiyun #define SUN50I_ADDA_ADC_CTRL_ADCREN		7
113*4882a593Smuzhiyun #define SUN50I_ADDA_ADC_CTRL_ADCLEN		6
114*4882a593Smuzhiyun #define SUN50I_ADDA_ADC_CTRL_ADCG		0
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun #define SUN50I_ADDA_HS_MBIAS_CTRL	0x0e
117*4882a593Smuzhiyun #define SUN50I_ADDA_HS_MBIAS_CTRL_MMICBIASEN	7
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun #define SUN50I_ADDA_JACK_MIC_CTRL	0x1d
120*4882a593Smuzhiyun #define SUN50I_ADDA_JACK_MIC_CTRL_HMICBIASEN	5
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun /* mixer controls */
123*4882a593Smuzhiyun static const struct snd_kcontrol_new sun50i_a64_codec_mixer_controls[] = {
124*4882a593Smuzhiyun 	SOC_DAPM_DOUBLE_R("Mic1 Playback Switch",
125*4882a593Smuzhiyun 			  SUN50I_ADDA_OL_MIX_CTRL,
126*4882a593Smuzhiyun 			  SUN50I_ADDA_OR_MIX_CTRL,
127*4882a593Smuzhiyun 			  SUN50I_ADDA_OL_MIX_CTRL_MIC1, 1, 0),
128*4882a593Smuzhiyun 	SOC_DAPM_DOUBLE_R("Mic2 Playback Switch",
129*4882a593Smuzhiyun 			  SUN50I_ADDA_OL_MIX_CTRL,
130*4882a593Smuzhiyun 			  SUN50I_ADDA_OR_MIX_CTRL,
131*4882a593Smuzhiyun 			  SUN50I_ADDA_OL_MIX_CTRL_MIC2, 1, 0),
132*4882a593Smuzhiyun 	SOC_DAPM_DOUBLE_R("Line In Playback Switch",
133*4882a593Smuzhiyun 			  SUN50I_ADDA_OL_MIX_CTRL,
134*4882a593Smuzhiyun 			  SUN50I_ADDA_OR_MIX_CTRL,
135*4882a593Smuzhiyun 			  SUN50I_ADDA_OL_MIX_CTRL_LINEINL, 1, 0),
136*4882a593Smuzhiyun 	SOC_DAPM_DOUBLE_R("DAC Playback Switch",
137*4882a593Smuzhiyun 			  SUN50I_ADDA_OL_MIX_CTRL,
138*4882a593Smuzhiyun 			  SUN50I_ADDA_OR_MIX_CTRL,
139*4882a593Smuzhiyun 			  SUN50I_ADDA_OL_MIX_CTRL_DACL, 1, 0),
140*4882a593Smuzhiyun 	SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch",
141*4882a593Smuzhiyun 			  SUN50I_ADDA_OL_MIX_CTRL,
142*4882a593Smuzhiyun 			  SUN50I_ADDA_OR_MIX_CTRL,
143*4882a593Smuzhiyun 			  SUN50I_ADDA_OL_MIX_CTRL_DACR, 1, 0),
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun /* ADC mixer controls */
147*4882a593Smuzhiyun static const struct snd_kcontrol_new sun50i_codec_adc_mixer_controls[] = {
148*4882a593Smuzhiyun 	SOC_DAPM_DOUBLE_R("Mic1 Capture Switch",
149*4882a593Smuzhiyun 			  SUN50I_ADDA_L_ADCMIX_SRC,
150*4882a593Smuzhiyun 			  SUN50I_ADDA_R_ADCMIX_SRC,
151*4882a593Smuzhiyun 			  SUN50I_ADDA_L_ADCMIX_SRC_MIC1, 1, 0),
152*4882a593Smuzhiyun 	SOC_DAPM_DOUBLE_R("Mic2 Capture Switch",
153*4882a593Smuzhiyun 			  SUN50I_ADDA_L_ADCMIX_SRC,
154*4882a593Smuzhiyun 			  SUN50I_ADDA_R_ADCMIX_SRC,
155*4882a593Smuzhiyun 			  SUN50I_ADDA_L_ADCMIX_SRC_MIC2, 1, 0),
156*4882a593Smuzhiyun 	SOC_DAPM_DOUBLE_R("Line In Capture Switch",
157*4882a593Smuzhiyun 			  SUN50I_ADDA_L_ADCMIX_SRC,
158*4882a593Smuzhiyun 			  SUN50I_ADDA_R_ADCMIX_SRC,
159*4882a593Smuzhiyun 			  SUN50I_ADDA_L_ADCMIX_SRC_LINEINL, 1, 0),
160*4882a593Smuzhiyun 	SOC_DAPM_DOUBLE_R("Mixer Capture Switch",
161*4882a593Smuzhiyun 			  SUN50I_ADDA_L_ADCMIX_SRC,
162*4882a593Smuzhiyun 			  SUN50I_ADDA_R_ADCMIX_SRC,
163*4882a593Smuzhiyun 			  SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL, 1, 0),
164*4882a593Smuzhiyun 	SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch",
165*4882a593Smuzhiyun 			  SUN50I_ADDA_L_ADCMIX_SRC,
166*4882a593Smuzhiyun 			  SUN50I_ADDA_R_ADCMIX_SRC,
167*4882a593Smuzhiyun 			  SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR, 1, 0),
168*4882a593Smuzhiyun };
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(sun50i_codec_out_mixer_pregain_scale,
171*4882a593Smuzhiyun 				  -450, 150, 0);
172*4882a593Smuzhiyun static const DECLARE_TLV_DB_RANGE(sun50i_codec_mic_gain_scale,
173*4882a593Smuzhiyun 	0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
174*4882a593Smuzhiyun 	1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0),
175*4882a593Smuzhiyun );
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(sun50i_codec_hp_vol_scale, -6300, 100, 1);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun static const DECLARE_TLV_DB_RANGE(sun50i_codec_lineout_vol_scale,
180*4882a593Smuzhiyun 	0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
181*4882a593Smuzhiyun 	2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0),
182*4882a593Smuzhiyun );
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun static const DECLARE_TLV_DB_RANGE(sun50i_codec_earpiece_vol_scale,
185*4882a593Smuzhiyun 	0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
186*4882a593Smuzhiyun 	2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0),
187*4882a593Smuzhiyun );
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun /* volume / mute controls */
190*4882a593Smuzhiyun static const struct snd_kcontrol_new sun50i_a64_codec_controls[] = {
191*4882a593Smuzhiyun 	SOC_SINGLE_TLV("Headphone Playback Volume",
192*4882a593Smuzhiyun 		       SUN50I_ADDA_HP_CTRL,
193*4882a593Smuzhiyun 		       SUN50I_ADDA_HP_CTRL_HPVOL, 0x3f, 0,
194*4882a593Smuzhiyun 		       sun50i_codec_hp_vol_scale),
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	/* Mixer pre-gain */
197*4882a593Smuzhiyun 	SOC_SINGLE_TLV("Mic1 Playback Volume", SUN50I_ADDA_MIC1_CTRL,
198*4882a593Smuzhiyun 		       SUN50I_ADDA_MIC1_CTRL_MIC1G,
199*4882a593Smuzhiyun 		       0x7, 0, sun50i_codec_out_mixer_pregain_scale),
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	/* Microphone Amp boost gain */
202*4882a593Smuzhiyun 	SOC_SINGLE_TLV("Mic1 Boost Volume", SUN50I_ADDA_MIC1_CTRL,
203*4882a593Smuzhiyun 		       SUN50I_ADDA_MIC1_CTRL_MIC1BOOST, 0x7, 0,
204*4882a593Smuzhiyun 		       sun50i_codec_mic_gain_scale),
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	/* Mixer pre-gain */
207*4882a593Smuzhiyun 	SOC_SINGLE_TLV("Mic2 Playback Volume",
208*4882a593Smuzhiyun 		       SUN50I_ADDA_MIC2_CTRL, SUN50I_ADDA_MIC2_CTRL_MIC2G,
209*4882a593Smuzhiyun 		       0x7, 0, sun50i_codec_out_mixer_pregain_scale),
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	/* Microphone Amp boost gain */
212*4882a593Smuzhiyun 	SOC_SINGLE_TLV("Mic2 Boost Volume", SUN50I_ADDA_MIC2_CTRL,
213*4882a593Smuzhiyun 		       SUN50I_ADDA_MIC2_CTRL_MIC2BOOST, 0x7, 0,
214*4882a593Smuzhiyun 		       sun50i_codec_mic_gain_scale),
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	/* ADC */
217*4882a593Smuzhiyun 	SOC_SINGLE_TLV("ADC Gain Capture Volume", SUN50I_ADDA_ADC_CTRL,
218*4882a593Smuzhiyun 		       SUN50I_ADDA_ADC_CTRL_ADCG, 0x7, 0,
219*4882a593Smuzhiyun 		       sun50i_codec_out_mixer_pregain_scale),
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	/* Mixer pre-gain */
222*4882a593Smuzhiyun 	SOC_SINGLE_TLV("Line In Playback Volume", SUN50I_ADDA_LINEIN_CTRL,
223*4882a593Smuzhiyun 		       SUN50I_ADDA_LINEIN_CTRL_LINEING,
224*4882a593Smuzhiyun 		       0x7, 0, sun50i_codec_out_mixer_pregain_scale),
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	SOC_SINGLE_TLV("Line Out Playback Volume",
227*4882a593Smuzhiyun 		       SUN50I_ADDA_LINEOUT_CTRL1,
228*4882a593Smuzhiyun 		       SUN50I_ADDA_LINEOUT_CTRL1_VOL, 0x1f, 0,
229*4882a593Smuzhiyun 		       sun50i_codec_lineout_vol_scale),
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	SOC_SINGLE_TLV("Earpiece Playback Volume",
232*4882a593Smuzhiyun 		       SUN50I_ADDA_EARPIECE_CTRL1,
233*4882a593Smuzhiyun 		       SUN50I_ADDA_EARPIECE_CTRL1_ESP_VOL, 0x1f, 0,
234*4882a593Smuzhiyun 		       sun50i_codec_earpiece_vol_scale),
235*4882a593Smuzhiyun };
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun static const char * const sun50i_codec_hp_src_enum_text[] = {
238*4882a593Smuzhiyun 	"DAC", "Mixer",
239*4882a593Smuzhiyun };
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun static SOC_ENUM_DOUBLE_DECL(sun50i_codec_hp_src_enum,
242*4882a593Smuzhiyun 			    SUN50I_ADDA_MIX_DAC_CTRL,
243*4882a593Smuzhiyun 			    SUN50I_ADDA_MIX_DAC_CTRL_LHPIS,
244*4882a593Smuzhiyun 			    SUN50I_ADDA_MIX_DAC_CTRL_RHPIS,
245*4882a593Smuzhiyun 			    sun50i_codec_hp_src_enum_text);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun static const struct snd_kcontrol_new sun50i_codec_hp_src[] = {
248*4882a593Smuzhiyun 	SOC_DAPM_ENUM("Headphone Source Playback Route",
249*4882a593Smuzhiyun 		      sun50i_codec_hp_src_enum),
250*4882a593Smuzhiyun };
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun static const struct snd_kcontrol_new sun50i_codec_hp_switch =
253*4882a593Smuzhiyun 	SOC_DAPM_DOUBLE("Headphone Playback Switch",
254*4882a593Smuzhiyun 			SUN50I_ADDA_MIX_DAC_CTRL,
255*4882a593Smuzhiyun 			SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE,
256*4882a593Smuzhiyun 			SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE, 1, 0);
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun static const char * const sun50i_codec_lineout_src_enum_text[] = {
259*4882a593Smuzhiyun 	"Stereo", "Mono Differential",
260*4882a593Smuzhiyun };
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun static SOC_ENUM_DOUBLE_DECL(sun50i_codec_lineout_src_enum,
263*4882a593Smuzhiyun 			    SUN50I_ADDA_LINEOUT_CTRL0,
264*4882a593Smuzhiyun 			    SUN50I_ADDA_LINEOUT_CTRL0_LSRC_SEL,
265*4882a593Smuzhiyun 			    SUN50I_ADDA_LINEOUT_CTRL0_RSRC_SEL,
266*4882a593Smuzhiyun 			    sun50i_codec_lineout_src_enum_text);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun static const struct snd_kcontrol_new sun50i_codec_lineout_src[] = {
269*4882a593Smuzhiyun 	SOC_DAPM_ENUM("Line Out Source Playback Route",
270*4882a593Smuzhiyun 		      sun50i_codec_lineout_src_enum),
271*4882a593Smuzhiyun };
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun static const struct snd_kcontrol_new sun50i_codec_lineout_switch =
274*4882a593Smuzhiyun 	SOC_DAPM_DOUBLE("Line Out Playback Switch",
275*4882a593Smuzhiyun 			SUN50I_ADDA_LINEOUT_CTRL0,
276*4882a593Smuzhiyun 			SUN50I_ADDA_LINEOUT_CTRL0_LEN,
277*4882a593Smuzhiyun 			SUN50I_ADDA_LINEOUT_CTRL0_REN, 1, 0);
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun static const char * const sun50i_codec_earpiece_src_enum_text[] = {
280*4882a593Smuzhiyun 	"DACR", "DACL", "Right Mixer", "Left Mixer",
281*4882a593Smuzhiyun };
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(sun50i_codec_earpiece_src_enum,
284*4882a593Smuzhiyun 			    SUN50I_ADDA_EARPIECE_CTRL0,
285*4882a593Smuzhiyun 			    SUN50I_ADDA_EARPIECE_CTRL0_ESPSR,
286*4882a593Smuzhiyun 			    sun50i_codec_earpiece_src_enum_text);
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun static const struct snd_kcontrol_new sun50i_codec_earpiece_src[] = {
289*4882a593Smuzhiyun 	SOC_DAPM_ENUM("Earpiece Source Playback Route",
290*4882a593Smuzhiyun 		      sun50i_codec_earpiece_src_enum),
291*4882a593Smuzhiyun };
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun static const struct snd_kcontrol_new sun50i_codec_earpiece_switch[] = {
294*4882a593Smuzhiyun 	SOC_DAPM_SINGLE("Earpiece Playback Switch",
295*4882a593Smuzhiyun 			SUN50I_ADDA_EARPIECE_CTRL1,
296*4882a593Smuzhiyun 			SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_MUTE, 1, 0),
297*4882a593Smuzhiyun };
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = {
300*4882a593Smuzhiyun 	/* DAC */
301*4882a593Smuzhiyun 	SND_SOC_DAPM_DAC("Left DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL,
302*4882a593Smuzhiyun 			 SUN50I_ADDA_MIX_DAC_CTRL_DACALEN, 0),
303*4882a593Smuzhiyun 	SND_SOC_DAPM_DAC("Right DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL,
304*4882a593Smuzhiyun 			 SUN50I_ADDA_MIX_DAC_CTRL_DACAREN, 0),
305*4882a593Smuzhiyun 	/* ADC */
306*4882a593Smuzhiyun 	SND_SOC_DAPM_ADC("Left ADC", NULL, SUN50I_ADDA_ADC_CTRL,
307*4882a593Smuzhiyun 			 SUN50I_ADDA_ADC_CTRL_ADCLEN, 0),
308*4882a593Smuzhiyun 	SND_SOC_DAPM_ADC("Right ADC", NULL, SUN50I_ADDA_ADC_CTRL,
309*4882a593Smuzhiyun 			 SUN50I_ADDA_ADC_CTRL_ADCREN, 0),
310*4882a593Smuzhiyun 	/*
311*4882a593Smuzhiyun 	 * Due to this component and the codec belonging to separate DAPM
312*4882a593Smuzhiyun 	 * contexts, we need to manually link the above widgets to their
313*4882a593Smuzhiyun 	 * stream widgets at the card level.
314*4882a593Smuzhiyun 	 */
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	SND_SOC_DAPM_REGULATOR_SUPPLY("cpvdd", 0, 0),
317*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("Left Headphone Source",
318*4882a593Smuzhiyun 			 SND_SOC_NOPM, 0, 0, sun50i_codec_hp_src),
319*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("Right Headphone Source",
320*4882a593Smuzhiyun 			 SND_SOC_NOPM, 0, 0, sun50i_codec_hp_src),
321*4882a593Smuzhiyun 	SND_SOC_DAPM_SWITCH("Left Headphone Switch",
322*4882a593Smuzhiyun 			    SND_SOC_NOPM, 0, 0, &sun50i_codec_hp_switch),
323*4882a593Smuzhiyun 	SND_SOC_DAPM_SWITCH("Right Headphone Switch",
324*4882a593Smuzhiyun 			    SND_SOC_NOPM, 0, 0, &sun50i_codec_hp_switch),
325*4882a593Smuzhiyun 	SND_SOC_DAPM_OUT_DRV("Left Headphone Amp",
326*4882a593Smuzhiyun 			     SND_SOC_NOPM, 0, 0, NULL, 0),
327*4882a593Smuzhiyun 	SND_SOC_DAPM_OUT_DRV("Right Headphone Amp",
328*4882a593Smuzhiyun 			     SND_SOC_NOPM, 0, 0, NULL, 0),
329*4882a593Smuzhiyun 	SND_SOC_DAPM_SUPPLY("Headphone Amp", SUN50I_ADDA_HP_CTRL,
330*4882a593Smuzhiyun 			     SUN50I_ADDA_HP_CTRL_HPPA_EN, 0, NULL, 0),
331*4882a593Smuzhiyun 	SND_SOC_DAPM_OUTPUT("HP"),
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("Left Line Out Source",
334*4882a593Smuzhiyun 			 SND_SOC_NOPM, 0, 0, sun50i_codec_lineout_src),
335*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("Right Line Out Source",
336*4882a593Smuzhiyun 			 SND_SOC_NOPM, 0, 0, sun50i_codec_lineout_src),
337*4882a593Smuzhiyun 	SND_SOC_DAPM_SWITCH("Left Line Out Switch",
338*4882a593Smuzhiyun 			    SND_SOC_NOPM, 0, 0, &sun50i_codec_lineout_switch),
339*4882a593Smuzhiyun 	SND_SOC_DAPM_SWITCH("Right Line Out Switch",
340*4882a593Smuzhiyun 			    SND_SOC_NOPM, 0, 0, &sun50i_codec_lineout_switch),
341*4882a593Smuzhiyun 	SND_SOC_DAPM_OUTPUT("LINEOUT"),
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("Earpiece Source Playback Route",
344*4882a593Smuzhiyun 			 SND_SOC_NOPM, 0, 0, sun50i_codec_earpiece_src),
345*4882a593Smuzhiyun 	SOC_MIXER_NAMED_CTL_ARRAY("Earpiece Switch",
346*4882a593Smuzhiyun 				  SND_SOC_NOPM, 0, 0,
347*4882a593Smuzhiyun 				  sun50i_codec_earpiece_switch),
348*4882a593Smuzhiyun 	SND_SOC_DAPM_OUT_DRV("Earpiece Amp", SUN50I_ADDA_EARPIECE_CTRL1,
349*4882a593Smuzhiyun 			     SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_EN, 0, NULL, 0),
350*4882a593Smuzhiyun 	SND_SOC_DAPM_OUTPUT("EARPIECE"),
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	/* Microphone inputs */
353*4882a593Smuzhiyun 	SND_SOC_DAPM_INPUT("MIC1"),
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	/* Microphone Bias */
356*4882a593Smuzhiyun 	SND_SOC_DAPM_SUPPLY("MBIAS", SUN50I_ADDA_HS_MBIAS_CTRL,
357*4882a593Smuzhiyun 			    SUN50I_ADDA_HS_MBIAS_CTRL_MMICBIASEN,
358*4882a593Smuzhiyun 			    0, NULL, 0),
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	/* Mic input path */
361*4882a593Smuzhiyun 	SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN50I_ADDA_MIC1_CTRL,
362*4882a593Smuzhiyun 			 SUN50I_ADDA_MIC1_CTRL_MIC1AMPEN, 0, NULL, 0),
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	/* Microphone input */
365*4882a593Smuzhiyun 	SND_SOC_DAPM_INPUT("MIC2"),
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	/* Microphone Bias */
368*4882a593Smuzhiyun 	SND_SOC_DAPM_SUPPLY("HBIAS", SUN50I_ADDA_JACK_MIC_CTRL,
369*4882a593Smuzhiyun 			    SUN50I_ADDA_JACK_MIC_CTRL_HMICBIASEN,
370*4882a593Smuzhiyun 			    0, NULL, 0),
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	/* Mic input path */
373*4882a593Smuzhiyun 	SND_SOC_DAPM_PGA("Mic2 Amplifier", SUN50I_ADDA_MIC2_CTRL,
374*4882a593Smuzhiyun 			 SUN50I_ADDA_MIC2_CTRL_MIC2AMPEN, 0, NULL, 0),
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	/* Line input */
377*4882a593Smuzhiyun 	SND_SOC_DAPM_INPUT("LINEIN"),
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 	/* Mixers */
380*4882a593Smuzhiyun 	SND_SOC_DAPM_MIXER("Left Mixer", SUN50I_ADDA_MIX_DAC_CTRL,
381*4882a593Smuzhiyun 			   SUN50I_ADDA_MIX_DAC_CTRL_LMIXEN, 0,
382*4882a593Smuzhiyun 			   sun50i_a64_codec_mixer_controls,
383*4882a593Smuzhiyun 			   ARRAY_SIZE(sun50i_a64_codec_mixer_controls)),
384*4882a593Smuzhiyun 	SND_SOC_DAPM_MIXER("Right Mixer", SUN50I_ADDA_MIX_DAC_CTRL,
385*4882a593Smuzhiyun 			   SUN50I_ADDA_MIX_DAC_CTRL_RMIXEN, 0,
386*4882a593Smuzhiyun 			   sun50i_a64_codec_mixer_controls,
387*4882a593Smuzhiyun 			   ARRAY_SIZE(sun50i_a64_codec_mixer_controls)),
388*4882a593Smuzhiyun 	SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
389*4882a593Smuzhiyun 			   sun50i_codec_adc_mixer_controls,
390*4882a593Smuzhiyun 			   ARRAY_SIZE(sun50i_codec_adc_mixer_controls)),
391*4882a593Smuzhiyun 	SND_SOC_DAPM_MIXER("Right ADC Mixer", SND_SOC_NOPM, 0, 0,
392*4882a593Smuzhiyun 			   sun50i_codec_adc_mixer_controls,
393*4882a593Smuzhiyun 			   ARRAY_SIZE(sun50i_codec_adc_mixer_controls)),
394*4882a593Smuzhiyun };
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun static const struct snd_soc_dapm_route sun50i_a64_codec_routes[] = {
397*4882a593Smuzhiyun 	/* Left Mixer Routes */
398*4882a593Smuzhiyun 	{ "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
399*4882a593Smuzhiyun 	{ "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
400*4882a593Smuzhiyun 	{ "Left Mixer", "Line In Playback Switch", "LINEIN" },
401*4882a593Smuzhiyun 	{ "Left Mixer", "DAC Playback Switch", "Left DAC" },
402*4882a593Smuzhiyun 	{ "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" },
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	/* Right Mixer Routes */
405*4882a593Smuzhiyun 	{ "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
406*4882a593Smuzhiyun 	{ "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
407*4882a593Smuzhiyun 	{ "Right Mixer", "Line In Playback Switch", "LINEIN" },
408*4882a593Smuzhiyun 	{ "Right Mixer", "DAC Playback Switch", "Right DAC" },
409*4882a593Smuzhiyun 	{ "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" },
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	/* Left ADC Mixer Routes */
412*4882a593Smuzhiyun 	{ "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
413*4882a593Smuzhiyun 	{ "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
414*4882a593Smuzhiyun 	{ "Left ADC Mixer", "Line In Capture Switch", "LINEIN" },
415*4882a593Smuzhiyun 	{ "Left ADC Mixer", "Mixer Capture Switch", "Left Mixer" },
416*4882a593Smuzhiyun 	{ "Left ADC Mixer", "Mixer Reversed Capture Switch", "Right Mixer" },
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	/* Right ADC Mixer Routes */
419*4882a593Smuzhiyun 	{ "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
420*4882a593Smuzhiyun 	{ "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
421*4882a593Smuzhiyun 	{ "Right ADC Mixer", "Line In Capture Switch", "LINEIN" },
422*4882a593Smuzhiyun 	{ "Right ADC Mixer", "Mixer Capture Switch", "Right Mixer" },
423*4882a593Smuzhiyun 	{ "Right ADC Mixer", "Mixer Reversed Capture Switch", "Left Mixer" },
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	/* ADC Routes */
426*4882a593Smuzhiyun 	{ "Left ADC", NULL, "Left ADC Mixer" },
427*4882a593Smuzhiyun 	{ "Right ADC", NULL, "Right ADC Mixer" },
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	/* Headphone Routes */
430*4882a593Smuzhiyun 	{ "Left Headphone Source", "DAC", "Left DAC" },
431*4882a593Smuzhiyun 	{ "Left Headphone Source", "Mixer", "Left Mixer" },
432*4882a593Smuzhiyun 	{ "Left Headphone Switch", "Headphone Playback Switch", "Left Headphone Source" },
433*4882a593Smuzhiyun 	{ "Left Headphone Amp", NULL, "Left Headphone Switch" },
434*4882a593Smuzhiyun 	{ "Left Headphone Amp", NULL, "Headphone Amp" },
435*4882a593Smuzhiyun 	{ "HP", NULL, "Left Headphone Amp" },
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	{ "Right Headphone Source", "DAC", "Right DAC" },
438*4882a593Smuzhiyun 	{ "Right Headphone Source", "Mixer", "Right Mixer" },
439*4882a593Smuzhiyun 	{ "Right Headphone Switch", "Headphone Playback Switch", "Right Headphone Source" },
440*4882a593Smuzhiyun 	{ "Right Headphone Amp", NULL, "Right Headphone Switch" },
441*4882a593Smuzhiyun 	{ "Right Headphone Amp", NULL, "Headphone Amp" },
442*4882a593Smuzhiyun 	{ "HP", NULL, "Right Headphone Amp" },
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	{ "Headphone Amp", NULL, "cpvdd" },
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	/* Microphone Routes */
447*4882a593Smuzhiyun 	{ "Mic1 Amplifier", NULL, "MIC1"},
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	/* Microphone Routes */
450*4882a593Smuzhiyun 	{ "Mic2 Amplifier", NULL, "MIC2"},
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	/* Line-out Routes */
453*4882a593Smuzhiyun 	{ "Left Line Out Source", "Stereo", "Left Mixer" },
454*4882a593Smuzhiyun 	{ "Left Line Out Source", "Mono Differential", "Left Mixer" },
455*4882a593Smuzhiyun 	{ "Left Line Out Source", "Mono Differential", "Right Mixer" },
456*4882a593Smuzhiyun 	{ "Left Line Out Switch", "Line Out Playback Switch", "Left Line Out Source" },
457*4882a593Smuzhiyun 	{ "LINEOUT", NULL, "Left Line Out Switch" },
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	{ "Right Line Out Switch", "Line Out Playback Switch", "Right Mixer" },
460*4882a593Smuzhiyun 	{ "Right Line Out Source", "Stereo", "Right Line Out Switch" },
461*4882a593Smuzhiyun 	{ "Right Line Out Source", "Mono Differential", "Left Line Out Switch" },
462*4882a593Smuzhiyun 	{ "LINEOUT", NULL, "Right Line Out Source" },
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	/* Earpiece Routes */
465*4882a593Smuzhiyun 	{ "Earpiece Source Playback Route", "DACL", "Left DAC" },
466*4882a593Smuzhiyun 	{ "Earpiece Source Playback Route", "DACR", "Right DAC" },
467*4882a593Smuzhiyun 	{ "Earpiece Source Playback Route", "Left Mixer", "Left Mixer" },
468*4882a593Smuzhiyun 	{ "Earpiece Source Playback Route", "Right Mixer", "Right Mixer" },
469*4882a593Smuzhiyun 	{ "Earpiece Switch", "Earpiece Playback Switch", "Earpiece Source Playback Route" },
470*4882a593Smuzhiyun 	{ "Earpiece Amp", NULL, "Earpiece Switch" },
471*4882a593Smuzhiyun 	{ "EARPIECE", NULL, "Earpiece Amp" },
472*4882a593Smuzhiyun };
473*4882a593Smuzhiyun 
sun50i_a64_codec_suspend(struct snd_soc_component * component)474*4882a593Smuzhiyun static int sun50i_a64_codec_suspend(struct snd_soc_component *component)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun 	return regmap_update_bits(component->regmap, SUN50I_ADDA_HP_CTRL,
477*4882a593Smuzhiyun 				  BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE),
478*4882a593Smuzhiyun 				  BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE));
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun 
sun50i_a64_codec_resume(struct snd_soc_component * component)481*4882a593Smuzhiyun static int sun50i_a64_codec_resume(struct snd_soc_component *component)
482*4882a593Smuzhiyun {
483*4882a593Smuzhiyun 	return regmap_update_bits(component->regmap, SUN50I_ADDA_HP_CTRL,
484*4882a593Smuzhiyun 				  BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE), 0);
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun static const struct snd_soc_component_driver sun50i_codec_analog_cmpnt_drv = {
488*4882a593Smuzhiyun 	.controls		= sun50i_a64_codec_controls,
489*4882a593Smuzhiyun 	.num_controls		= ARRAY_SIZE(sun50i_a64_codec_controls),
490*4882a593Smuzhiyun 	.dapm_widgets		= sun50i_a64_codec_widgets,
491*4882a593Smuzhiyun 	.num_dapm_widgets	= ARRAY_SIZE(sun50i_a64_codec_widgets),
492*4882a593Smuzhiyun 	.dapm_routes		= sun50i_a64_codec_routes,
493*4882a593Smuzhiyun 	.num_dapm_routes	= ARRAY_SIZE(sun50i_a64_codec_routes),
494*4882a593Smuzhiyun 	.suspend		= sun50i_a64_codec_suspend,
495*4882a593Smuzhiyun 	.resume			= sun50i_a64_codec_resume,
496*4882a593Smuzhiyun };
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun static const struct of_device_id sun50i_codec_analog_of_match[] = {
499*4882a593Smuzhiyun 	{
500*4882a593Smuzhiyun 		.compatible = "allwinner,sun50i-a64-codec-analog",
501*4882a593Smuzhiyun 	},
502*4882a593Smuzhiyun 	{}
503*4882a593Smuzhiyun };
504*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, sun50i_codec_analog_of_match);
505*4882a593Smuzhiyun 
sun50i_codec_analog_probe(struct platform_device * pdev)506*4882a593Smuzhiyun static int sun50i_codec_analog_probe(struct platform_device *pdev)
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun 	struct regmap *regmap;
509*4882a593Smuzhiyun 	void __iomem *base;
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	base = devm_platform_ioremap_resource(pdev, 0);
512*4882a593Smuzhiyun 	if (IS_ERR(base)) {
513*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Failed to map the registers\n");
514*4882a593Smuzhiyun 		return PTR_ERR(base);
515*4882a593Smuzhiyun 	}
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	regmap = sun8i_adda_pr_regmap_init(&pdev->dev, base);
518*4882a593Smuzhiyun 	if (IS_ERR(regmap)) {
519*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Failed to create regmap\n");
520*4882a593Smuzhiyun 		return PTR_ERR(regmap);
521*4882a593Smuzhiyun 	}
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	return devm_snd_soc_register_component(&pdev->dev,
524*4882a593Smuzhiyun 					       &sun50i_codec_analog_cmpnt_drv,
525*4882a593Smuzhiyun 					       NULL, 0);
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun static struct platform_driver sun50i_codec_analog_driver = {
529*4882a593Smuzhiyun 	.driver = {
530*4882a593Smuzhiyun 		.name = "sun50i-codec-analog",
531*4882a593Smuzhiyun 		.of_match_table = sun50i_codec_analog_of_match,
532*4882a593Smuzhiyun 	},
533*4882a593Smuzhiyun 	.probe = sun50i_codec_analog_probe,
534*4882a593Smuzhiyun };
535*4882a593Smuzhiyun module_platform_driver(sun50i_codec_analog_driver);
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun MODULE_DESCRIPTION("Allwinner internal codec analog controls driver for A64");
538*4882a593Smuzhiyun MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>");
539*4882a593Smuzhiyun MODULE_LICENSE("GPL");
540*4882a593Smuzhiyun MODULE_ALIAS("platform:sun50i-codec-analog");
541