brintos

brintos / linux-shallow public Read only

0
0
Text · 33.6 KiB · b24c322 Raw
1095 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * alc5623.c  --  alc562[123] ALSA Soc Audio driver4 *5 * Copyright 2008 Realtek Microelectronics6 * Author: flove <flove@realtek.com> Ethan <eku@marvell.com>7 *8 * Copyright 2010 Arnaud Patard <arnaud.patard@rtp-net.org>9 *10 * Based on WM8753.c11 */12 13#include <linux/module.h>14#include <linux/kernel.h>15#include <linux/init.h>16#include <linux/delay.h>17#include <linux/pm.h>18#include <linux/i2c.h>19#include <linux/regmap.h>20#include <linux/slab.h>21#include <linux/of.h>22#include <sound/core.h>23#include <sound/pcm.h>24#include <sound/pcm_params.h>25#include <sound/tlv.h>26#include <sound/soc.h>27#include <sound/initval.h>28#include <sound/alc5623.h>29 30#include "alc5623.h"31 32static int caps_charge = 2000;33module_param(caps_charge, int, 0);34MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)");35 36/* codec private data */37struct alc5623_priv {38	struct regmap *regmap;39	u8 id;40	unsigned int sysclk;41	unsigned int add_ctrl;42	unsigned int jack_det_ctrl;43};44 45static inline int alc5623_reset(struct snd_soc_component *component)46{47	return snd_soc_component_write(component, ALC5623_RESET, 0);48}49 50static int amp_mixer_event(struct snd_soc_dapm_widget *w,51	struct snd_kcontrol *kcontrol, int event)52{53	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);54 55	/* to power-on/off class-d amp generators/speaker */56	/* need to write to 'index-46h' register :        */57	/* so write index num (here 0x46) to reg 0x6a     */58	/* and then 0xffff/0 to reg 0x6c                  */59	snd_soc_component_write(component, ALC5623_HID_CTRL_INDEX, 0x46);60 61	switch (event) {62	case SND_SOC_DAPM_PRE_PMU:63		snd_soc_component_write(component, ALC5623_HID_CTRL_DATA, 0xFFFF);64		break;65	case SND_SOC_DAPM_POST_PMD:66		snd_soc_component_write(component, ALC5623_HID_CTRL_DATA, 0);67		break;68	}69 70	return 0;71}72 73/*74 * ALC5623 Controls75 */76 77static const DECLARE_TLV_DB_SCALE(vol_tlv, -3450, 150, 0);78static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0);79static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0);80static const DECLARE_TLV_DB_RANGE(boost_tlv,81	0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),82	1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),83	2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0)84);85static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0);86 87static const struct snd_kcontrol_new alc5621_vol_snd_controls[] = {88	SOC_DOUBLE_TLV("Speaker Playback Volume",89			ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),90	SOC_DOUBLE("Speaker Playback Switch",91			ALC5623_SPK_OUT_VOL, 15, 7, 1, 1),92	SOC_DOUBLE_TLV("Headphone Playback Volume",93			ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),94	SOC_DOUBLE("Headphone Playback Switch",95			ALC5623_HP_OUT_VOL, 15, 7, 1, 1),96};97 98static const struct snd_kcontrol_new alc5622_vol_snd_controls[] = {99	SOC_DOUBLE_TLV("Speaker Playback Volume",100			ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),101	SOC_DOUBLE("Speaker Playback Switch",102			ALC5623_SPK_OUT_VOL, 15, 7, 1, 1),103	SOC_DOUBLE_TLV("Line Playback Volume",104			ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),105	SOC_DOUBLE("Line Playback Switch",106			ALC5623_HP_OUT_VOL, 15, 7, 1, 1),107};108 109static const struct snd_kcontrol_new alc5623_vol_snd_controls[] = {110	SOC_DOUBLE_TLV("Line Playback Volume",111			ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),112	SOC_DOUBLE("Line Playback Switch",113			ALC5623_SPK_OUT_VOL, 15, 7, 1, 1),114	SOC_DOUBLE_TLV("Headphone Playback Volume",115			ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),116	SOC_DOUBLE("Headphone Playback Switch",117			ALC5623_HP_OUT_VOL, 15, 7, 1, 1),118};119 120static const struct snd_kcontrol_new alc5623_snd_controls[] = {121	SOC_DOUBLE_TLV("Auxout Playback Volume",122			ALC5623_MONO_AUX_OUT_VOL, 8, 0, 31, 1, hp_tlv),123	SOC_DOUBLE("Auxout Playback Switch",124			ALC5623_MONO_AUX_OUT_VOL, 15, 7, 1, 1),125	SOC_DOUBLE_TLV("PCM Playback Volume",126			ALC5623_STEREO_DAC_VOL, 8, 0, 31, 1, vol_tlv),127	SOC_DOUBLE_TLV("AuxI Capture Volume",128			ALC5623_AUXIN_VOL, 8, 0, 31, 1, vol_tlv),129	SOC_DOUBLE_TLV("LineIn Capture Volume",130			ALC5623_LINE_IN_VOL, 8, 0, 31, 1, vol_tlv),131	SOC_SINGLE_TLV("Mic1 Capture Volume",132			ALC5623_MIC_VOL, 8, 31, 1, vol_tlv),133	SOC_SINGLE_TLV("Mic2 Capture Volume",134			ALC5623_MIC_VOL, 0, 31, 1, vol_tlv),135	SOC_DOUBLE_TLV("Rec Capture Volume",136			ALC5623_ADC_REC_GAIN, 7, 0, 31, 0, adc_rec_tlv),137	SOC_SINGLE_TLV("Mic 1 Boost Volume",138			ALC5623_MIC_CTRL, 10, 2, 0, boost_tlv),139	SOC_SINGLE_TLV("Mic 2 Boost Volume",140			ALC5623_MIC_CTRL, 8, 2, 0, boost_tlv),141	SOC_SINGLE_TLV("Digital Boost Volume",142			ALC5623_ADD_CTRL_REG, 4, 3, 0, dig_tlv),143};144 145/*146 * DAPM Controls147 */148static const struct snd_kcontrol_new alc5623_hp_mixer_controls[] = {149SOC_DAPM_SINGLE("LI2HP Playback Switch", ALC5623_LINE_IN_VOL, 15, 1, 1),150SOC_DAPM_SINGLE("AUXI2HP Playback Switch", ALC5623_AUXIN_VOL, 15, 1, 1),151SOC_DAPM_SINGLE("MIC12HP Playback Switch", ALC5623_MIC_ROUTING_CTRL, 15, 1, 1),152SOC_DAPM_SINGLE("MIC22HP Playback Switch", ALC5623_MIC_ROUTING_CTRL, 7, 1, 1),153SOC_DAPM_SINGLE("DAC2HP Playback Switch", ALC5623_STEREO_DAC_VOL, 15, 1, 1),154};155 156static const struct snd_kcontrol_new alc5623_hpl_mixer_controls[] = {157SOC_DAPM_SINGLE("ADC2HP_L Playback Switch", ALC5623_ADC_REC_GAIN, 15, 1, 1),158};159 160static const struct snd_kcontrol_new alc5623_hpr_mixer_controls[] = {161SOC_DAPM_SINGLE("ADC2HP_R Playback Switch", ALC5623_ADC_REC_GAIN, 14, 1, 1),162};163 164static const struct snd_kcontrol_new alc5623_mono_mixer_controls[] = {165SOC_DAPM_SINGLE("ADC2MONO_L Playback Switch", ALC5623_ADC_REC_GAIN, 13, 1, 1),166SOC_DAPM_SINGLE("ADC2MONO_R Playback Switch", ALC5623_ADC_REC_GAIN, 12, 1, 1),167SOC_DAPM_SINGLE("LI2MONO Playback Switch", ALC5623_LINE_IN_VOL, 13, 1, 1),168SOC_DAPM_SINGLE("AUXI2MONO Playback Switch", ALC5623_AUXIN_VOL, 13, 1, 1),169SOC_DAPM_SINGLE("MIC12MONO Playback Switch", ALC5623_MIC_ROUTING_CTRL, 13, 1, 1),170SOC_DAPM_SINGLE("MIC22MONO Playback Switch", ALC5623_MIC_ROUTING_CTRL, 5, 1, 1),171SOC_DAPM_SINGLE("DAC2MONO Playback Switch", ALC5623_STEREO_DAC_VOL, 13, 1, 1),172};173 174static const struct snd_kcontrol_new alc5623_speaker_mixer_controls[] = {175SOC_DAPM_SINGLE("LI2SPK Playback Switch", ALC5623_LINE_IN_VOL, 14, 1, 1),176SOC_DAPM_SINGLE("AUXI2SPK Playback Switch", ALC5623_AUXIN_VOL, 14, 1, 1),177SOC_DAPM_SINGLE("MIC12SPK Playback Switch", ALC5623_MIC_ROUTING_CTRL, 14, 1, 1),178SOC_DAPM_SINGLE("MIC22SPK Playback Switch", ALC5623_MIC_ROUTING_CTRL, 6, 1, 1),179SOC_DAPM_SINGLE("DAC2SPK Playback Switch", ALC5623_STEREO_DAC_VOL, 14, 1, 1),180};181 182/* Left Record Mixer */183static const struct snd_kcontrol_new alc5623_captureL_mixer_controls[] = {184SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5623_ADC_REC_MIXER, 14, 1, 1),185SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5623_ADC_REC_MIXER, 13, 1, 1),186SOC_DAPM_SINGLE("LineInL Capture Switch", ALC5623_ADC_REC_MIXER, 12, 1, 1),187SOC_DAPM_SINGLE("Left AuxI Capture Switch", ALC5623_ADC_REC_MIXER, 11, 1, 1),188SOC_DAPM_SINGLE("HPMixerL Capture Switch", ALC5623_ADC_REC_MIXER, 10, 1, 1),189SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5623_ADC_REC_MIXER, 9, 1, 1),190SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5623_ADC_REC_MIXER, 8, 1, 1),191};192 193/* Right Record Mixer */194static const struct snd_kcontrol_new alc5623_captureR_mixer_controls[] = {195SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5623_ADC_REC_MIXER, 6, 1, 1),196SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5623_ADC_REC_MIXER, 5, 1, 1),197SOC_DAPM_SINGLE("LineInR Capture Switch", ALC5623_ADC_REC_MIXER, 4, 1, 1),198SOC_DAPM_SINGLE("Right AuxI Capture Switch", ALC5623_ADC_REC_MIXER, 3, 1, 1),199SOC_DAPM_SINGLE("HPMixerR Capture Switch", ALC5623_ADC_REC_MIXER, 2, 1, 1),200SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5623_ADC_REC_MIXER, 1, 1, 1),201SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5623_ADC_REC_MIXER, 0, 1, 1),202};203 204static const char *alc5623_spk_n_sour_sel[] = {205		"RN/-R", "RP/+R", "LN/-R", "Vmid" };206static const char *alc5623_hpl_out_input_sel[] = {207		"Vmid", "HP Left Mix"};208static const char *alc5623_hpr_out_input_sel[] = {209		"Vmid", "HP Right Mix"};210static const char *alc5623_spkout_input_sel[] = {211		"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};212static const char *alc5623_aux_out_input_sel[] = {213		"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};214 215/* auxout output mux */216static SOC_ENUM_SINGLE_DECL(alc5623_aux_out_input_enum,217			    ALC5623_OUTPUT_MIXER_CTRL, 6,218			    alc5623_aux_out_input_sel);219static const struct snd_kcontrol_new alc5623_auxout_mux_controls =220SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum);221 222/* speaker output mux */223static SOC_ENUM_SINGLE_DECL(alc5623_spkout_input_enum,224			    ALC5623_OUTPUT_MIXER_CTRL, 10,225			    alc5623_spkout_input_sel);226static const struct snd_kcontrol_new alc5623_spkout_mux_controls =227SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum);228 229/* headphone left output mux */230static SOC_ENUM_SINGLE_DECL(alc5623_hpl_out_input_enum,231			    ALC5623_OUTPUT_MIXER_CTRL, 9,232			    alc5623_hpl_out_input_sel);233static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls =234SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum);235 236/* headphone right output mux */237static SOC_ENUM_SINGLE_DECL(alc5623_hpr_out_input_enum,238			    ALC5623_OUTPUT_MIXER_CTRL, 8,239			    alc5623_hpr_out_input_sel);240static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls =241SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum);242 243/* speaker output N select */244static SOC_ENUM_SINGLE_DECL(alc5623_spk_n_sour_enum,245			    ALC5623_OUTPUT_MIXER_CTRL, 14,246			    alc5623_spk_n_sour_sel);247static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls =248SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum);249 250static const struct snd_soc_dapm_widget alc5623_dapm_widgets[] = {251/* Muxes */252SND_SOC_DAPM_MUX("AuxOut Mux", SND_SOC_NOPM, 0, 0,253	&alc5623_auxout_mux_controls),254SND_SOC_DAPM_MUX("SpeakerOut Mux", SND_SOC_NOPM, 0, 0,255	&alc5623_spkout_mux_controls),256SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0,257	&alc5623_hpl_out_mux_controls),258SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,259	&alc5623_hpr_out_mux_controls),260SND_SOC_DAPM_MUX("SpeakerOut N Mux", SND_SOC_NOPM, 0, 0,261	&alc5623_spkoutn_mux_controls),262 263/* output mixers */264SND_SOC_DAPM_MIXER("HP Mix", SND_SOC_NOPM, 0, 0,265	&alc5623_hp_mixer_controls[0],266	ARRAY_SIZE(alc5623_hp_mixer_controls)),267SND_SOC_DAPM_MIXER("HPR Mix", ALC5623_PWR_MANAG_ADD2, 4, 0,268	&alc5623_hpr_mixer_controls[0],269	ARRAY_SIZE(alc5623_hpr_mixer_controls)),270SND_SOC_DAPM_MIXER("HPL Mix", ALC5623_PWR_MANAG_ADD2, 5, 0,271	&alc5623_hpl_mixer_controls[0],272	ARRAY_SIZE(alc5623_hpl_mixer_controls)),273SND_SOC_DAPM_MIXER("HPOut Mix", SND_SOC_NOPM, 0, 0, NULL, 0),274SND_SOC_DAPM_MIXER("Mono Mix", ALC5623_PWR_MANAG_ADD2, 2, 0,275	&alc5623_mono_mixer_controls[0],276	ARRAY_SIZE(alc5623_mono_mixer_controls)),277SND_SOC_DAPM_MIXER("Speaker Mix", ALC5623_PWR_MANAG_ADD2, 3, 0,278	&alc5623_speaker_mixer_controls[0],279	ARRAY_SIZE(alc5623_speaker_mixer_controls)),280 281/* input mixers */282SND_SOC_DAPM_MIXER("Left Capture Mix", ALC5623_PWR_MANAG_ADD2, 1, 0,283	&alc5623_captureL_mixer_controls[0],284	ARRAY_SIZE(alc5623_captureL_mixer_controls)),285SND_SOC_DAPM_MIXER("Right Capture Mix", ALC5623_PWR_MANAG_ADD2, 0, 0,286	&alc5623_captureR_mixer_controls[0],287	ARRAY_SIZE(alc5623_captureR_mixer_controls)),288 289SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback",290	ALC5623_PWR_MANAG_ADD2, 9, 0),291SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback",292	ALC5623_PWR_MANAG_ADD2, 8, 0),293SND_SOC_DAPM_MIXER("I2S Mix", ALC5623_PWR_MANAG_ADD1, 15, 0, NULL, 0),294SND_SOC_DAPM_MIXER("AuxI Mix", SND_SOC_NOPM, 0, 0, NULL, 0),295SND_SOC_DAPM_MIXER("Line Mix", SND_SOC_NOPM, 0, 0, NULL, 0),296SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture",297	ALC5623_PWR_MANAG_ADD2, 7, 0),298SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture",299	ALC5623_PWR_MANAG_ADD2, 6, 0),300SND_SOC_DAPM_PGA("Left Headphone", ALC5623_PWR_MANAG_ADD3, 10, 0, NULL, 0),301SND_SOC_DAPM_PGA("Right Headphone", ALC5623_PWR_MANAG_ADD3, 9, 0, NULL, 0),302SND_SOC_DAPM_PGA("SpeakerOut", ALC5623_PWR_MANAG_ADD3, 12, 0, NULL, 0),303SND_SOC_DAPM_PGA("Left AuxOut", ALC5623_PWR_MANAG_ADD3, 14, 0, NULL, 0),304SND_SOC_DAPM_PGA("Right AuxOut", ALC5623_PWR_MANAG_ADD3, 13, 0, NULL, 0),305SND_SOC_DAPM_PGA("Left LineIn", ALC5623_PWR_MANAG_ADD3, 7, 0, NULL, 0),306SND_SOC_DAPM_PGA("Right LineIn", ALC5623_PWR_MANAG_ADD3, 6, 0, NULL, 0),307SND_SOC_DAPM_PGA("Left AuxI", ALC5623_PWR_MANAG_ADD3, 5, 0, NULL, 0),308SND_SOC_DAPM_PGA("Right AuxI", ALC5623_PWR_MANAG_ADD3, 4, 0, NULL, 0),309SND_SOC_DAPM_PGA("MIC1 PGA", ALC5623_PWR_MANAG_ADD3, 3, 0, NULL, 0),310SND_SOC_DAPM_PGA("MIC2 PGA", ALC5623_PWR_MANAG_ADD3, 2, 0, NULL, 0),311SND_SOC_DAPM_PGA("MIC1 Pre Amp", ALC5623_PWR_MANAG_ADD3, 1, 0, NULL, 0),312SND_SOC_DAPM_PGA("MIC2 Pre Amp", ALC5623_PWR_MANAG_ADD3, 0, 0, NULL, 0),313SND_SOC_DAPM_MICBIAS("Mic Bias1", ALC5623_PWR_MANAG_ADD1, 11, 0),314 315SND_SOC_DAPM_OUTPUT("AUXOUTL"),316SND_SOC_DAPM_OUTPUT("AUXOUTR"),317SND_SOC_DAPM_OUTPUT("HPL"),318SND_SOC_DAPM_OUTPUT("HPR"),319SND_SOC_DAPM_OUTPUT("SPKOUT"),320SND_SOC_DAPM_OUTPUT("SPKOUTN"),321SND_SOC_DAPM_INPUT("LINEINL"),322SND_SOC_DAPM_INPUT("LINEINR"),323SND_SOC_DAPM_INPUT("AUXINL"),324SND_SOC_DAPM_INPUT("AUXINR"),325SND_SOC_DAPM_INPUT("MIC1"),326SND_SOC_DAPM_INPUT("MIC2"),327SND_SOC_DAPM_VMID("Vmid"),328};329 330static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"};331static SOC_ENUM_SINGLE_DECL(alc5623_amp_enum,332			    ALC5623_OUTPUT_MIXER_CTRL, 13,333			    alc5623_amp_names);334static const struct snd_kcontrol_new alc5623_amp_mux_controls =335	SOC_DAPM_ENUM("Route", alc5623_amp_enum);336 337static const struct snd_soc_dapm_widget alc5623_dapm_amp_widgets[] = {338SND_SOC_DAPM_PGA_E("D Amp", ALC5623_PWR_MANAG_ADD2, 14, 0, NULL, 0,339	amp_mixer_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),340SND_SOC_DAPM_PGA("AB Amp", ALC5623_PWR_MANAG_ADD2, 15, 0, NULL, 0),341SND_SOC_DAPM_MUX("AB-D Amp Mux", SND_SOC_NOPM, 0, 0,342	&alc5623_amp_mux_controls),343};344 345static const struct snd_soc_dapm_route intercon[] = {346	/* virtual mixer - mixes left & right channels */347	{"I2S Mix", NULL,				"Left DAC"},348	{"I2S Mix", NULL,				"Right DAC"},349	{"Line Mix", NULL,				"Right LineIn"},350	{"Line Mix", NULL,				"Left LineIn"},351	{"AuxI Mix", NULL,				"Left AuxI"},352	{"AuxI Mix", NULL,				"Right AuxI"},353	{"AUXOUTL", NULL,				"Left AuxOut"},354	{"AUXOUTR", NULL,				"Right AuxOut"},355 356	/* HP mixer */357	{"HPL Mix", "ADC2HP_L Playback Switch",		"Left Capture Mix"},358	{"HPL Mix", NULL,				"HP Mix"},359	{"HPR Mix", "ADC2HP_R Playback Switch",		"Right Capture Mix"},360	{"HPR Mix", NULL,				"HP Mix"},361	{"HP Mix", "LI2HP Playback Switch",		"Line Mix"},362	{"HP Mix", "AUXI2HP Playback Switch",		"AuxI Mix"},363	{"HP Mix", "MIC12HP Playback Switch",		"MIC1 PGA"},364	{"HP Mix", "MIC22HP Playback Switch",		"MIC2 PGA"},365	{"HP Mix", "DAC2HP Playback Switch",		"I2S Mix"},366 367	/* speaker mixer */368	{"Speaker Mix", "LI2SPK Playback Switch",	"Line Mix"},369	{"Speaker Mix", "AUXI2SPK Playback Switch",	"AuxI Mix"},370	{"Speaker Mix", "MIC12SPK Playback Switch",	"MIC1 PGA"},371	{"Speaker Mix", "MIC22SPK Playback Switch",	"MIC2 PGA"},372	{"Speaker Mix", "DAC2SPK Playback Switch",	"I2S Mix"},373 374	/* mono mixer */375	{"Mono Mix", "ADC2MONO_L Playback Switch",	"Left Capture Mix"},376	{"Mono Mix", "ADC2MONO_R Playback Switch",	"Right Capture Mix"},377	{"Mono Mix", "LI2MONO Playback Switch",		"Line Mix"},378	{"Mono Mix", "AUXI2MONO Playback Switch",	"AuxI Mix"},379	{"Mono Mix", "MIC12MONO Playback Switch",	"MIC1 PGA"},380	{"Mono Mix", "MIC22MONO Playback Switch",	"MIC2 PGA"},381	{"Mono Mix", "DAC2MONO Playback Switch",	"I2S Mix"},382 383	/* Left record mixer */384	{"Left Capture Mix", "LineInL Capture Switch",	"LINEINL"},385	{"Left Capture Mix", "Left AuxI Capture Switch", "AUXINL"},386	{"Left Capture Mix", "Mic1 Capture Switch",	"MIC1 Pre Amp"},387	{"Left Capture Mix", "Mic2 Capture Switch",	"MIC2 Pre Amp"},388	{"Left Capture Mix", "HPMixerL Capture Switch", "HPL Mix"},389	{"Left Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},390	{"Left Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},391 392	/*Right record mixer */393	{"Right Capture Mix", "LineInR Capture Switch",	"LINEINR"},394	{"Right Capture Mix", "Right AuxI Capture Switch",	"AUXINR"},395	{"Right Capture Mix", "Mic1 Capture Switch",	"MIC1 Pre Amp"},396	{"Right Capture Mix", "Mic2 Capture Switch",	"MIC2 Pre Amp"},397	{"Right Capture Mix", "HPMixerR Capture Switch", "HPR Mix"},398	{"Right Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},399	{"Right Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},400 401	/* headphone left mux */402	{"Left Headphone Mux", "HP Left Mix",		"HPL Mix"},403	{"Left Headphone Mux", "Vmid",			"Vmid"},404 405	/* headphone right mux */406	{"Right Headphone Mux", "HP Right Mix",		"HPR Mix"},407	{"Right Headphone Mux", "Vmid",			"Vmid"},408 409	/* speaker out mux */410	{"SpeakerOut Mux", "Vmid",			"Vmid"},411	{"SpeakerOut Mux", "HPOut Mix",			"HPOut Mix"},412	{"SpeakerOut Mux", "Speaker Mix",		"Speaker Mix"},413	{"SpeakerOut Mux", "Mono Mix",			"Mono Mix"},414 415	/* Mono/Aux Out mux */416	{"AuxOut Mux", "Vmid",				"Vmid"},417	{"AuxOut Mux", "HPOut Mix",			"HPOut Mix"},418	{"AuxOut Mux", "Speaker Mix",			"Speaker Mix"},419	{"AuxOut Mux", "Mono Mix",			"Mono Mix"},420 421	/* output pga */422	{"HPL", NULL,					"Left Headphone"},423	{"Left Headphone", NULL,			"Left Headphone Mux"},424	{"HPR", NULL,					"Right Headphone"},425	{"Right Headphone", NULL,			"Right Headphone Mux"},426	{"Left AuxOut", NULL,				"AuxOut Mux"},427	{"Right AuxOut", NULL,				"AuxOut Mux"},428 429	/* input pga */430	{"Left LineIn", NULL,				"LINEINL"},431	{"Right LineIn", NULL,				"LINEINR"},432	{"Left AuxI", NULL,				"AUXINL"},433	{"Right AuxI", NULL,				"AUXINR"},434	{"MIC1 Pre Amp", NULL,				"MIC1"},435	{"MIC2 Pre Amp", NULL,				"MIC2"},436	{"MIC1 PGA", NULL,				"MIC1 Pre Amp"},437	{"MIC2 PGA", NULL,				"MIC2 Pre Amp"},438 439	/* left ADC */440	{"Left ADC", NULL,				"Left Capture Mix"},441 442	/* right ADC */443	{"Right ADC", NULL,				"Right Capture Mix"},444 445	{"SpeakerOut N Mux", "RN/-R",			"SpeakerOut"},446	{"SpeakerOut N Mux", "RP/+R",			"SpeakerOut"},447	{"SpeakerOut N Mux", "LN/-R",			"SpeakerOut"},448	{"SpeakerOut N Mux", "Vmid",			"Vmid"},449 450	{"SPKOUT", NULL,				"SpeakerOut"},451	{"SPKOUTN", NULL,				"SpeakerOut N Mux"},452};453 454static const struct snd_soc_dapm_route intercon_spk[] = {455	{"SpeakerOut", NULL,				"SpeakerOut Mux"},456};457 458static const struct snd_soc_dapm_route intercon_amp_spk[] = {459	{"AB Amp", NULL,				"SpeakerOut Mux"},460	{"D Amp", NULL,					"SpeakerOut Mux"},461	{"AB-D Amp Mux", "AB Amp",			"AB Amp"},462	{"AB-D Amp Mux", "D Amp",			"D Amp"},463	{"SpeakerOut", NULL,				"AB-D Amp Mux"},464};465 466/* PLL divisors */467struct _pll_div {468	u32 pll_in;469	u32 pll_out;470	u16 regvalue;471};472 473/* Note : pll code from original alc5623 driver. Not sure of how good it is */474/* useful only for master mode */475static const struct _pll_div codec_master_pll_div[] = {476 477	{  2048000,  8192000,	0x0ea0},478	{  3686400,  8192000,	0x4e27},479	{ 12000000,  8192000,	0x456b},480	{ 13000000,  8192000,	0x495f},481	{ 13100000,  8192000,	0x0320},482	{  2048000,  11289600,	0xf637},483	{  3686400,  11289600,	0x2f22},484	{ 12000000,  11289600,	0x3e2f},485	{ 13000000,  11289600,	0x4d5b},486	{ 13100000,  11289600,	0x363b},487	{  2048000,  16384000,	0x1ea0},488	{  3686400,  16384000,	0x9e27},489	{ 12000000,  16384000,	0x452b},490	{ 13000000,  16384000,	0x542f},491	{ 13100000,  16384000,	0x03a0},492	{  2048000,  16934400,	0xe625},493	{  3686400,  16934400,	0x9126},494	{ 12000000,  16934400,	0x4d2c},495	{ 13000000,  16934400,	0x742f},496	{ 13100000,  16934400,	0x3c27},497	{  2048000,  22579200,	0x2aa0},498	{  3686400,  22579200,	0x2f20},499	{ 12000000,  22579200,	0x7e2f},500	{ 13000000,  22579200,	0x742f},501	{ 13100000,  22579200,	0x3c27},502	{  2048000,  24576000,	0x2ea0},503	{  3686400,  24576000,	0xee27},504	{ 12000000,  24576000,	0x2915},505	{ 13000000,  24576000,	0x772e},506	{ 13100000,  24576000,	0x0d20},507};508 509static const struct _pll_div codec_slave_pll_div[] = {510 511	{  1024000,  16384000,  0x3ea0},512	{  1411200,  22579200,	0x3ea0},513	{  1536000,  24576000,	0x3ea0},514	{  2048000,  16384000,  0x1ea0},515	{  2822400,  22579200,	0x1ea0},516	{  3072000,  24576000,	0x1ea0},517 518};519 520static int alc5623_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,521		int source, unsigned int freq_in, unsigned int freq_out)522{523	int i;524	struct snd_soc_component *component = codec_dai->component;525	int gbl_clk = 0, pll_div = 0;526	u16 reg;527 528	if (pll_id < ALC5623_PLL_FR_MCLK || pll_id > ALC5623_PLL_FR_BCK)529		return -ENODEV;530 531	/* Disable PLL power */532	snd_soc_component_update_bits(component, ALC5623_PWR_MANAG_ADD2,533				ALC5623_PWR_ADD2_PLL,534				0);535 536	/* pll is not used in slave mode */537	reg = snd_soc_component_read(component, ALC5623_DAI_CONTROL);538	if (reg & ALC5623_DAI_SDP_SLAVE_MODE)539		return 0;540 541	if (!freq_in || !freq_out)542		return 0;543 544	switch (pll_id) {545	case ALC5623_PLL_FR_MCLK:546		for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++) {547			if (codec_master_pll_div[i].pll_in == freq_in548			   && codec_master_pll_div[i].pll_out == freq_out) {549				/* PLL source from MCLK */550				pll_div  = codec_master_pll_div[i].regvalue;551				break;552			}553		}554		break;555	case ALC5623_PLL_FR_BCK:556		for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) {557			if (codec_slave_pll_div[i].pll_in == freq_in558			   && codec_slave_pll_div[i].pll_out == freq_out) {559				/* PLL source from Bitclk */560				gbl_clk = ALC5623_GBL_CLK_PLL_SOUR_SEL_BITCLK;561				pll_div = codec_slave_pll_div[i].regvalue;562				break;563			}564		}565		break;566	default:567		return -EINVAL;568	}569 570	if (!pll_div)571		return -EINVAL;572 573	snd_soc_component_write(component, ALC5623_GLOBAL_CLK_CTRL_REG, gbl_clk);574	snd_soc_component_write(component, ALC5623_PLL_CTRL, pll_div);575	snd_soc_component_update_bits(component, ALC5623_PWR_MANAG_ADD2,576				ALC5623_PWR_ADD2_PLL,577				ALC5623_PWR_ADD2_PLL);578	gbl_clk |= ALC5623_GBL_CLK_SYS_SOUR_SEL_PLL;579	snd_soc_component_write(component, ALC5623_GLOBAL_CLK_CTRL_REG, gbl_clk);580 581	return 0;582}583 584struct _coeff_div {585	u16 fs;586	u16 regvalue;587};588 589/* codec hifi mclk (after PLL) clock divider coefficients */590/* values inspired from column BCLK=32Fs of Appendix A table */591static const struct _coeff_div coeff_div[] = {592	{256*8, 0x3a69},593	{384*8, 0x3c6b},594	{256*4, 0x2a69},595	{384*4, 0x2c6b},596	{256*2, 0x1a69},597	{384*2, 0x1c6b},598	{256*1, 0x0a69},599	{384*1, 0x0c6b},600};601 602static int get_coeff(struct snd_soc_component *component, int rate)603{604	struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component);605	int i;606 607	for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {608		if (coeff_div[i].fs * rate == alc5623->sysclk)609			return i;610	}611	return -EINVAL;612}613 614/*615 * Clock after PLL and dividers616 */617static int alc5623_set_dai_sysclk(struct snd_soc_dai *codec_dai,618		int clk_id, unsigned int freq, int dir)619{620	struct snd_soc_component *component = codec_dai->component;621	struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component);622 623	switch (freq) {624	case  8192000:625	case 11289600:626	case 12288000:627	case 16384000:628	case 16934400:629	case 18432000:630	case 22579200:631	case 24576000:632		alc5623->sysclk = freq;633		return 0;634	}635	return -EINVAL;636}637 638static int alc5623_set_dai_fmt(struct snd_soc_dai *codec_dai,639		unsigned int fmt)640{641	struct snd_soc_component *component = codec_dai->component;642	u16 iface = 0;643 644	/* set audio interface clocking */645	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {646	case SND_SOC_DAIFMT_CBP_CFP:647		iface = ALC5623_DAI_SDP_MASTER_MODE;648		break;649	case SND_SOC_DAIFMT_CBC_CFC:650		iface = ALC5623_DAI_SDP_SLAVE_MODE;651		break;652	default:653		return -EINVAL;654	}655 656	/* interface format */657	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {658	case SND_SOC_DAIFMT_I2S:659		iface |= ALC5623_DAI_I2S_DF_I2S;660		break;661	case SND_SOC_DAIFMT_RIGHT_J:662		iface |= ALC5623_DAI_I2S_DF_RIGHT;663		break;664	case SND_SOC_DAIFMT_LEFT_J:665		iface |= ALC5623_DAI_I2S_DF_LEFT;666		break;667	case SND_SOC_DAIFMT_DSP_A:668		iface |= ALC5623_DAI_I2S_DF_PCM;669		break;670	case SND_SOC_DAIFMT_DSP_B:671		iface |= ALC5623_DAI_I2S_DF_PCM | ALC5623_DAI_I2S_PCM_MODE;672		break;673	default:674		return -EINVAL;675	}676 677	/* clock inversion */678	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {679	case SND_SOC_DAIFMT_NB_NF:680		break;681	case SND_SOC_DAIFMT_IB_IF:682		iface |= ALC5623_DAI_MAIN_I2S_BCLK_POL_CTRL;683		break;684	case SND_SOC_DAIFMT_IB_NF:685		iface |= ALC5623_DAI_MAIN_I2S_BCLK_POL_CTRL;686		break;687	case SND_SOC_DAIFMT_NB_IF:688		break;689	default:690		return -EINVAL;691	}692 693	return snd_soc_component_write(component, ALC5623_DAI_CONTROL, iface);694}695 696static int alc5623_pcm_hw_params(struct snd_pcm_substream *substream,697		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)698{699	struct snd_soc_component *component = dai->component;700	struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component);701	int coeff, rate;702	u16 iface;703 704	iface = snd_soc_component_read(component, ALC5623_DAI_CONTROL);705	iface &= ~ALC5623_DAI_I2S_DL_MASK;706 707	/* bit size */708	switch (params_width(params)) {709	case 16:710		iface |= ALC5623_DAI_I2S_DL_16;711		break;712	case 20:713		iface |= ALC5623_DAI_I2S_DL_20;714		break;715	case 24:716		iface |= ALC5623_DAI_I2S_DL_24;717		break;718	case 32:719		iface |= ALC5623_DAI_I2S_DL_32;720		break;721	default:722		return -EINVAL;723	}724 725	/* set iface & srate */726	snd_soc_component_write(component, ALC5623_DAI_CONTROL, iface);727	rate = params_rate(params);728	coeff = get_coeff(component, rate);729	if (coeff < 0)730		return -EINVAL;731 732	coeff = coeff_div[coeff].regvalue;733	dev_dbg(component->dev, "%s: sysclk=%d,rate=%d,coeff=0x%04x\n",734		__func__, alc5623->sysclk, rate, coeff);735	snd_soc_component_write(component, ALC5623_STEREO_AD_DA_CLK_CTRL, coeff);736 737	return 0;738}739 740static int alc5623_mute(struct snd_soc_dai *dai, int mute, int direction)741{742	struct snd_soc_component *component = dai->component;743	u16 hp_mute = ALC5623_MISC_M_DAC_L_INPUT | ALC5623_MISC_M_DAC_R_INPUT;744	u16 mute_reg = snd_soc_component_read(component, ALC5623_MISC_CTRL) & ~hp_mute;745 746	if (mute)747		mute_reg |= hp_mute;748 749	return snd_soc_component_write(component, ALC5623_MISC_CTRL, mute_reg);750}751 752#define ALC5623_ADD2_POWER_EN (ALC5623_PWR_ADD2_VREF \753	| ALC5623_PWR_ADD2_DAC_REF_CIR)754 755#define ALC5623_ADD3_POWER_EN (ALC5623_PWR_ADD3_MAIN_BIAS \756	| ALC5623_PWR_ADD3_MIC1_BOOST_AD)757 758#define ALC5623_ADD1_POWER_EN \759	(ALC5623_PWR_ADD1_SHORT_CURR_DET_EN | ALC5623_PWR_ADD1_SOFTGEN_EN \760	| ALC5623_PWR_ADD1_DEPOP_BUF_HP | ALC5623_PWR_ADD1_HP_OUT_AMP \761	| ALC5623_PWR_ADD1_HP_OUT_ENH_AMP)762 763#define ALC5623_ADD1_POWER_EN_5622 \764	(ALC5623_PWR_ADD1_SHORT_CURR_DET_EN \765	| ALC5623_PWR_ADD1_HP_OUT_AMP)766 767static void enable_power_depop(struct snd_soc_component *component)768{769	struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component);770 771	snd_soc_component_update_bits(component, ALC5623_PWR_MANAG_ADD1,772				ALC5623_PWR_ADD1_SOFTGEN_EN,773				ALC5623_PWR_ADD1_SOFTGEN_EN);774 775	snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD3, ALC5623_ADD3_POWER_EN);776 777	snd_soc_component_update_bits(component, ALC5623_MISC_CTRL,778				ALC5623_MISC_HP_DEPOP_MODE2_EN,779				ALC5623_MISC_HP_DEPOP_MODE2_EN);780 781	msleep(500);782 783	snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD2, ALC5623_ADD2_POWER_EN);784 785	/* avoid writing '1' into 5622 reserved bits */786	if (alc5623->id == 0x22)787		snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD1,788			ALC5623_ADD1_POWER_EN_5622);789	else790		snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD1,791			ALC5623_ADD1_POWER_EN);792 793	/* disable HP Depop2 */794	snd_soc_component_update_bits(component, ALC5623_MISC_CTRL,795				ALC5623_MISC_HP_DEPOP_MODE2_EN,796				0);797 798}799 800static int alc5623_set_bias_level(struct snd_soc_component *component,801				      enum snd_soc_bias_level level)802{803	switch (level) {804	case SND_SOC_BIAS_ON:805		enable_power_depop(component);806		break;807	case SND_SOC_BIAS_PREPARE:808		break;809	case SND_SOC_BIAS_STANDBY:810		/* everything off except vref/vmid, */811		snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD2,812				ALC5623_PWR_ADD2_VREF);813		snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD3,814				ALC5623_PWR_ADD3_MAIN_BIAS);815		break;816	case SND_SOC_BIAS_OFF:817		/* everything off, dac mute, inactive */818		snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD2, 0);819		snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD3, 0);820		snd_soc_component_write(component, ALC5623_PWR_MANAG_ADD1, 0);821		break;822	}823	return 0;824}825 826#define ALC5623_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE \827			| SNDRV_PCM_FMTBIT_S24_LE \828			| SNDRV_PCM_FMTBIT_S32_LE)829 830static const struct snd_soc_dai_ops alc5623_dai_ops = {831		.hw_params = alc5623_pcm_hw_params,832		.mute_stream = alc5623_mute,833		.set_fmt = alc5623_set_dai_fmt,834		.set_sysclk = alc5623_set_dai_sysclk,835		.set_pll = alc5623_set_dai_pll,836		.no_capture_mute = 1,837};838 839static struct snd_soc_dai_driver alc5623_dai = {840	.name = "alc5623-hifi",841	.playback = {842		.stream_name = "Playback",843		.channels_min = 1,844		.channels_max = 2,845		.rate_min =	8000,846		.rate_max =	48000,847		.rates = SNDRV_PCM_RATE_8000_48000,848		.formats = ALC5623_FORMATS,},849	.capture = {850		.stream_name = "Capture",851		.channels_min = 1,852		.channels_max = 2,853		.rate_min =	8000,854		.rate_max =	48000,855		.rates = SNDRV_PCM_RATE_8000_48000,856		.formats = ALC5623_FORMATS,},857 858	.ops = &alc5623_dai_ops,859};860 861static int alc5623_suspend(struct snd_soc_component *component)862{863	struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component);864 865	regcache_cache_only(alc5623->regmap, true);866 867	return 0;868}869 870static int alc5623_resume(struct snd_soc_component *component)871{872	struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component);873	int ret;874 875	/* Sync reg_cache with the hardware */876	regcache_cache_only(alc5623->regmap, false);877	ret = regcache_sync(alc5623->regmap);878	if (ret != 0) {879		dev_err(component->dev, "Failed to sync register cache: %d\n",880			ret);881		regcache_cache_only(alc5623->regmap, true);882		return ret;883	}884 885	return 0;886}887 888static int alc5623_probe(struct snd_soc_component *component)889{890	struct alc5623_priv *alc5623 = snd_soc_component_get_drvdata(component);891	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);892 893	alc5623_reset(component);894 895	if (alc5623->add_ctrl) {896		snd_soc_component_write(component, ALC5623_ADD_CTRL_REG,897				alc5623->add_ctrl);898	}899 900	if (alc5623->jack_det_ctrl) {901		snd_soc_component_write(component, ALC5623_JACK_DET_CTRL,902				alc5623->jack_det_ctrl);903	}904 905	switch (alc5623->id) {906	case 0x21:907		snd_soc_add_component_controls(component, alc5621_vol_snd_controls,908			ARRAY_SIZE(alc5621_vol_snd_controls));909		break;910	case 0x22:911		snd_soc_add_component_controls(component, alc5622_vol_snd_controls,912			ARRAY_SIZE(alc5622_vol_snd_controls));913		break;914	case 0x23:915		snd_soc_add_component_controls(component, alc5623_vol_snd_controls,916			ARRAY_SIZE(alc5623_vol_snd_controls));917		break;918	default:919		return -EINVAL;920	}921 922	snd_soc_add_component_controls(component, alc5623_snd_controls,923			ARRAY_SIZE(alc5623_snd_controls));924 925	snd_soc_dapm_new_controls(dapm, alc5623_dapm_widgets,926					ARRAY_SIZE(alc5623_dapm_widgets));927 928	/* set up audio path interconnects */929	snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));930 931	switch (alc5623->id) {932	case 0x21:933	case 0x22:934		snd_soc_dapm_new_controls(dapm, alc5623_dapm_amp_widgets,935					ARRAY_SIZE(alc5623_dapm_amp_widgets));936		snd_soc_dapm_add_routes(dapm, intercon_amp_spk,937					ARRAY_SIZE(intercon_amp_spk));938		break;939	case 0x23:940		snd_soc_dapm_add_routes(dapm, intercon_spk,941					ARRAY_SIZE(intercon_spk));942		break;943	default:944		return -EINVAL;945	}946 947	return 0;948}949 950static const struct snd_soc_component_driver soc_component_device_alc5623 = {951	.probe			= alc5623_probe,952	.suspend		= alc5623_suspend,953	.resume			= alc5623_resume,954	.set_bias_level		= alc5623_set_bias_level,955	.suspend_bias_off	= 1,956	.idle_bias_on		= 1,957	.use_pmdown_time	= 1,958	.endianness		= 1,959};960 961static const struct regmap_config alc5623_regmap = {962	.reg_bits = 8,963	.val_bits = 16,964	.reg_stride = 2,965 966	.max_register = ALC5623_VENDOR_ID2,967	.cache_type = REGCACHE_RBTREE,968};969 970static const struct i2c_device_id alc5623_i2c_table[] = {971	{"alc5621", 0x21},972	{"alc5622", 0x22},973	{"alc5623", 0x23},974	{}975};976MODULE_DEVICE_TABLE(i2c, alc5623_i2c_table);977 978/*979 * ALC5623 2 wire address is determined by A1 pin980 * state during powerup.981 *    low  = 0x1a982 *    high = 0x1b983 */984static int alc5623_i2c_probe(struct i2c_client *client)985{986	struct alc5623_platform_data *pdata;987	struct alc5623_priv *alc5623;988	struct device_node *np;989	unsigned int vid1, vid2;990	int ret;991	u32 val32;992	const struct i2c_device_id *id;993 994	alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),995			       GFP_KERNEL);996	if (alc5623 == NULL)997		return -ENOMEM;998 999	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_OF1073static const struct of_device_id alc5623_of_match[] = {1074	{ .compatible = "realtek,alc5623", },1075	{ }1076};1077MODULE_DEVICE_TABLE(of, alc5623_of_match);1078#endif1079 1080/*  i2c codec control layer */1081static 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 = alc5623_i2c_probe,1087	.id_table = alc5623_i2c_table,1088};1089 1090module_i2c_driver(alc5623_i2c_driver);1091 1092MODULE_DESCRIPTION("ASoC alc5621/2/3 driver");1093MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");1094MODULE_LICENSE("GPL");1095