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