Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * alc5623.c  --  alc562[123] ALSA Soc Audio driver
0004  *
0005  * Copyright 2008 Realtek Microelectronics
0006  * Author: flove <flove@realtek.com> Ethan <eku@marvell.com>
0007  *
0008  * Copyright 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
0009  *
0010  * Based on WM8753.c
0011  */
0012 
0013 #include <linux/module.h>
0014 #include <linux/kernel.h>
0015 #include <linux/init.h>
0016 #include <linux/delay.h>
0017 #include <linux/pm.h>
0018 #include <linux/i2c.h>
0019 #include <linux/regmap.h>
0020 #include <linux/slab.h>
0021 #include <linux/of.h>
0022 #include <sound/core.h>
0023 #include <sound/pcm.h>
0024 #include <sound/pcm_params.h>
0025 #include <sound/tlv.h>
0026 #include <sound/soc.h>
0027 #include <sound/initval.h>
0028 #include <sound/alc5623.h>
0029 
0030 #include "alc5623.h"
0031 
0032 static int caps_charge = 2000;
0033 module_param(caps_charge, int, 0);
0034 MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)");
0035 
0036 /* codec private data */
0037 struct alc5623_priv {
0038     struct regmap *regmap;
0039     u8 id;
0040     unsigned int sysclk;
0041     unsigned int add_ctrl;
0042     unsigned int jack_det_ctrl;
0043 };
0044 
0045 static inline int alc5623_reset(struct snd_soc_component *component)
0046 {
0047     return snd_soc_component_write(component, ALC5623_RESET, 0);
0048 }
0049 
0050 static int amp_mixer_event(struct snd_soc_dapm_widget *w,
0051     struct snd_kcontrol *kcontrol, int event)
0052 {
0053     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0054 
0055     /* to power-on/off class-d amp generators/speaker */
0056     /* need to write to 'index-46h' register :        */
0057     /* so write index num (here 0x46) to reg 0x6a     */
0058     /* and then 0xffff/0 to reg 0x6c                  */
0059     snd_soc_component_write(component, ALC5623_HID_CTRL_INDEX, 0x46);
0060 
0061     switch (event) {
0062     case SND_SOC_DAPM_PRE_PMU:
0063         snd_soc_component_write(component, ALC5623_HID_CTRL_DATA, 0xFFFF);
0064         break;
0065     case SND_SOC_DAPM_POST_PMD:
0066         snd_soc_component_write(component, ALC5623_HID_CTRL_DATA, 0);
0067         break;
0068     }
0069 
0070     return 0;
0071 }
0072 
0073 /*
0074  * ALC5623 Controls
0075  */
0076 
0077 static const DECLARE_TLV_DB_SCALE(vol_tlv, -3450, 150, 0);
0078 static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0);
0079 static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0);
0080 static const DECLARE_TLV_DB_RANGE(boost_tlv,
0081     0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
0082     1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
0083     2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0)
0084 );
0085 static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0);
0086 
0087 static const struct snd_kcontrol_new alc5621_vol_snd_controls[] = {
0088     SOC_DOUBLE_TLV("Speaker Playback Volume",
0089             ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),
0090     SOC_DOUBLE("Speaker Playback Switch",
0091             ALC5623_SPK_OUT_VOL, 15, 7, 1, 1),
0092     SOC_DOUBLE_TLV("Headphone Playback Volume",
0093             ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),
0094     SOC_DOUBLE("Headphone Playback Switch",
0095             ALC5623_HP_OUT_VOL, 15, 7, 1, 1),
0096 };
0097 
0098 static const struct snd_kcontrol_new alc5622_vol_snd_controls[] = {
0099     SOC_DOUBLE_TLV("Speaker Playback Volume",
0100             ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),
0101     SOC_DOUBLE("Speaker Playback Switch",
0102             ALC5623_SPK_OUT_VOL, 15, 7, 1, 1),
0103     SOC_DOUBLE_TLV("Line Playback Volume",
0104             ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),
0105     SOC_DOUBLE("Line Playback Switch",
0106             ALC5623_HP_OUT_VOL, 15, 7, 1, 1),
0107 };
0108 
0109 static const struct snd_kcontrol_new alc5623_vol_snd_controls[] = {
0110     SOC_DOUBLE_TLV("Line Playback Volume",
0111             ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),
0112     SOC_DOUBLE("Line Playback Switch",
0113             ALC5623_SPK_OUT_VOL, 15, 7, 1, 1),
0114     SOC_DOUBLE_TLV("Headphone Playback Volume",
0115             ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),
0116     SOC_DOUBLE("Headphone Playback Switch",
0117             ALC5623_HP_OUT_VOL, 15, 7, 1, 1),
0118 };
0119 
0120 static const struct snd_kcontrol_new alc5623_snd_controls[] = {
0121     SOC_DOUBLE_TLV("Auxout Playback Volume",
0122             ALC5623_MONO_AUX_OUT_VOL, 8, 0, 31, 1, hp_tlv),
0123     SOC_DOUBLE("Auxout Playback Switch",
0124             ALC5623_MONO_AUX_OUT_VOL, 15, 7, 1, 1),
0125     SOC_DOUBLE_TLV("PCM Playback Volume",
0126             ALC5623_STEREO_DAC_VOL, 8, 0, 31, 1, vol_tlv),
0127     SOC_DOUBLE_TLV("AuxI Capture Volume",
0128             ALC5623_AUXIN_VOL, 8, 0, 31, 1, vol_tlv),
0129     SOC_DOUBLE_TLV("LineIn Capture Volume",
0130             ALC5623_LINE_IN_VOL, 8, 0, 31, 1, vol_tlv),
0131     SOC_SINGLE_TLV("Mic1 Capture Volume",
0132             ALC5623_MIC_VOL, 8, 31, 1, vol_tlv),
0133     SOC_SINGLE_TLV("Mic2 Capture Volume",
0134             ALC5623_MIC_VOL, 0, 31, 1, vol_tlv),
0135     SOC_DOUBLE_TLV("Rec Capture Volume",
0136             ALC5623_ADC_REC_GAIN, 7, 0, 31, 0, adc_rec_tlv),
0137     SOC_SINGLE_TLV("Mic 1 Boost Volume",
0138             ALC5623_MIC_CTRL, 10, 2, 0, boost_tlv),
0139     SOC_SINGLE_TLV("Mic 2 Boost Volume",
0140             ALC5623_MIC_CTRL, 8, 2, 0, boost_tlv),
0141     SOC_SINGLE_TLV("Digital Boost Volume",
0142             ALC5623_ADD_CTRL_REG, 4, 3, 0, dig_tlv),
0143 };
0144 
0145 /*
0146  * DAPM Controls
0147  */
0148 static const struct snd_kcontrol_new alc5623_hp_mixer_controls[] = {
0149 SOC_DAPM_SINGLE("LI2HP Playback Switch", ALC5623_LINE_IN_VOL, 15, 1, 1),
0150 SOC_DAPM_SINGLE("AUXI2HP Playback Switch", ALC5623_AUXIN_VOL, 15, 1, 1),
0151 SOC_DAPM_SINGLE("MIC12HP Playback Switch", ALC5623_MIC_ROUTING_CTRL, 15, 1, 1),
0152 SOC_DAPM_SINGLE("MIC22HP Playback Switch", ALC5623_MIC_ROUTING_CTRL, 7, 1, 1),
0153 SOC_DAPM_SINGLE("DAC2HP Playback Switch", ALC5623_STEREO_DAC_VOL, 15, 1, 1),
0154 };
0155 
0156 static const struct snd_kcontrol_new alc5623_hpl_mixer_controls[] = {
0157 SOC_DAPM_SINGLE("ADC2HP_L Playback Switch", ALC5623_ADC_REC_GAIN, 15, 1, 1),
0158 };
0159 
0160 static const struct snd_kcontrol_new alc5623_hpr_mixer_controls[] = {
0161 SOC_DAPM_SINGLE("ADC2HP_R Playback Switch", ALC5623_ADC_REC_GAIN, 14, 1, 1),
0162 };
0163 
0164 static const struct snd_kcontrol_new alc5623_mono_mixer_controls[] = {
0165 SOC_DAPM_SINGLE("ADC2MONO_L Playback Switch", ALC5623_ADC_REC_GAIN, 13, 1, 1),
0166 SOC_DAPM_SINGLE("ADC2MONO_R Playback Switch", ALC5623_ADC_REC_GAIN, 12, 1, 1),
0167 SOC_DAPM_SINGLE("LI2MONO Playback Switch", ALC5623_LINE_IN_VOL, 13, 1, 1),
0168 SOC_DAPM_SINGLE("AUXI2MONO Playback Switch", ALC5623_AUXIN_VOL, 13, 1, 1),
0169 SOC_DAPM_SINGLE("MIC12MONO Playback Switch", ALC5623_MIC_ROUTING_CTRL, 13, 1, 1),
0170 SOC_DAPM_SINGLE("MIC22MONO Playback Switch", ALC5623_MIC_ROUTING_CTRL, 5, 1, 1),
0171 SOC_DAPM_SINGLE("DAC2MONO Playback Switch", ALC5623_STEREO_DAC_VOL, 13, 1, 1),
0172 };
0173 
0174 static const struct snd_kcontrol_new alc5623_speaker_mixer_controls[] = {
0175 SOC_DAPM_SINGLE("LI2SPK Playback Switch", ALC5623_LINE_IN_VOL, 14, 1, 1),
0176 SOC_DAPM_SINGLE("AUXI2SPK Playback Switch", ALC5623_AUXIN_VOL, 14, 1, 1),
0177 SOC_DAPM_SINGLE("MIC12SPK Playback Switch", ALC5623_MIC_ROUTING_CTRL, 14, 1, 1),
0178 SOC_DAPM_SINGLE("MIC22SPK Playback Switch", ALC5623_MIC_ROUTING_CTRL, 6, 1, 1),
0179 SOC_DAPM_SINGLE("DAC2SPK Playback Switch", ALC5623_STEREO_DAC_VOL, 14, 1, 1),
0180 };
0181 
0182 /* Left Record Mixer */
0183 static const struct snd_kcontrol_new alc5623_captureL_mixer_controls[] = {
0184 SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5623_ADC_REC_MIXER, 14, 1, 1),
0185 SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5623_ADC_REC_MIXER, 13, 1, 1),
0186 SOC_DAPM_SINGLE("LineInL Capture Switch", ALC5623_ADC_REC_MIXER, 12, 1, 1),
0187 SOC_DAPM_SINGLE("Left AuxI Capture Switch", ALC5623_ADC_REC_MIXER, 11, 1, 1),
0188 SOC_DAPM_SINGLE("HPMixerL Capture Switch", ALC5623_ADC_REC_MIXER, 10, 1, 1),
0189 SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5623_ADC_REC_MIXER, 9, 1, 1),
0190 SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5623_ADC_REC_MIXER, 8, 1, 1),
0191 };
0192 
0193 /* Right Record Mixer */
0194 static const struct snd_kcontrol_new alc5623_captureR_mixer_controls[] = {
0195 SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5623_ADC_REC_MIXER, 6, 1, 1),
0196 SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5623_ADC_REC_MIXER, 5, 1, 1),
0197 SOC_DAPM_SINGLE("LineInR Capture Switch", ALC5623_ADC_REC_MIXER, 4, 1, 1),
0198 SOC_DAPM_SINGLE("Right AuxI Capture Switch", ALC5623_ADC_REC_MIXER, 3, 1, 1),
0199 SOC_DAPM_SINGLE("HPMixerR Capture Switch", ALC5623_ADC_REC_MIXER, 2, 1, 1),
0200 SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5623_ADC_REC_MIXER, 1, 1, 1),
0201 SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5623_ADC_REC_MIXER, 0, 1, 1),
0202 };
0203 
0204 static const char *alc5623_spk_n_sour_sel[] = {
0205         "RN/-R", "RP/+R", "LN/-R", "Vmid" };
0206 static const char *alc5623_hpl_out_input_sel[] = {
0207         "Vmid", "HP Left Mix"};
0208 static const char *alc5623_hpr_out_input_sel[] = {
0209         "Vmid", "HP Right Mix"};
0210 static const char *alc5623_spkout_input_sel[] = {
0211         "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
0212 static const char *alc5623_aux_out_input_sel[] = {
0213         "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
0214 
0215 /* auxout output mux */
0216 static SOC_ENUM_SINGLE_DECL(alc5623_aux_out_input_enum,
0217                 ALC5623_OUTPUT_MIXER_CTRL, 6,
0218                 alc5623_aux_out_input_sel);
0219 static const struct snd_kcontrol_new alc5623_auxout_mux_controls =
0220 SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum);
0221 
0222 /* speaker output mux */
0223 static SOC_ENUM_SINGLE_DECL(alc5623_spkout_input_enum,
0224                 ALC5623_OUTPUT_MIXER_CTRL, 10,
0225                 alc5623_spkout_input_sel);
0226 static const struct snd_kcontrol_new alc5623_spkout_mux_controls =
0227 SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum);
0228 
0229 /* headphone left output mux */
0230 static SOC_ENUM_SINGLE_DECL(alc5623_hpl_out_input_enum,
0231                 ALC5623_OUTPUT_MIXER_CTRL, 9,
0232                 alc5623_hpl_out_input_sel);
0233 static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls =
0234 SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum);
0235 
0236 /* headphone right output mux */
0237 static SOC_ENUM_SINGLE_DECL(alc5623_hpr_out_input_enum,
0238                 ALC5623_OUTPUT_MIXER_CTRL, 8,
0239                 alc5623_hpr_out_input_sel);
0240 static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls =
0241 SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum);
0242 
0243 /* speaker output N select */
0244 static SOC_ENUM_SINGLE_DECL(alc5623_spk_n_sour_enum,
0245                 ALC5623_OUTPUT_MIXER_CTRL, 14,
0246                 alc5623_spk_n_sour_sel);
0247 static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls =
0248 SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum);
0249 
0250 static const struct snd_soc_dapm_widget alc5623_dapm_widgets[] = {
0251 /* Muxes */
0252 SND_SOC_DAPM_MUX("AuxOut Mux", SND_SOC_NOPM, 0, 0,
0253     &alc5623_auxout_mux_controls),
0254 SND_SOC_DAPM_MUX("SpeakerOut Mux", SND_SOC_NOPM, 0, 0,
0255     &alc5623_spkout_mux_controls),
0256 SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0,
0257     &alc5623_hpl_out_mux_controls),
0258 SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,
0259     &alc5623_hpr_out_mux_controls),
0260 SND_SOC_DAPM_MUX("SpeakerOut N Mux", SND_SOC_NOPM, 0, 0,
0261     &alc5623_spkoutn_mux_controls),
0262 
0263 /* output mixers */
0264 SND_SOC_DAPM_MIXER("HP Mix", SND_SOC_NOPM, 0, 0,
0265     &alc5623_hp_mixer_controls[0],
0266     ARRAY_SIZE(alc5623_hp_mixer_controls)),
0267 SND_SOC_DAPM_MIXER("HPR Mix", ALC5623_PWR_MANAG_ADD2, 4, 0,
0268     &alc5623_hpr_mixer_controls[0],
0269     ARRAY_SIZE(alc5623_hpr_mixer_controls)),
0270 SND_SOC_DAPM_MIXER("HPL Mix", ALC5623_PWR_MANAG_ADD2, 5, 0,
0271     &alc5623_hpl_mixer_controls[0],
0272     ARRAY_SIZE(alc5623_hpl_mixer_controls)),
0273 SND_SOC_DAPM_MIXER("HPOut Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
0274 SND_SOC_DAPM_MIXER("Mono Mix", ALC5623_PWR_MANAG_ADD2, 2, 0,
0275     &alc5623_mono_mixer_controls[0],
0276     ARRAY_SIZE(alc5623_mono_mixer_controls)),
0277 SND_SOC_DAPM_MIXER("Speaker Mix", ALC5623_PWR_MANAG_ADD2, 3, 0,
0278     &alc5623_speaker_mixer_controls[0],
0279     ARRAY_SIZE(alc5623_speaker_mixer_controls)),
0280 
0281 /* input mixers */
0282 SND_SOC_DAPM_MIXER("Left Capture Mix", ALC5623_PWR_MANAG_ADD2, 1, 0,
0283     &alc5623_captureL_mixer_controls[0],
0284     ARRAY_SIZE(alc5623_captureL_mixer_controls)),
0285 SND_SOC_DAPM_MIXER("Right Capture Mix", ALC5623_PWR_MANAG_ADD2, 0, 0,
0286     &alc5623_captureR_mixer_controls[0],
0287     ARRAY_SIZE(alc5623_captureR_mixer_controls)),
0288 
0289 SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback",
0290     ALC5623_PWR_MANAG_ADD2, 9, 0),
0291 SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback",
0292     ALC5623_PWR_MANAG_ADD2, 8, 0),
0293 SND_SOC_DAPM_MIXER("I2S Mix", ALC5623_PWR_MANAG_ADD1, 15, 0, NULL, 0),
0294 SND_SOC_DAPM_MIXER("AuxI Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
0295 SND_SOC_DAPM_MIXER("Line Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
0296 SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture",
0297     ALC5623_PWR_MANAG_ADD2, 7, 0),
0298 SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture",
0299     ALC5623_PWR_MANAG_ADD2, 6, 0),
0300 SND_SOC_DAPM_PGA("Left Headphone", ALC5623_PWR_MANAG_ADD3, 10, 0, NULL, 0),
0301 SND_SOC_DAPM_PGA("Right Headphone", ALC5623_PWR_MANAG_ADD3, 9, 0, NULL, 0),
0302 SND_SOC_DAPM_PGA("SpeakerOut", ALC5623_PWR_MANAG_ADD3, 12, 0, NULL, 0),
0303 SND_SOC_DAPM_PGA("Left AuxOut", ALC5623_PWR_MANAG_ADD3, 14, 0, NULL, 0),
0304 SND_SOC_DAPM_PGA("Right AuxOut", ALC5623_PWR_MANAG_ADD3, 13, 0, NULL, 0),
0305 SND_SOC_DAPM_PGA("Left LineIn", ALC5623_PWR_MANAG_ADD3, 7, 0, NULL, 0),
0306 SND_SOC_DAPM_PGA("Right LineIn", ALC5623_PWR_MANAG_ADD3, 6, 0, NULL, 0),
0307 SND_SOC_DAPM_PGA("Left AuxI", ALC5623_PWR_MANAG_ADD3, 5, 0, NULL, 0),
0308 SND_SOC_DAPM_PGA("Right AuxI", ALC5623_PWR_MANAG_ADD3, 4, 0, NULL, 0),
0309 SND_SOC_DAPM_PGA("MIC1 PGA", ALC5623_PWR_MANAG_ADD3, 3, 0, NULL, 0),
0310 SND_SOC_DAPM_PGA("MIC2 PGA", ALC5623_PWR_MANAG_ADD3, 2, 0, NULL, 0),
0311 SND_SOC_DAPM_PGA("MIC1 Pre Amp", ALC5623_PWR_MANAG_ADD3, 1, 0, NULL, 0),
0312 SND_SOC_DAPM_PGA("MIC2 Pre Amp", ALC5623_PWR_MANAG_ADD3, 0, 0, NULL, 0),
0313 SND_SOC_DAPM_MICBIAS("Mic Bias1", ALC5623_PWR_MANAG_ADD1, 11, 0),
0314 
0315 SND_SOC_DAPM_OUTPUT("AUXOUTL"),
0316 SND_SOC_DAPM_OUTPUT("AUXOUTR"),
0317 SND_SOC_DAPM_OUTPUT("HPL"),
0318 SND_SOC_DAPM_OUTPUT("HPR"),
0319 SND_SOC_DAPM_OUTPUT("SPKOUT"),
0320 SND_SOC_DAPM_OUTPUT("SPKOUTN"),
0321 SND_SOC_DAPM_INPUT("LINEINL"),
0322 SND_SOC_DAPM_INPUT("LINEINR"),
0323 SND_SOC_DAPM_INPUT("AUXINL"),
0324 SND_SOC_DAPM_INPUT("AUXINR"),
0325 SND_SOC_DAPM_INPUT("MIC1"),
0326 SND_SOC_DAPM_INPUT("MIC2"),
0327 SND_SOC_DAPM_VMID("Vmid"),
0328 };
0329 
0330 static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"};
0331 static SOC_ENUM_SINGLE_DECL(alc5623_amp_enum,
0332                 ALC5623_OUTPUT_MIXER_CTRL, 13,
0333                 alc5623_amp_names);
0334 static const struct snd_kcontrol_new alc5623_amp_mux_controls =
0335     SOC_DAPM_ENUM("Route", alc5623_amp_enum);
0336 
0337 static const struct snd_soc_dapm_widget alc5623_dapm_amp_widgets[] = {
0338 SND_SOC_DAPM_PGA_E("D Amp", ALC5623_PWR_MANAG_ADD2, 14, 0, NULL, 0,
0339     amp_mixer_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0340 SND_SOC_DAPM_PGA("AB Amp", ALC5623_PWR_MANAG_ADD2, 15, 0, NULL, 0),
0341 SND_SOC_DAPM_MUX("AB-D Amp Mux", SND_SOC_NOPM, 0, 0,
0342     &alc5623_amp_mux_controls),
0343 };
0344 
0345 static const struct snd_soc_dapm_route intercon[] = {
0346     /* virtual mixer - mixes left & right channels */
0347     {"I2S Mix", NULL,               "Left DAC"},
0348     {"I2S Mix", NULL,               "Right DAC"},
0349     {"Line Mix", NULL,              "Right LineIn"},
0350     {"Line Mix", NULL,              "Left LineIn"},
0351     {"AuxI Mix", NULL,              "Left AuxI"},
0352     {"AuxI Mix", NULL,              "Right AuxI"},
0353     {"AUXOUTL", NULL,               "Left AuxOut"},
0354     {"AUXOUTR", NULL,               "Right AuxOut"},
0355 
0356     /* HP mixer */
0357     {"HPL Mix", "ADC2HP_L Playback Switch",     "Left Capture Mix"},
0358     {"HPL Mix", NULL,               "HP Mix"},
0359     {"HPR Mix", "ADC2HP_R Playback Switch",     "Right Capture Mix"},
0360     {"HPR Mix", NULL,               "HP Mix"},
0361     {"HP Mix", "LI2HP Playback Switch",     "Line Mix"},
0362     {"HP Mix", "AUXI2HP Playback Switch",       "AuxI Mix"},
0363     {"HP Mix", "MIC12HP Playback Switch",       "MIC1 PGA"},
0364     {"HP Mix", "MIC22HP Playback Switch",       "MIC2 PGA"},
0365     {"HP Mix", "DAC2HP Playback Switch",        "I2S Mix"},
0366 
0367     /* speaker mixer */
0368     {"Speaker Mix", "LI2SPK Playback Switch",   "Line Mix"},
0369     {"Speaker Mix", "AUXI2SPK Playback Switch", "AuxI Mix"},
0370     {"Speaker Mix", "MIC12SPK Playback Switch", "MIC1 PGA"},
0371     {"Speaker Mix", "MIC22SPK Playback Switch", "MIC2 PGA"},
0372     {"Speaker Mix", "DAC2SPK Playback Switch",  "I2S Mix"},
0373 
0374     /* mono mixer */
0375     {"Mono Mix", "ADC2MONO_L Playback Switch",  "Left Capture Mix"},
0376     {"Mono Mix", "ADC2MONO_R Playback Switch",  "Right Capture Mix"},
0377     {"Mono Mix", "LI2MONO Playback Switch",     "Line Mix"},
0378     {"Mono Mix", "AUXI2MONO Playback Switch",   "AuxI Mix"},
0379     {"Mono Mix", "MIC12MONO Playback Switch",   "MIC1 PGA"},
0380     {"Mono Mix", "MIC22MONO Playback Switch",   "MIC2 PGA"},
0381     {"Mono Mix", "DAC2MONO Playback Switch",    "I2S Mix"},
0382 
0383     /* Left record mixer */
0384     {"Left Capture Mix", "LineInL Capture Switch",  "LINEINL"},
0385     {"Left Capture Mix", "Left AuxI Capture Switch", "AUXINL"},
0386     {"Left Capture Mix", "Mic1 Capture Switch", "MIC1 Pre Amp"},
0387     {"Left Capture Mix", "Mic2 Capture Switch", "MIC2 Pre Amp"},
0388     {"Left Capture Mix", "HPMixerL Capture Switch", "HPL Mix"},
0389     {"Left Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
0390     {"Left Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
0391 
0392     /*Right record mixer */
0393     {"Right Capture Mix", "LineInR Capture Switch", "LINEINR"},
0394     {"Right Capture Mix", "Right AuxI Capture Switch",  "AUXINR"},
0395     {"Right Capture Mix", "Mic1 Capture Switch",    "MIC1 Pre Amp"},
0396     {"Right Capture Mix", "Mic2 Capture Switch",    "MIC2 Pre Amp"},
0397     {"Right Capture Mix", "HPMixerR Capture Switch", "HPR Mix"},
0398     {"Right Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
0399     {"Right Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
0400 
0401     /* headphone left mux */
0402     {"Left Headphone Mux", "HP Left Mix",       "HPL Mix"},
0403     {"Left Headphone Mux", "Vmid",          "Vmid"},
0404 
0405     /* headphone right mux */
0406     {"Right Headphone Mux", "HP Right Mix",     "HPR Mix"},
0407     {"Right Headphone Mux", "Vmid",         "Vmid"},
0408 
0409     /* speaker out mux */
0410     {"SpeakerOut Mux", "Vmid",          "Vmid"},
0411     {"SpeakerOut Mux", "HPOut Mix",         "HPOut Mix"},
0412     {"SpeakerOut Mux", "Speaker Mix",       "Speaker Mix"},
0413     {"SpeakerOut Mux", "Mono Mix",          "Mono Mix"},
0414 
0415     /* Mono/Aux Out mux */
0416     {"AuxOut Mux", "Vmid",              "Vmid"},
0417     {"AuxOut Mux", "HPOut Mix",         "HPOut Mix"},
0418     {"AuxOut Mux", "Speaker Mix",           "Speaker Mix"},
0419     {"AuxOut Mux", "Mono Mix",          "Mono Mix"},
0420 
0421     /* output pga */
0422     {"HPL", NULL,                   "Left Headphone"},
0423     {"Left Headphone", NULL,            "Left Headphone Mux"},
0424     {"HPR", NULL,                   "Right Headphone"},
0425     {"Right Headphone", NULL,           "Right Headphone Mux"},
0426     {"Left AuxOut", NULL,               "AuxOut Mux"},
0427     {"Right AuxOut", NULL,              "AuxOut Mux"},
0428 
0429     /* input pga */
0430     {"Left LineIn", NULL,               "LINEINL"},
0431     {"Right LineIn", NULL,              "LINEINR"},
0432     {"Left AuxI", NULL,             "AUXINL"},
0433     {"Right AuxI", NULL,                "AUXINR"},
0434     {"MIC1 Pre Amp", NULL,              "MIC1"},
0435     {"MIC2 Pre Amp", NULL,              "MIC2"},
0436     {"MIC1 PGA", NULL,              "MIC1 Pre Amp"},
0437     {"MIC2 PGA", NULL,              "MIC2 Pre Amp"},
0438 
0439     /* left ADC */
0440     {"Left ADC", NULL,              "Left Capture Mix"},
0441 
0442     /* right ADC */
0443     {"Right ADC", NULL,             "Right Capture Mix"},
0444 
0445     {"SpeakerOut N Mux", "RN/-R",           "SpeakerOut"},
0446     {"SpeakerOut N Mux", "RP/+R",           "SpeakerOut"},
0447     {"SpeakerOut N Mux", "LN/-R",           "SpeakerOut"},
0448     {"SpeakerOut N Mux", "Vmid",            "Vmid"},
0449 
0450     {"SPKOUT", NULL,                "SpeakerOut"},
0451     {"SPKOUTN", NULL,               "SpeakerOut N Mux"},
0452 };
0453 
0454 static const struct snd_soc_dapm_route intercon_spk[] = {
0455     {"SpeakerOut", NULL,                "SpeakerOut Mux"},
0456 };
0457 
0458 static const struct snd_soc_dapm_route intercon_amp_spk[] = {
0459     {"AB Amp", NULL,                "SpeakerOut Mux"},
0460     {"D Amp", NULL,                 "SpeakerOut Mux"},
0461     {"AB-D Amp Mux", "AB Amp",          "AB Amp"},
0462     {"AB-D Amp Mux", "D Amp",           "D Amp"},
0463     {"SpeakerOut", NULL,                "AB-D Amp Mux"},
0464 };
0465 
0466 /* PLL divisors */
0467 struct _pll_div {
0468     u32 pll_in;
0469     u32 pll_out;
0470     u16 regvalue;
0471 };
0472 
0473 /* Note : pll code from original alc5623 driver. Not sure of how good it is */
0474 /* useful only for master mode */
0475 static const struct _pll_div codec_master_pll_div[] = {
0476 
0477     {  2048000,  8192000,   0x0ea0},
0478     {  3686400,  8192000,   0x4e27},
0479     { 12000000,  8192000,   0x456b},
0480     { 13000000,  8192000,   0x495f},
0481     { 13100000,  8192000,   0x0320},
0482     {  2048000,  11289600,  0xf637},
0483     {  3686400,  11289600,  0x2f22},
0484     { 12000000,  11289600,  0x3e2f},
0485     { 13000000,  11289600,  0x4d5b},
0486     { 13100000,  11289600,  0x363b},
0487     {  2048000,  16384000,  0x1ea0},
0488     {  3686400,  16384000,  0x9e27},
0489     { 12000000,  16384000,  0x452b},
0490     { 13000000,  16384000,  0x542f},
0491     { 13100000,  16384000,  0x03a0},
0492     {  2048000,  16934400,  0xe625},
0493     {  3686400,  16934400,  0x9126},
0494     { 12000000,  16934400,  0x4d2c},
0495     { 13000000,  16934400,  0x742f},
0496     { 13100000,  16934400,  0x3c27},
0497     {  2048000,  22579200,  0x2aa0},
0498     {  3686400,  22579200,  0x2f20},
0499     { 12000000,  22579200,  0x7e2f},
0500     { 13000000,  22579200,  0x742f},
0501     { 13100000,  22579200,  0x3c27},
0502     {  2048000,  24576000,  0x2ea0},
0503     {  3686400,  24576000,  0xee27},
0504     { 12000000,  24576000,  0x2915},
0505     { 13000000,  24576000,  0x772e},
0506     { 13100000,  24576000,  0x0d20},
0507 };
0508 
0509 static const struct _pll_div codec_slave_pll_div[] = {
0510 
0511     {  1024000,  16384000,  0x3ea0},
0512     {  1411200,  22579200,  0x3ea0},
0513     {  1536000,  24576000,  0x3ea0},
0514     {  2048000,  16384000,  0x1ea0},
0515     {  2822400,  22579200,  0x1ea0},
0516     {  3072000,  24576000,  0x1ea0},
0517 
0518 };
0519 
0520 static int alc5623_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
0521         int source, unsigned int freq_in, unsigned int freq_out)
0522 {
0523     int i;
0524     struct snd_soc_component *component = codec_dai->component;
0525     int gbl_clk = 0, pll_div = 0;
0526     u16 reg;
0527 
0528     if (pll_id < ALC5623_PLL_FR_MCLK || pll_id > ALC5623_PLL_FR_BCK)
0529         return -ENODEV;
0530 
0531     /* Disable PLL power */
0532     snd_soc_component_update_bits(component, ALC5623_PWR_MANAG_ADD2,
0533                 ALC5623_PWR_ADD2_PLL,
0534                 0);
0535 
0536     /* pll is not used in slave mode */
0537     reg = snd_soc_component_read(component, ALC5623_DAI_CONTROL);
0538     if (reg & ALC5623_DAI_SDP_SLAVE_MODE)
0539         return 0;
0540 
0541     if (!freq_in || !freq_out)
0542         return 0;
0543 
0544     switch (pll_id) {
0545     case ALC5623_PLL_FR_MCLK:
0546         for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++) {
0547             if (codec_master_pll_div[i].pll_in == freq_in
0548                && codec_master_pll_div[i].pll_out == freq_out) {
0549                 /* PLL source from MCLK */
0550                 pll_div  = codec_master_pll_div[i].regvalue;
0551                 break;
0552             }
0553         }
0554         break;
0555     case ALC5623_PLL_FR_BCK:
0556         for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) {
0557             if (codec_slave_pll_div[i].pll_in == freq_in
0558                && codec_slave_pll_div[i].pll_out == freq_out) {
0559                 /* PLL source from Bitclk */
0560                 gbl_clk = ALC5623_GBL_CLK_PLL_SOUR_SEL_BITCLK;
0561                 pll_div = codec_slave_pll_div[i].regvalue;
0562                 break;
0563             }
0564         }
0565         break;
0566     default:
0567         return -EINVAL;
0568     }
0569 
0570     if (!pll_div)
0571         return -EINVAL;
0572 
0573     snd_soc_component_write(component, ALC5623_GLOBAL_CLK_CTRL_REG, gbl_clk);
0574     snd_soc_component_write(component, ALC5623_PLL_CTRL, pll_div);
0575     snd_soc_component_update_bits(component, ALC5623_PWR_MANAG_ADD2,
0576                 ALC5623_PWR_ADD2_PLL,
0577                 ALC5623_PWR_ADD2_PLL);
0578     gbl_clk |= ALC5623_GBL_CLK_SYS_SOUR_SEL_PLL;
0579     snd_soc_component_write(component, ALC5623_GLOBAL_CLK_CTRL_REG, gbl_clk);
0580 
0581     return 0;
0582 }
0583 
0584 struct _coeff_div {
0585     u16 fs;
0586     u16 regvalue;
0587 };
0588 
0589 /* codec hifi mclk (after PLL) clock divider coefficients */
0590 /* values inspired from column BCLK=32Fs of Appendix A table */
0591 static const struct _coeff_div coeff_div[] = {
0592     {256*8, 0x3a69},
0593     {384*8, 0x3c6b},
0594     {256*4, 0x2a69},
0595     {384*4, 0x2c6b},
0596     {256*2, 0x1a69},
0597     {384*2, 0x1c6b},
0598     {256*1, 0x0a69},
0599     {384*1, 0x0c6b},
0600 };
0601 
0602 static int get_coeff(struct snd_soc_component *component, int rate)
0603 {
0604     struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component);
0605     int i;
0606 
0607     for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
0608         if (coeff_div[i].fs * rate == alc5623->sysclk)
0609             return i;
0610     }
0611     return -EINVAL;
0612 }
0613 
0614 /*
0615  * Clock after PLL and dividers
0616  */
0617 static int alc5623_set_dai_sysclk(struct snd_soc_dai *codec_dai,
0618         int clk_id, unsigned int freq, int dir)
0619 {
0620     struct snd_soc_component *component = codec_dai->component;
0621     struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component);
0622 
0623     switch (freq) {
0624     case  8192000:
0625     case 11289600:
0626     case 12288000:
0627     case 16384000:
0628     case 16934400:
0629     case 18432000:
0630     case 22579200:
0631     case 24576000:
0632         alc5623->sysclk = freq;
0633         return 0;
0634     }
0635     return -EINVAL;
0636 }
0637 
0638 static int alc5623_set_dai_fmt(struct snd_soc_dai *codec_dai,
0639         unsigned int fmt)
0640 {
0641     struct snd_soc_component *component = codec_dai->component;
0642     u16 iface = 0;
0643 
0644     /* set audio interface clocking */
0645     switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
0646     case SND_SOC_DAIFMT_CBP_CFP:
0647         iface = ALC5623_DAI_SDP_MASTER_MODE;
0648         break;
0649     case SND_SOC_DAIFMT_CBC_CFC:
0650         iface = ALC5623_DAI_SDP_SLAVE_MODE;
0651         break;
0652     default:
0653         return -EINVAL;
0654     }
0655 
0656     /* interface format */
0657     switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0658     case SND_SOC_DAIFMT_I2S:
0659         iface |= ALC5623_DAI_I2S_DF_I2S;
0660         break;
0661     case SND_SOC_DAIFMT_RIGHT_J:
0662         iface |= ALC5623_DAI_I2S_DF_RIGHT;
0663         break;
0664     case SND_SOC_DAIFMT_LEFT_J:
0665         iface |= ALC5623_DAI_I2S_DF_LEFT;
0666         break;
0667     case SND_SOC_DAIFMT_DSP_A:
0668         iface |= ALC5623_DAI_I2S_DF_PCM;
0669         break;
0670     case SND_SOC_DAIFMT_DSP_B:
0671         iface |= ALC5623_DAI_I2S_DF_PCM | ALC5623_DAI_I2S_PCM_MODE;
0672         break;
0673     default:
0674         return -EINVAL;
0675     }
0676 
0677     /* clock inversion */
0678     switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
0679     case SND_SOC_DAIFMT_NB_NF:
0680         break;
0681     case SND_SOC_DAIFMT_IB_IF:
0682         iface |= ALC5623_DAI_MAIN_I2S_BCLK_POL_CTRL;
0683         break;
0684     case SND_SOC_DAIFMT_IB_NF:
0685         iface |= ALC5623_DAI_MAIN_I2S_BCLK_POL_CTRL;
0686         break;
0687     case SND_SOC_DAIFMT_NB_IF:
0688         break;
0689     default:
0690         return -EINVAL;
0691     }
0692 
0693     return snd_soc_component_write(component, ALC5623_DAI_CONTROL, iface);
0694 }
0695 
0696 static int alc5623_pcm_hw_params(struct snd_pcm_substream *substream,
0697         struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
0698 {
0699     struct snd_soc_component *component = dai->component;
0700     struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component);
0701     int coeff, rate;
0702     u16 iface;
0703 
0704     iface = snd_soc_component_read(component, ALC5623_DAI_CONTROL);
0705     iface &= ~ALC5623_DAI_I2S_DL_MASK;
0706 
0707     /* bit size */
0708     switch (params_width(params)) {
0709     case 16:
0710         iface |= ALC5623_DAI_I2S_DL_16;
0711         break;
0712     case 20:
0713         iface |= ALC5623_DAI_I2S_DL_20;
0714         break;
0715     case 24:
0716         iface |= ALC5623_DAI_I2S_DL_24;
0717         break;
0718     case 32:
0719         iface |= ALC5623_DAI_I2S_DL_32;
0720         break;
0721     default:
0722         return -EINVAL;
0723     }
0724 
0725     /* set iface & srate */
0726     snd_soc_component_write(component, ALC5623_DAI_CONTROL, iface);
0727     rate = params_rate(params);
0728     coeff = get_coeff(component, rate);
0729     if (coeff < 0)
0730         return -EINVAL;
0731 
0732     coeff = coeff_div[coeff].regvalue;
0733     dev_dbg(component->dev, "%s: sysclk=%d,rate=%d,coeff=0x%04x\n",
0734         __func__, alc5623->sysclk, rate, coeff);
0735     snd_soc_component_write(component, ALC5623_STEREO_AD_DA_CLK_CTRL, coeff);
0736 
0737     return 0;
0738 }
0739 
0740 static int alc5623_mute(struct snd_soc_dai *dai, int mute, int direction)
0741 {
0742     struct snd_soc_component *component = dai->component;
0743     u16 hp_mute = ALC5623_MISC_M_DAC_L_INPUT | ALC5623_MISC_M_DAC_R_INPUT;
0744     u16 mute_reg = snd_soc_component_read(component, ALC5623_MISC_CTRL) & ~hp_mute;
0745 
0746     if (mute)
0747         mute_reg |= hp_mute;
0748 
0749     return snd_soc_component_write(component, ALC5623_MISC_CTRL, mute_reg);
0750 }
0751 
0752 #define ALC5623_ADD2_POWER_EN (ALC5623_PWR_ADD2_VREF \
0753     | ALC5623_PWR_ADD2_DAC_REF_CIR)
0754 
0755 #define ALC5623_ADD3_POWER_EN (ALC5623_PWR_ADD3_MAIN_BIAS \
0756     | ALC5623_PWR_ADD3_MIC1_BOOST_AD)
0757 
0758 #define ALC5623_ADD1_POWER_EN \
0759     (ALC5623_PWR_ADD1_SHORT_CURR_DET_EN | ALC5623_PWR_ADD1_SOFTGEN_EN \
0760     | ALC5623_PWR_ADD1_DEPOP_BUF_HP | ALC5623_PWR_ADD1_HP_OUT_AMP \
0761     | ALC5623_PWR_ADD1_HP_OUT_ENH_AMP)
0762 
0763 #define ALC5623_ADD1_POWER_EN_5622 \
0764     (ALC5623_PWR_ADD1_SHORT_CURR_DET_EN \
0765     | ALC5623_PWR_ADD1_HP_OUT_AMP)
0766 
0767 static void enable_power_depop(struct snd_soc_component *component)
0768 {
0769     struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component);
0770 
0771     snd_soc_component_update_bits(component, ALC5623_PWR_MANAG_ADD1,
0772                 ALC5623_PWR_ADD1_SOFTGEN_EN,
0773                 ALC5623_PWR_ADD1_SOFTGEN_EN);
0774 
0775     snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD3, ALC5623_ADD3_POWER_EN);
0776 
0777     snd_soc_component_update_bits(component, ALC5623_MISC_CTRL,
0778                 ALC5623_MISC_HP_DEPOP_MODE2_EN,
0779                 ALC5623_MISC_HP_DEPOP_MODE2_EN);
0780 
0781     msleep(500);
0782 
0783     snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD2, ALC5623_ADD2_POWER_EN);
0784 
0785     /* avoid writing '1' into 5622 reserved bits */
0786     if (alc5623->id == 0x22)
0787         snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD1,
0788             ALC5623_ADD1_POWER_EN_5622);
0789     else
0790         snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD1,
0791             ALC5623_ADD1_POWER_EN);
0792 
0793     /* disable HP Depop2 */
0794     snd_soc_component_update_bits(component, ALC5623_MISC_CTRL,
0795                 ALC5623_MISC_HP_DEPOP_MODE2_EN,
0796                 0);
0797 
0798 }
0799 
0800 static int alc5623_set_bias_level(struct snd_soc_component *component,
0801                       enum snd_soc_bias_level level)
0802 {
0803     switch (level) {
0804     case SND_SOC_BIAS_ON:
0805         enable_power_depop(component);
0806         break;
0807     case SND_SOC_BIAS_PREPARE:
0808         break;
0809     case SND_SOC_BIAS_STANDBY:
0810         /* everything off except vref/vmid, */
0811         snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD2,
0812                 ALC5623_PWR_ADD2_VREF);
0813         snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD3,
0814                 ALC5623_PWR_ADD3_MAIN_BIAS);
0815         break;
0816     case SND_SOC_BIAS_OFF:
0817         /* everything off, dac mute, inactive */
0818         snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD2, 0);
0819         snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD3, 0);
0820         snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD1, 0);
0821         break;
0822     }
0823     return 0;
0824 }
0825 
0826 #define ALC5623_FORMATS (SNDRV_PCM_FMTBIT_S16_LE \
0827             | SNDRV_PCM_FMTBIT_S24_LE \
0828             | SNDRV_PCM_FMTBIT_S32_LE)
0829 
0830 static const struct snd_soc_dai_ops alc5623_dai_ops = {
0831         .hw_params = alc5623_pcm_hw_params,
0832         .mute_stream = alc5623_mute,
0833         .set_fmt = alc5623_set_dai_fmt,
0834         .set_sysclk = alc5623_set_dai_sysclk,
0835         .set_pll = alc5623_set_dai_pll,
0836         .no_capture_mute = 1,
0837 };
0838 
0839 static struct snd_soc_dai_driver alc5623_dai = {
0840     .name = "alc5623-hifi",
0841     .playback = {
0842         .stream_name = "Playback",
0843         .channels_min = 1,
0844         .channels_max = 2,
0845         .rate_min = 8000,
0846         .rate_max = 48000,
0847         .rates = SNDRV_PCM_RATE_8000_48000,
0848         .formats = ALC5623_FORMATS,},
0849     .capture = {
0850         .stream_name = "Capture",
0851         .channels_min = 1,
0852         .channels_max = 2,
0853         .rate_min = 8000,
0854         .rate_max = 48000,
0855         .rates = SNDRV_PCM_RATE_8000_48000,
0856         .formats = ALC5623_FORMATS,},
0857 
0858     .ops = &alc5623_dai_ops,
0859 };
0860 
0861 static int alc5623_suspend(struct snd_soc_component *component)
0862 {
0863     struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component);
0864 
0865     regcache_cache_only(alc5623->regmap, true);
0866 
0867     return 0;
0868 }
0869 
0870 static int alc5623_resume(struct snd_soc_component *component)
0871 {
0872     struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component);
0873     int ret;
0874 
0875     /* Sync reg_cache with the hardware */
0876     regcache_cache_only(alc5623->regmap, false);
0877     ret = regcache_sync(alc5623->regmap);
0878     if (ret != 0) {
0879         dev_err(component->dev, "Failed to sync register cache: %d\n",
0880             ret);
0881         regcache_cache_only(alc5623->regmap, true);
0882         return ret;
0883     }
0884 
0885     return 0;
0886 }
0887 
0888 static int alc5623_probe(struct snd_soc_component *component)
0889 {
0890     struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component);
0891     struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
0892 
0893     alc5623_reset(component);
0894 
0895     if (alc5623->add_ctrl) {
0896         snd_soc_component_write(component, ALC5623_ADD_CTRL_REG,
0897                 alc5623->add_ctrl);
0898     }
0899 
0900     if (alc5623->jack_det_ctrl) {
0901         snd_soc_component_write(component, ALC5623_JACK_DET_CTRL,
0902                 alc5623->jack_det_ctrl);
0903     }
0904 
0905     switch (alc5623->id) {
0906     case 0x21:
0907         snd_soc_add_component_controls(component, alc5621_vol_snd_controls,
0908             ARRAY_SIZE(alc5621_vol_snd_controls));
0909         break;
0910     case 0x22:
0911         snd_soc_add_component_controls(component, alc5622_vol_snd_controls,
0912             ARRAY_SIZE(alc5622_vol_snd_controls));
0913         break;
0914     case 0x23:
0915         snd_soc_add_component_controls(component, alc5623_vol_snd_controls,
0916             ARRAY_SIZE(alc5623_vol_snd_controls));
0917         break;
0918     default:
0919         return -EINVAL;
0920     }
0921 
0922     snd_soc_add_component_controls(component, alc5623_snd_controls,
0923             ARRAY_SIZE(alc5623_snd_controls));
0924 
0925     snd_soc_dapm_new_controls(dapm, alc5623_dapm_widgets,
0926                     ARRAY_SIZE(alc5623_dapm_widgets));
0927 
0928     /* set up audio path interconnects */
0929     snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
0930 
0931     switch (alc5623->id) {
0932     case 0x21:
0933     case 0x22:
0934         snd_soc_dapm_new_controls(dapm, alc5623_dapm_amp_widgets,
0935                     ARRAY_SIZE(alc5623_dapm_amp_widgets));
0936         snd_soc_dapm_add_routes(dapm, intercon_amp_spk,
0937                     ARRAY_SIZE(intercon_amp_spk));
0938         break;
0939     case 0x23:
0940         snd_soc_dapm_add_routes(dapm, intercon_spk,
0941                     ARRAY_SIZE(intercon_spk));
0942         break;
0943     default:
0944         return -EINVAL;
0945     }
0946 
0947     return 0;
0948 }
0949 
0950 static const struct snd_soc_component_driver soc_component_device_alc5623 = {
0951     .probe          = alc5623_probe,
0952     .suspend        = alc5623_suspend,
0953     .resume         = alc5623_resume,
0954     .set_bias_level     = alc5623_set_bias_level,
0955     .suspend_bias_off   = 1,
0956     .idle_bias_on       = 1,
0957     .use_pmdown_time    = 1,
0958     .endianness     = 1,
0959 };
0960 
0961 static const struct regmap_config alc5623_regmap = {
0962     .reg_bits = 8,
0963     .val_bits = 16,
0964     .reg_stride = 2,
0965 
0966     .max_register = ALC5623_VENDOR_ID2,
0967     .cache_type = REGCACHE_RBTREE,
0968 };
0969 
0970 static const struct i2c_device_id alc5623_i2c_table[] = {
0971     {"alc5621", 0x21},
0972     {"alc5622", 0x22},
0973     {"alc5623", 0x23},
0974     {}
0975 };
0976 MODULE_DEVICE_TABLE(i2c, alc5623_i2c_table);
0977 
0978 /*
0979  * ALC5623 2 wire address is determined by A1 pin
0980  * state during powerup.
0981  *    low  = 0x1a
0982  *    high = 0x1b
0983  */
0984 static int alc5623_i2c_probe(struct i2c_client *client)
0985 {
0986     struct alc5623_platform_data *pdata;
0987     struct alc5623_priv *alc5623;
0988     struct device_node *np;
0989     unsigned int vid1, vid2;
0990     int ret;
0991     u32 val32;
0992     const struct i2c_device_id *id;
0993 
0994     alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),
0995                    GFP_KERNEL);
0996     if (alc5623 == NULL)
0997         return -ENOMEM;
0998 
0999     alc5623->regmap = devm_regmap_init_i2c(client, &alc5623_regmap);
1000     if (IS_ERR(alc5623->regmap)) {
1001         ret = PTR_ERR(alc5623->regmap);
1002         dev_err(&client->dev, "Failed to initialise I/O: %d\n", ret);
1003         return ret;
1004     }
1005 
1006     ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID1, &vid1);
1007     if (ret < 0) {
1008         dev_err(&client->dev, "failed to read vendor ID1: %d\n", ret);
1009         return ret;
1010     }
1011 
1012     ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2);
1013     if (ret < 0) {
1014         dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret);
1015         return ret;
1016     }
1017     vid2 >>= 8;
1018 
1019     id = i2c_match_id(alc5623_i2c_table, client);
1020 
1021     if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) {
1022         dev_err(&client->dev, "unknown or wrong codec\n");
1023         dev_err(&client->dev, "Expected %x:%lx, got %x:%x\n",
1024                 0x10ec, id->driver_data,
1025                 vid1, vid2);
1026         return -ENODEV;
1027     }
1028 
1029     dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2);
1030 
1031     pdata = client->dev.platform_data;
1032     if (pdata) {
1033         alc5623->add_ctrl = pdata->add_ctrl;
1034         alc5623->jack_det_ctrl = pdata->jack_det_ctrl;
1035     } else {
1036         if (client->dev.of_node) {
1037             np = client->dev.of_node;
1038             ret = of_property_read_u32(np, "add-ctrl", &val32);
1039             if (!ret)
1040                 alc5623->add_ctrl = val32;
1041             ret = of_property_read_u32(np, "jack-det-ctrl", &val32);
1042             if (!ret)
1043                 alc5623->jack_det_ctrl = val32;
1044         }
1045     }
1046 
1047     alc5623->id = vid2;
1048     switch (alc5623->id) {
1049     case 0x21:
1050         alc5623_dai.name = "alc5621-hifi";
1051         break;
1052     case 0x22:
1053         alc5623_dai.name = "alc5622-hifi";
1054         break;
1055     case 0x23:
1056         alc5623_dai.name = "alc5623-hifi";
1057         break;
1058     default:
1059         return -EINVAL;
1060     }
1061 
1062     i2c_set_clientdata(client, alc5623);
1063 
1064     ret =  devm_snd_soc_register_component(&client->dev,
1065         &soc_component_device_alc5623, &alc5623_dai, 1);
1066     if (ret != 0)
1067         dev_err(&client->dev, "Failed to register codec: %d\n", ret);
1068 
1069     return ret;
1070 }
1071 
1072 #ifdef CONFIG_OF
1073 static const struct of_device_id alc5623_of_match[] = {
1074     { .compatible = "realtek,alc5623", },
1075     { }
1076 };
1077 MODULE_DEVICE_TABLE(of, alc5623_of_match);
1078 #endif
1079 
1080 /*  i2c codec control layer */
1081 static struct i2c_driver alc5623_i2c_driver = {
1082     .driver = {
1083         .name = "alc562x-codec",
1084         .of_match_table = of_match_ptr(alc5623_of_match),
1085     },
1086     .probe_new = alc5623_i2c_probe,
1087     .id_table = alc5623_i2c_table,
1088 };
1089 
1090 module_i2c_driver(alc5623_i2c_driver);
1091 
1092 MODULE_DESCRIPTION("ASoC alc5621/2/3 driver");
1093 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
1094 MODULE_LICENSE("GPL");