0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/io.h>
0015 #include <linux/kernel.h>
0016 #include <linux/module.h>
0017 #include <linux/of.h>
0018 #include <linux/of_device.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/regmap.h>
0021
0022 #include <sound/soc.h>
0023 #include <sound/soc-dapm.h>
0024 #include <sound/tlv.h>
0025
0026 #include "sun8i-adda-pr-regmap.h"
0027
0028
0029 #define SUN50I_ADDA_HP_CTRL 0x00
0030 #define SUN50I_ADDA_HP_CTRL_PA_CLK_GATE 7
0031 #define SUN50I_ADDA_HP_CTRL_HPPA_EN 6
0032 #define SUN50I_ADDA_HP_CTRL_HPVOL 0
0033
0034 #define SUN50I_ADDA_OL_MIX_CTRL 0x01
0035 #define SUN50I_ADDA_OL_MIX_CTRL_MIC1 6
0036 #define SUN50I_ADDA_OL_MIX_CTRL_MIC2 5
0037 #define SUN50I_ADDA_OL_MIX_CTRL_PHONE 4
0038 #define SUN50I_ADDA_OL_MIX_CTRL_PHONEN 3
0039 #define SUN50I_ADDA_OL_MIX_CTRL_LINEINL 2
0040 #define SUN50I_ADDA_OL_MIX_CTRL_DACL 1
0041 #define SUN50I_ADDA_OL_MIX_CTRL_DACR 0
0042
0043 #define SUN50I_ADDA_OR_MIX_CTRL 0x02
0044 #define SUN50I_ADDA_OR_MIX_CTRL_MIC1 6
0045 #define SUN50I_ADDA_OR_MIX_CTRL_MIC2 5
0046 #define SUN50I_ADDA_OR_MIX_CTRL_PHONE 4
0047 #define SUN50I_ADDA_OR_MIX_CTRL_PHONEP 3
0048 #define SUN50I_ADDA_OR_MIX_CTRL_LINEINR 2
0049 #define SUN50I_ADDA_OR_MIX_CTRL_DACR 1
0050 #define SUN50I_ADDA_OR_MIX_CTRL_DACL 0
0051
0052 #define SUN50I_ADDA_EARPIECE_CTRL0 0x03
0053 #define SUN50I_ADDA_EARPIECE_CTRL0_EAR_RAMP_TIME 4
0054 #define SUN50I_ADDA_EARPIECE_CTRL0_ESPSR 0
0055
0056 #define SUN50I_ADDA_EARPIECE_CTRL1 0x04
0057 #define SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_EN 7
0058 #define SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_MUTE 6
0059 #define SUN50I_ADDA_EARPIECE_CTRL1_ESP_VOL 0
0060
0061 #define SUN50I_ADDA_LINEOUT_CTRL0 0x05
0062 #define SUN50I_ADDA_LINEOUT_CTRL0_LEN 7
0063 #define SUN50I_ADDA_LINEOUT_CTRL0_REN 6
0064 #define SUN50I_ADDA_LINEOUT_CTRL0_LSRC_SEL 5
0065 #define SUN50I_ADDA_LINEOUT_CTRL0_RSRC_SEL 4
0066
0067 #define SUN50I_ADDA_LINEOUT_CTRL1 0x06
0068 #define SUN50I_ADDA_LINEOUT_CTRL1_VOL 0
0069
0070 #define SUN50I_ADDA_MIC1_CTRL 0x07
0071 #define SUN50I_ADDA_MIC1_CTRL_MIC1G 4
0072 #define SUN50I_ADDA_MIC1_CTRL_MIC1AMPEN 3
0073 #define SUN50I_ADDA_MIC1_CTRL_MIC1BOOST 0
0074
0075 #define SUN50I_ADDA_MIC2_CTRL 0x08
0076 #define SUN50I_ADDA_MIC2_CTRL_MIC2G 4
0077 #define SUN50I_ADDA_MIC2_CTRL_MIC2AMPEN 3
0078 #define SUN50I_ADDA_MIC2_CTRL_MIC2BOOST 0
0079
0080 #define SUN50I_ADDA_LINEIN_CTRL 0x09
0081 #define SUN50I_ADDA_LINEIN_CTRL_LINEING 0
0082
0083 #define SUN50I_ADDA_MIX_DAC_CTRL 0x0a
0084 #define SUN50I_ADDA_MIX_DAC_CTRL_DACAREN 7
0085 #define SUN50I_ADDA_MIX_DAC_CTRL_DACALEN 6
0086 #define SUN50I_ADDA_MIX_DAC_CTRL_RMIXEN 5
0087 #define SUN50I_ADDA_MIX_DAC_CTRL_LMIXEN 4
0088 #define SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE 3
0089 #define SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE 2
0090 #define SUN50I_ADDA_MIX_DAC_CTRL_RHPIS 1
0091 #define SUN50I_ADDA_MIX_DAC_CTRL_LHPIS 0
0092
0093 #define SUN50I_ADDA_L_ADCMIX_SRC 0x0b
0094 #define SUN50I_ADDA_L_ADCMIX_SRC_MIC1 6
0095 #define SUN50I_ADDA_L_ADCMIX_SRC_MIC2 5
0096 #define SUN50I_ADDA_L_ADCMIX_SRC_PHONE 4
0097 #define SUN50I_ADDA_L_ADCMIX_SRC_PHONEN 3
0098 #define SUN50I_ADDA_L_ADCMIX_SRC_LINEINL 2
0099 #define SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL 1
0100 #define SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR 0
0101
0102 #define SUN50I_ADDA_R_ADCMIX_SRC 0x0c
0103 #define SUN50I_ADDA_R_ADCMIX_SRC_MIC1 6
0104 #define SUN50I_ADDA_R_ADCMIX_SRC_MIC2 5
0105 #define SUN50I_ADDA_R_ADCMIX_SRC_PHONE 4
0106 #define SUN50I_ADDA_R_ADCMIX_SRC_PHONEP 3
0107 #define SUN50I_ADDA_R_ADCMIX_SRC_LINEINR 2
0108 #define SUN50I_ADDA_R_ADCMIX_SRC_OMIXR 1
0109 #define SUN50I_ADDA_R_ADCMIX_SRC_OMIXL 0
0110
0111 #define SUN50I_ADDA_ADC_CTRL 0x0d
0112 #define SUN50I_ADDA_ADC_CTRL_ADCREN 7
0113 #define SUN50I_ADDA_ADC_CTRL_ADCLEN 6
0114 #define SUN50I_ADDA_ADC_CTRL_ADCG 0
0115
0116 #define SUN50I_ADDA_HS_MBIAS_CTRL 0x0e
0117 #define SUN50I_ADDA_HS_MBIAS_CTRL_MMICBIASEN 7
0118
0119 #define SUN50I_ADDA_JACK_MIC_CTRL 0x1d
0120 #define SUN50I_ADDA_JACK_MIC_CTRL_INNERRESEN 6
0121 #define SUN50I_ADDA_JACK_MIC_CTRL_HMICBIASEN 5
0122
0123
0124 static const struct snd_kcontrol_new sun50i_a64_codec_mixer_controls[] = {
0125 SOC_DAPM_DOUBLE_R("Mic1 Playback Switch",
0126 SUN50I_ADDA_OL_MIX_CTRL,
0127 SUN50I_ADDA_OR_MIX_CTRL,
0128 SUN50I_ADDA_OL_MIX_CTRL_MIC1, 1, 0),
0129 SOC_DAPM_DOUBLE_R("Mic2 Playback Switch",
0130 SUN50I_ADDA_OL_MIX_CTRL,
0131 SUN50I_ADDA_OR_MIX_CTRL,
0132 SUN50I_ADDA_OL_MIX_CTRL_MIC2, 1, 0),
0133 SOC_DAPM_DOUBLE_R("Line In Playback Switch",
0134 SUN50I_ADDA_OL_MIX_CTRL,
0135 SUN50I_ADDA_OR_MIX_CTRL,
0136 SUN50I_ADDA_OL_MIX_CTRL_LINEINL, 1, 0),
0137 SOC_DAPM_DOUBLE_R("DAC Playback Switch",
0138 SUN50I_ADDA_OL_MIX_CTRL,
0139 SUN50I_ADDA_OR_MIX_CTRL,
0140 SUN50I_ADDA_OL_MIX_CTRL_DACL, 1, 0),
0141 SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch",
0142 SUN50I_ADDA_OL_MIX_CTRL,
0143 SUN50I_ADDA_OR_MIX_CTRL,
0144 SUN50I_ADDA_OL_MIX_CTRL_DACR, 1, 0),
0145 };
0146
0147
0148 static const struct snd_kcontrol_new sun50i_codec_adc_mixer_controls[] = {
0149 SOC_DAPM_DOUBLE_R("Mic1 Capture Switch",
0150 SUN50I_ADDA_L_ADCMIX_SRC,
0151 SUN50I_ADDA_R_ADCMIX_SRC,
0152 SUN50I_ADDA_L_ADCMIX_SRC_MIC1, 1, 0),
0153 SOC_DAPM_DOUBLE_R("Mic2 Capture Switch",
0154 SUN50I_ADDA_L_ADCMIX_SRC,
0155 SUN50I_ADDA_R_ADCMIX_SRC,
0156 SUN50I_ADDA_L_ADCMIX_SRC_MIC2, 1, 0),
0157 SOC_DAPM_DOUBLE_R("Line In Capture Switch",
0158 SUN50I_ADDA_L_ADCMIX_SRC,
0159 SUN50I_ADDA_R_ADCMIX_SRC,
0160 SUN50I_ADDA_L_ADCMIX_SRC_LINEINL, 1, 0),
0161 SOC_DAPM_DOUBLE_R("Mixer Capture Switch",
0162 SUN50I_ADDA_L_ADCMIX_SRC,
0163 SUN50I_ADDA_R_ADCMIX_SRC,
0164 SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL, 1, 0),
0165 SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch",
0166 SUN50I_ADDA_L_ADCMIX_SRC,
0167 SUN50I_ADDA_R_ADCMIX_SRC,
0168 SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR, 1, 0),
0169 };
0170
0171 static const DECLARE_TLV_DB_SCALE(sun50i_codec_out_mixer_pregain_scale,
0172 -450, 150, 0);
0173 static const DECLARE_TLV_DB_RANGE(sun50i_codec_mic_gain_scale,
0174 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
0175 1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0),
0176 );
0177
0178 static const DECLARE_TLV_DB_SCALE(sun50i_codec_hp_vol_scale, -6300, 100, 1);
0179
0180 static const DECLARE_TLV_DB_RANGE(sun50i_codec_lineout_vol_scale,
0181 0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
0182 2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0),
0183 );
0184
0185 static const DECLARE_TLV_DB_RANGE(sun50i_codec_earpiece_vol_scale,
0186 0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
0187 2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0),
0188 );
0189
0190
0191 static const struct snd_kcontrol_new sun50i_a64_codec_controls[] = {
0192 SOC_SINGLE_TLV("Headphone Playback Volume",
0193 SUN50I_ADDA_HP_CTRL,
0194 SUN50I_ADDA_HP_CTRL_HPVOL, 0x3f, 0,
0195 sun50i_codec_hp_vol_scale),
0196
0197
0198 SOC_SINGLE_TLV("Mic1 Playback Volume", SUN50I_ADDA_MIC1_CTRL,
0199 SUN50I_ADDA_MIC1_CTRL_MIC1G,
0200 0x7, 0, sun50i_codec_out_mixer_pregain_scale),
0201
0202
0203 SOC_SINGLE_TLV("Mic1 Boost Volume", SUN50I_ADDA_MIC1_CTRL,
0204 SUN50I_ADDA_MIC1_CTRL_MIC1BOOST, 0x7, 0,
0205 sun50i_codec_mic_gain_scale),
0206
0207
0208 SOC_SINGLE_TLV("Mic2 Playback Volume",
0209 SUN50I_ADDA_MIC2_CTRL, SUN50I_ADDA_MIC2_CTRL_MIC2G,
0210 0x7, 0, sun50i_codec_out_mixer_pregain_scale),
0211
0212
0213 SOC_SINGLE_TLV("Mic2 Boost Volume", SUN50I_ADDA_MIC2_CTRL,
0214 SUN50I_ADDA_MIC2_CTRL_MIC2BOOST, 0x7, 0,
0215 sun50i_codec_mic_gain_scale),
0216
0217
0218 SOC_SINGLE_TLV("ADC Gain Capture Volume", SUN50I_ADDA_ADC_CTRL,
0219 SUN50I_ADDA_ADC_CTRL_ADCG, 0x7, 0,
0220 sun50i_codec_out_mixer_pregain_scale),
0221
0222
0223 SOC_SINGLE_TLV("Line In Playback Volume", SUN50I_ADDA_LINEIN_CTRL,
0224 SUN50I_ADDA_LINEIN_CTRL_LINEING,
0225 0x7, 0, sun50i_codec_out_mixer_pregain_scale),
0226
0227 SOC_SINGLE_TLV("Line Out Playback Volume",
0228 SUN50I_ADDA_LINEOUT_CTRL1,
0229 SUN50I_ADDA_LINEOUT_CTRL1_VOL, 0x1f, 0,
0230 sun50i_codec_lineout_vol_scale),
0231
0232 SOC_SINGLE_TLV("Earpiece Playback Volume",
0233 SUN50I_ADDA_EARPIECE_CTRL1,
0234 SUN50I_ADDA_EARPIECE_CTRL1_ESP_VOL, 0x1f, 0,
0235 sun50i_codec_earpiece_vol_scale),
0236 };
0237
0238 static const char * const sun50i_codec_hp_src_enum_text[] = {
0239 "DAC", "Mixer",
0240 };
0241
0242 static SOC_ENUM_DOUBLE_DECL(sun50i_codec_hp_src_enum,
0243 SUN50I_ADDA_MIX_DAC_CTRL,
0244 SUN50I_ADDA_MIX_DAC_CTRL_LHPIS,
0245 SUN50I_ADDA_MIX_DAC_CTRL_RHPIS,
0246 sun50i_codec_hp_src_enum_text);
0247
0248 static const struct snd_kcontrol_new sun50i_codec_hp_src[] = {
0249 SOC_DAPM_ENUM("Headphone Source Playback Route",
0250 sun50i_codec_hp_src_enum),
0251 };
0252
0253 static const struct snd_kcontrol_new sun50i_codec_hp_switch =
0254 SOC_DAPM_DOUBLE("Headphone Playback Switch",
0255 SUN50I_ADDA_MIX_DAC_CTRL,
0256 SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE,
0257 SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE, 1, 0);
0258
0259 static const char * const sun50i_codec_lineout_src_enum_text[] = {
0260 "Stereo", "Mono Differential",
0261 };
0262
0263 static SOC_ENUM_DOUBLE_DECL(sun50i_codec_lineout_src_enum,
0264 SUN50I_ADDA_LINEOUT_CTRL0,
0265 SUN50I_ADDA_LINEOUT_CTRL0_LSRC_SEL,
0266 SUN50I_ADDA_LINEOUT_CTRL0_RSRC_SEL,
0267 sun50i_codec_lineout_src_enum_text);
0268
0269 static const struct snd_kcontrol_new sun50i_codec_lineout_src[] = {
0270 SOC_DAPM_ENUM("Line Out Source Playback Route",
0271 sun50i_codec_lineout_src_enum),
0272 };
0273
0274 static const struct snd_kcontrol_new sun50i_codec_lineout_switch =
0275 SOC_DAPM_DOUBLE("Line Out Playback Switch",
0276 SUN50I_ADDA_LINEOUT_CTRL0,
0277 SUN50I_ADDA_LINEOUT_CTRL0_LEN,
0278 SUN50I_ADDA_LINEOUT_CTRL0_REN, 1, 0);
0279
0280 static const char * const sun50i_codec_earpiece_src_enum_text[] = {
0281 "DACR", "DACL", "Right Mixer", "Left Mixer",
0282 };
0283
0284 static SOC_ENUM_SINGLE_DECL(sun50i_codec_earpiece_src_enum,
0285 SUN50I_ADDA_EARPIECE_CTRL0,
0286 SUN50I_ADDA_EARPIECE_CTRL0_ESPSR,
0287 sun50i_codec_earpiece_src_enum_text);
0288
0289 static const struct snd_kcontrol_new sun50i_codec_earpiece_src[] = {
0290 SOC_DAPM_ENUM("Earpiece Source Playback Route",
0291 sun50i_codec_earpiece_src_enum),
0292 };
0293
0294 static const struct snd_kcontrol_new sun50i_codec_earpiece_switch[] = {
0295 SOC_DAPM_SINGLE("Earpiece Playback Switch",
0296 SUN50I_ADDA_EARPIECE_CTRL1,
0297 SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_MUTE, 1, 0),
0298 };
0299
0300 static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = {
0301
0302 SND_SOC_DAPM_DAC("Left DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL,
0303 SUN50I_ADDA_MIX_DAC_CTRL_DACALEN, 0),
0304 SND_SOC_DAPM_DAC("Right DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL,
0305 SUN50I_ADDA_MIX_DAC_CTRL_DACAREN, 0),
0306
0307 SND_SOC_DAPM_ADC("Left ADC", NULL, SUN50I_ADDA_ADC_CTRL,
0308 SUN50I_ADDA_ADC_CTRL_ADCLEN, 0),
0309 SND_SOC_DAPM_ADC("Right ADC", NULL, SUN50I_ADDA_ADC_CTRL,
0310 SUN50I_ADDA_ADC_CTRL_ADCREN, 0),
0311
0312
0313
0314
0315
0316
0317 SND_SOC_DAPM_REGULATOR_SUPPLY("cpvdd", 0, 0),
0318 SND_SOC_DAPM_MUX("Left Headphone Source",
0319 SND_SOC_NOPM, 0, 0, sun50i_codec_hp_src),
0320 SND_SOC_DAPM_MUX("Right Headphone Source",
0321 SND_SOC_NOPM, 0, 0, sun50i_codec_hp_src),
0322 SND_SOC_DAPM_SWITCH("Left Headphone Switch",
0323 SND_SOC_NOPM, 0, 0, &sun50i_codec_hp_switch),
0324 SND_SOC_DAPM_SWITCH("Right Headphone Switch",
0325 SND_SOC_NOPM, 0, 0, &sun50i_codec_hp_switch),
0326 SND_SOC_DAPM_OUT_DRV("Left Headphone Amp",
0327 SND_SOC_NOPM, 0, 0, NULL, 0),
0328 SND_SOC_DAPM_OUT_DRV("Right Headphone Amp",
0329 SND_SOC_NOPM, 0, 0, NULL, 0),
0330 SND_SOC_DAPM_SUPPLY("Headphone Amp", SUN50I_ADDA_HP_CTRL,
0331 SUN50I_ADDA_HP_CTRL_HPPA_EN, 0, NULL, 0),
0332 SND_SOC_DAPM_OUTPUT("HP"),
0333
0334 SND_SOC_DAPM_MUX("Left Line Out Source",
0335 SND_SOC_NOPM, 0, 0, sun50i_codec_lineout_src),
0336 SND_SOC_DAPM_MUX("Right Line Out Source",
0337 SND_SOC_NOPM, 0, 0, sun50i_codec_lineout_src),
0338 SND_SOC_DAPM_SWITCH("Left Line Out Switch",
0339 SND_SOC_NOPM, 0, 0, &sun50i_codec_lineout_switch),
0340 SND_SOC_DAPM_SWITCH("Right Line Out Switch",
0341 SND_SOC_NOPM, 0, 0, &sun50i_codec_lineout_switch),
0342 SND_SOC_DAPM_OUTPUT("LINEOUT"),
0343
0344 SND_SOC_DAPM_MUX("Earpiece Source Playback Route",
0345 SND_SOC_NOPM, 0, 0, sun50i_codec_earpiece_src),
0346 SOC_MIXER_NAMED_CTL_ARRAY("Earpiece Switch",
0347 SND_SOC_NOPM, 0, 0,
0348 sun50i_codec_earpiece_switch),
0349 SND_SOC_DAPM_OUT_DRV("Earpiece Amp", SUN50I_ADDA_EARPIECE_CTRL1,
0350 SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_EN, 0, NULL, 0),
0351 SND_SOC_DAPM_OUTPUT("EARPIECE"),
0352
0353
0354 SND_SOC_DAPM_INPUT("MIC1"),
0355
0356
0357 SND_SOC_DAPM_SUPPLY("MBIAS", SUN50I_ADDA_HS_MBIAS_CTRL,
0358 SUN50I_ADDA_HS_MBIAS_CTRL_MMICBIASEN,
0359 0, NULL, 0),
0360
0361
0362 SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN50I_ADDA_MIC1_CTRL,
0363 SUN50I_ADDA_MIC1_CTRL_MIC1AMPEN, 0, NULL, 0),
0364
0365
0366 SND_SOC_DAPM_INPUT("MIC2"),
0367
0368
0369 SND_SOC_DAPM_SUPPLY("HBIAS", SUN50I_ADDA_JACK_MIC_CTRL,
0370 SUN50I_ADDA_JACK_MIC_CTRL_HMICBIASEN,
0371 0, NULL, 0),
0372
0373
0374 SND_SOC_DAPM_PGA("Mic2 Amplifier", SUN50I_ADDA_MIC2_CTRL,
0375 SUN50I_ADDA_MIC2_CTRL_MIC2AMPEN, 0, NULL, 0),
0376
0377
0378 SND_SOC_DAPM_INPUT("LINEIN"),
0379
0380
0381 SND_SOC_DAPM_MIXER("Left Mixer", SUN50I_ADDA_MIX_DAC_CTRL,
0382 SUN50I_ADDA_MIX_DAC_CTRL_LMIXEN, 0,
0383 sun50i_a64_codec_mixer_controls,
0384 ARRAY_SIZE(sun50i_a64_codec_mixer_controls)),
0385 SND_SOC_DAPM_MIXER("Right Mixer", SUN50I_ADDA_MIX_DAC_CTRL,
0386 SUN50I_ADDA_MIX_DAC_CTRL_RMIXEN, 0,
0387 sun50i_a64_codec_mixer_controls,
0388 ARRAY_SIZE(sun50i_a64_codec_mixer_controls)),
0389 SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
0390 sun50i_codec_adc_mixer_controls,
0391 ARRAY_SIZE(sun50i_codec_adc_mixer_controls)),
0392 SND_SOC_DAPM_MIXER("Right ADC Mixer", SND_SOC_NOPM, 0, 0,
0393 sun50i_codec_adc_mixer_controls,
0394 ARRAY_SIZE(sun50i_codec_adc_mixer_controls)),
0395 };
0396
0397 static const struct snd_soc_dapm_route sun50i_a64_codec_routes[] = {
0398
0399 { "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
0400 { "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
0401 { "Left Mixer", "Line In Playback Switch", "LINEIN" },
0402 { "Left Mixer", "DAC Playback Switch", "Left DAC" },
0403 { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" },
0404
0405
0406 { "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
0407 { "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
0408 { "Right Mixer", "Line In Playback Switch", "LINEIN" },
0409 { "Right Mixer", "DAC Playback Switch", "Right DAC" },
0410 { "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" },
0411
0412
0413 { "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
0414 { "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
0415 { "Left ADC Mixer", "Line In Capture Switch", "LINEIN" },
0416 { "Left ADC Mixer", "Mixer Capture Switch", "Left Mixer" },
0417 { "Left ADC Mixer", "Mixer Reversed Capture Switch", "Right Mixer" },
0418
0419
0420 { "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
0421 { "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
0422 { "Right ADC Mixer", "Line In Capture Switch", "LINEIN" },
0423 { "Right ADC Mixer", "Mixer Capture Switch", "Right Mixer" },
0424 { "Right ADC Mixer", "Mixer Reversed Capture Switch", "Left Mixer" },
0425
0426
0427 { "Left ADC", NULL, "Left ADC Mixer" },
0428 { "Right ADC", NULL, "Right ADC Mixer" },
0429
0430
0431 { "Left Headphone Source", "DAC", "Left DAC" },
0432 { "Left Headphone Source", "Mixer", "Left Mixer" },
0433 { "Left Headphone Switch", "Headphone Playback Switch", "Left Headphone Source" },
0434 { "Left Headphone Amp", NULL, "Left Headphone Switch" },
0435 { "Left Headphone Amp", NULL, "Headphone Amp" },
0436 { "HP", NULL, "Left Headphone Amp" },
0437
0438 { "Right Headphone Source", "DAC", "Right DAC" },
0439 { "Right Headphone Source", "Mixer", "Right Mixer" },
0440 { "Right Headphone Switch", "Headphone Playback Switch", "Right Headphone Source" },
0441 { "Right Headphone Amp", NULL, "Right Headphone Switch" },
0442 { "Right Headphone Amp", NULL, "Headphone Amp" },
0443 { "HP", NULL, "Right Headphone Amp" },
0444
0445 { "Headphone Amp", NULL, "cpvdd" },
0446
0447
0448 { "Mic1 Amplifier", NULL, "MIC1"},
0449
0450
0451 { "Mic2 Amplifier", NULL, "MIC2"},
0452
0453
0454 { "Left Line Out Source", "Stereo", "Left Mixer" },
0455 { "Left Line Out Source", "Mono Differential", "Left Mixer" },
0456 { "Left Line Out Source", "Mono Differential", "Right Mixer" },
0457 { "Left Line Out Switch", "Line Out Playback Switch", "Left Line Out Source" },
0458 { "LINEOUT", NULL, "Left Line Out Switch" },
0459
0460 { "Right Line Out Switch", "Line Out Playback Switch", "Right Mixer" },
0461 { "Right Line Out Source", "Stereo", "Right Line Out Switch" },
0462 { "Right Line Out Source", "Mono Differential", "Left Line Out Switch" },
0463 { "LINEOUT", NULL, "Right Line Out Source" },
0464
0465
0466 { "Earpiece Source Playback Route", "DACL", "Left DAC" },
0467 { "Earpiece Source Playback Route", "DACR", "Right DAC" },
0468 { "Earpiece Source Playback Route", "Left Mixer", "Left Mixer" },
0469 { "Earpiece Source Playback Route", "Right Mixer", "Right Mixer" },
0470 { "Earpiece Switch", "Earpiece Playback Switch", "Earpiece Source Playback Route" },
0471 { "Earpiece Amp", NULL, "Earpiece Switch" },
0472 { "EARPIECE", NULL, "Earpiece Amp" },
0473 };
0474
0475 static int sun50i_a64_codec_suspend(struct snd_soc_component *component)
0476 {
0477 return regmap_update_bits(component->regmap, SUN50I_ADDA_HP_CTRL,
0478 BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE),
0479 BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE));
0480 }
0481
0482 static int sun50i_a64_codec_resume(struct snd_soc_component *component)
0483 {
0484 return regmap_update_bits(component->regmap, SUN50I_ADDA_HP_CTRL,
0485 BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE), 0);
0486 }
0487
0488 static const struct snd_soc_component_driver sun50i_codec_analog_cmpnt_drv = {
0489 .controls = sun50i_a64_codec_controls,
0490 .num_controls = ARRAY_SIZE(sun50i_a64_codec_controls),
0491 .dapm_widgets = sun50i_a64_codec_widgets,
0492 .num_dapm_widgets = ARRAY_SIZE(sun50i_a64_codec_widgets),
0493 .dapm_routes = sun50i_a64_codec_routes,
0494 .num_dapm_routes = ARRAY_SIZE(sun50i_a64_codec_routes),
0495 .suspend = sun50i_a64_codec_suspend,
0496 .resume = sun50i_a64_codec_resume,
0497 };
0498
0499 static const struct of_device_id sun50i_codec_analog_of_match[] = {
0500 {
0501 .compatible = "allwinner,sun50i-a64-codec-analog",
0502 },
0503 {}
0504 };
0505 MODULE_DEVICE_TABLE(of, sun50i_codec_analog_of_match);
0506
0507 static int sun50i_codec_analog_probe(struct platform_device *pdev)
0508 {
0509 struct regmap *regmap;
0510 void __iomem *base;
0511 bool enable;
0512
0513 base = devm_platform_ioremap_resource(pdev, 0);
0514 if (IS_ERR(base)) {
0515 dev_err(&pdev->dev, "Failed to map the registers\n");
0516 return PTR_ERR(base);
0517 }
0518
0519 regmap = sun8i_adda_pr_regmap_init(&pdev->dev, base);
0520 if (IS_ERR(regmap)) {
0521 dev_err(&pdev->dev, "Failed to create regmap\n");
0522 return PTR_ERR(regmap);
0523 }
0524
0525 enable = device_property_read_bool(&pdev->dev,
0526 "allwinner,internal-bias-resistor");
0527 regmap_update_bits(regmap, SUN50I_ADDA_JACK_MIC_CTRL,
0528 BIT(SUN50I_ADDA_JACK_MIC_CTRL_INNERRESEN),
0529 enable << SUN50I_ADDA_JACK_MIC_CTRL_INNERRESEN);
0530
0531 return devm_snd_soc_register_component(&pdev->dev,
0532 &sun50i_codec_analog_cmpnt_drv,
0533 NULL, 0);
0534 }
0535
0536 static struct platform_driver sun50i_codec_analog_driver = {
0537 .driver = {
0538 .name = "sun50i-codec-analog",
0539 .of_match_table = sun50i_codec_analog_of_match,
0540 },
0541 .probe = sun50i_codec_analog_probe,
0542 };
0543 module_platform_driver(sun50i_codec_analog_driver);
0544
0545 MODULE_DESCRIPTION("Allwinner internal codec analog controls driver for A64");
0546 MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>");
0547 MODULE_LICENSE("GPL");
0548 MODULE_ALIAS("platform:sun50i-codec-analog");