Commit 6f4bc952c60b26ecfcb013fb9a7e9474023e046e

Authored by Arnaud Patard (Rtp)
Committed by Mark Brown
1 parent 4428bc0990

ASoC: add support for alc562[123] codecs

This patch is adding support for alc562[123] codecs. It's based
on the source code available in HP source code and other places.

Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

Showing 5 changed files with 1301 additions and 0 deletions Side-by-side Diff

include/sound/alc5623.h
  1 +#ifndef _INCLUDE_SOUND_ALC5623_H
  2 +#define _INCLUDE_SOUND_ALC5623_H
  3 +struct alc5623_platform_data {
  4 + /* configure : */
  5 + /* Lineout/Speaker Amps Vmid ratio control */
  6 + /* enable/disable adc/dac high pass filters */
  7 + unsigned int add_ctrl;
  8 + /* configure : */
  9 + /* output to enable when jack is low */
  10 + /* output to enable when jack is high */
  11 + /* jack detect (gpio/nc/jack detect [12] */
  12 + unsigned int jack_det_ctrl;
  13 +};
  14 +#endif
sound/soc/codecs/Kconfig
... ... @@ -22,6 +22,7 @@
22 22 select SND_SOC_AK4535 if I2C
23 23 select SND_SOC_AK4642 if I2C
24 24 select SND_SOC_AK4671 if I2C
  25 + select SND_SOC_ALC562 if I2C
25 26 select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
26 27 select SND_SOC_CS42L51 if I2C
27 28 select SND_SOC_CS4270 if I2C
... ... @@ -128,6 +129,9 @@
128 129  
129 130 config SND_SOC_AK4671
130 131 tristate
  132 +
  133 +config SND_SOC_ALC5623
  134 + tristate
131 135  
132 136 config SND_SOC_CQ0093VC
133 137 tristate
sound/soc/codecs/Makefile
... ... @@ -17,6 +17,7 @@
17 17 snd-soc-l3-objs := l3.o
18 18 snd-soc-max98088-objs := max98088.o
19 19 snd-soc-pcm3008-objs := pcm3008.o
  20 +snd-soc-alc5623-objs := alc5623.o
20 21 snd-soc-spdif-objs := spdif_transciever.o
21 22 snd-soc-ssm2602-objs := ssm2602.o
22 23 snd-soc-stac9766-objs := stac9766.o
... ... @@ -92,6 +93,7 @@
92 93 obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
93 94 obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
94 95 obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
  96 +obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
95 97 obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
96 98 obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
97 99 obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
sound/soc/codecs/alc5623.c
Changes suppressed. Click to show
  1 +/*
  2 + * alc5623.c -- alc562[123] ALSA Soc Audio driver
  3 + *
  4 + * Copyright 2008 Realtek Microelectronics
  5 + * Author: flove <flove@realtek.com> Ethan <eku@marvell.com>
  6 + *
  7 + * Copyright 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
  8 + *
  9 + *
  10 + * Based on WM8753.c
  11 + *
  12 + * This program is free software; you can redistribute it and/or modify
  13 + * it under the terms of the GNU General Public License version 2 as
  14 + * published by the Free Software Foundation.
  15 + *
  16 + */
  17 +
  18 +#include <linux/module.h>
  19 +#include <linux/kernel.h>
  20 +#include <linux/init.h>
  21 +#include <linux/delay.h>
  22 +#include <linux/pm.h>
  23 +#include <linux/i2c.h>
  24 +#include <linux/slab.h>
  25 +#include <linux/platform_device.h>
  26 +#include <sound/core.h>
  27 +#include <sound/pcm.h>
  28 +#include <sound/pcm_params.h>
  29 +#include <sound/tlv.h>
  30 +#include <sound/soc.h>
  31 +#include <sound/soc-dapm.h>
  32 +#include <sound/initval.h>
  33 +#include <sound/alc5623.h>
  34 +
  35 +#include "alc5623.h"
  36 +
  37 +static int caps_charge = 2000;
  38 +module_param(caps_charge, int, 0);
  39 +MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)");
  40 +
  41 +/* codec private data */
  42 +struct alc5623_priv {
  43 + enum snd_soc_control_type control_type;
  44 + void *control_data;
  45 + struct mutex mutex;
  46 + u8 id;
  47 + unsigned int sysclk;
  48 + u16 reg_cache[ALC5623_VENDOR_ID2+2];
  49 + unsigned int add_ctrl;
  50 + unsigned int jack_det_ctrl;
  51 +};
  52 +
  53 +static void alc5623_fill_cache(struct snd_soc_codec *codec)
  54 +{
  55 + int i, step = codec->driver->reg_cache_step;
  56 + u16 *cache = codec->reg_cache;
  57 +
  58 + /* not really efficient ... */
  59 + for (i = 0 ; i < codec->driver->reg_cache_size ; i += step)
  60 + cache[i] = codec->hw_read(codec, i);
  61 +}
  62 +
  63 +static inline int alc5623_reset(struct snd_soc_codec *codec)
  64 +{
  65 + return snd_soc_write(codec, ALC5623_RESET, 0);
  66 +}
  67 +
  68 +static int amp_mixer_event(struct snd_soc_dapm_widget *w,
  69 + struct snd_kcontrol *kcontrol, int event)
  70 +{
  71 + /* to power-on/off class-d amp generators/speaker */
  72 + /* need to write to 'index-46h' register : */
  73 + /* so write index num (here 0x46) to reg 0x6a */
  74 + /* and then 0xffff/0 to reg 0x6c */
  75 + snd_soc_write(w->codec, ALC5623_HID_CTRL_INDEX, 0x46);
  76 +
  77 + switch (event) {
  78 + case SND_SOC_DAPM_PRE_PMU:
  79 + snd_soc_write(w->codec, ALC5623_HID_CTRL_DATA, 0xFFFF);
  80 + break;
  81 + case SND_SOC_DAPM_POST_PMD:
  82 + snd_soc_write(w->codec, ALC5623_HID_CTRL_DATA, 0);
  83 + break;
  84 + }
  85 +
  86 + return 0;
  87 +}
  88 +
  89 +/*
  90 + * ALC5623 Controls
  91 + */
  92 +
  93 +static const DECLARE_TLV_DB_SCALE(vol_tlv, -3450, 150, 0);
  94 +static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0);
  95 +static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0);
  96 +static const unsigned int boost_tlv[] = {
  97 + TLV_DB_RANGE_HEAD(3),
  98 + 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
  99 + 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
  100 + 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
  101 +};
  102 +static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0);
  103 +
  104 +static const struct snd_kcontrol_new rt5621_vol_snd_controls[] = {
  105 + SOC_DOUBLE_TLV("Speaker Playback Volume",
  106 + ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),
  107 + SOC_DOUBLE("Speaker Playback Switch",
  108 + ALC5623_SPK_OUT_VOL, 15, 7, 1, 1),
  109 + SOC_DOUBLE_TLV("Headphone Playback Volume",
  110 + ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),
  111 + SOC_DOUBLE("Headphone Playback Switch",
  112 + ALC5623_HP_OUT_VOL, 15, 7, 1, 1),
  113 +};
  114 +
  115 +static const struct snd_kcontrol_new rt5622_vol_snd_controls[] = {
  116 + SOC_DOUBLE_TLV("Speaker Playback Volume",
  117 + ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),
  118 + SOC_DOUBLE("Speaker Playback Switch",
  119 + ALC5623_SPK_OUT_VOL, 15, 7, 1, 1),
  120 + SOC_DOUBLE_TLV("Line Playback Volume",
  121 + ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),
  122 + SOC_DOUBLE("Line Playback Switch",
  123 + ALC5623_HP_OUT_VOL, 15, 7, 1, 1),
  124 +};
  125 +
  126 +static const struct snd_kcontrol_new alc5623_vol_snd_controls[] = {
  127 + SOC_DOUBLE_TLV("Line Playback Volume",
  128 + ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),
  129 + SOC_DOUBLE("Line Playback Switch",
  130 + ALC5623_SPK_OUT_VOL, 15, 7, 1, 1),
  131 + SOC_DOUBLE_TLV("Headphone Playback Volume",
  132 + ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),
  133 + SOC_DOUBLE("Headphone Playback Switch",
  134 + ALC5623_HP_OUT_VOL, 15, 7, 1, 1),
  135 +};
  136 +
  137 +static const struct snd_kcontrol_new alc5623_snd_controls[] = {
  138 + SOC_DOUBLE_TLV("Auxout Playback Volume",
  139 + ALC5623_MONO_AUX_OUT_VOL, 8, 0, 31, 1, hp_tlv),
  140 + SOC_DOUBLE("Auxout Playback Switch",
  141 + ALC5623_MONO_AUX_OUT_VOL, 15, 7, 1, 1),
  142 + SOC_DOUBLE_TLV("PCM Playback Volume",
  143 + ALC5623_STEREO_DAC_VOL, 8, 0, 31, 1, vol_tlv),
  144 + SOC_DOUBLE_TLV("AuxI Capture Volume",
  145 + ALC5623_AUXIN_VOL, 8, 0, 31, 1, vol_tlv),
  146 + SOC_DOUBLE_TLV("LineIn Capture Volume",
  147 + ALC5623_LINE_IN_VOL, 8, 0, 31, 1, vol_tlv),
  148 + SOC_SINGLE_TLV("Mic1 Capture Volume",
  149 + ALC5623_MIC_VOL, 8, 31, 1, vol_tlv),
  150 + SOC_SINGLE_TLV("Mic2 Capture Volume",
  151 + ALC5623_MIC_VOL, 0, 31, 1, vol_tlv),
  152 + SOC_DOUBLE_TLV("Rec Capture Volume",
  153 + ALC5623_ADC_REC_GAIN, 7, 0, 31, 0, adc_rec_tlv),
  154 + SOC_SINGLE_TLV("Mic 1 Boost Volume",
  155 + ALC5623_MIC_CTRL, 10, 2, 0, boost_tlv),
  156 + SOC_SINGLE_TLV("Mic 2 Boost Volume",
  157 + ALC5623_MIC_CTRL, 8, 2, 0, boost_tlv),
  158 + SOC_SINGLE_TLV("Digital Boost Volume",
  159 + ALC5623_ADD_CTRL_REG, 4, 3, 0, dig_tlv),
  160 +};
  161 +
  162 +/*
  163 + * DAPM Controls
  164 + */
  165 +static const struct snd_kcontrol_new alc5623_hp_mixer_controls[] = {
  166 +SOC_DAPM_SINGLE("LI2HP Playback Switch", ALC5623_LINE_IN_VOL, 15, 1, 1),
  167 +SOC_DAPM_SINGLE("AUXI2HP Playback Switch", ALC5623_AUXIN_VOL, 15, 1, 1),
  168 +SOC_DAPM_SINGLE("MIC12HP Playback Switch", ALC5623_MIC_ROUTING_CTRL, 15, 1, 1),
  169 +SOC_DAPM_SINGLE("MIC22HP Playback Switch", ALC5623_MIC_ROUTING_CTRL, 7, 1, 1),
  170 +SOC_DAPM_SINGLE("DAC2HP Playback Switch", ALC5623_STEREO_DAC_VOL, 15, 1, 1),
  171 +};
  172 +
  173 +static const struct snd_kcontrol_new alc5623_hpl_mixer_controls[] = {
  174 +SOC_DAPM_SINGLE("ADC2HP_L Playback Switch", ALC5623_ADC_REC_GAIN, 15, 1, 1),
  175 +};
  176 +
  177 +static const struct snd_kcontrol_new alc5623_hpr_mixer_controls[] = {
  178 +SOC_DAPM_SINGLE("ADC2HP_R Playback Switch", ALC5623_ADC_REC_GAIN, 14, 1, 1),
  179 +};
  180 +
  181 +static const struct snd_kcontrol_new alc5623_mono_mixer_controls[] = {
  182 +SOC_DAPM_SINGLE("ADC2MONO_L Playback Switch", ALC5623_ADC_REC_GAIN, 13, 1, 1),
  183 +SOC_DAPM_SINGLE("ADC2MONO_R Playback Switch", ALC5623_ADC_REC_GAIN, 12, 1, 1),
  184 +SOC_DAPM_SINGLE("LI2MONO Playback Switch", ALC5623_LINE_IN_VOL, 13, 1, 1),
  185 +SOC_DAPM_SINGLE("AUXI2MONO Playback Switch", ALC5623_AUXIN_VOL, 13, 1, 1),
  186 +SOC_DAPM_SINGLE("MIC12MONO Playback Switch", ALC5623_MIC_ROUTING_CTRL, 13, 1, 1),
  187 +SOC_DAPM_SINGLE("MIC22MONO Playback Switch", ALC5623_MIC_ROUTING_CTRL, 5, 1, 1),
  188 +SOC_DAPM_SINGLE("DAC2MONO Playback Switch", ALC5623_STEREO_DAC_VOL, 13, 1, 1),
  189 +};
  190 +
  191 +static const struct snd_kcontrol_new alc5623_speaker_mixer_controls[] = {
  192 +SOC_DAPM_SINGLE("LI2SPK Playback Switch", ALC5623_LINE_IN_VOL, 14, 1, 1),
  193 +SOC_DAPM_SINGLE("AUXI2SPK Playback Switch", ALC5623_AUXIN_VOL, 14, 1, 1),
  194 +SOC_DAPM_SINGLE("MIC12SPK Playback Switch", ALC5623_MIC_ROUTING_CTRL, 14, 1, 1),
  195 +SOC_DAPM_SINGLE("MIC22SPK Playback Switch", ALC5623_MIC_ROUTING_CTRL, 6, 1, 1),
  196 +SOC_DAPM_SINGLE("DAC2SPK Playback Switch", ALC5623_STEREO_DAC_VOL, 14, 1, 1),
  197 +};
  198 +
  199 +/* Left Record Mixer */
  200 +static const struct snd_kcontrol_new alc5623_captureL_mixer_controls[] = {
  201 +SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5623_ADC_REC_MIXER, 14, 1, 1),
  202 +SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5623_ADC_REC_MIXER, 13, 1, 1),
  203 +SOC_DAPM_SINGLE("LineInL Capture Switch", ALC5623_ADC_REC_MIXER, 12, 1, 1),
  204 +SOC_DAPM_SINGLE("Left AuxI Capture Switch", ALC5623_ADC_REC_MIXER, 11, 1, 1),
  205 +SOC_DAPM_SINGLE("HPMixerL Capture Switch", ALC5623_ADC_REC_MIXER, 10, 1, 1),
  206 +SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5623_ADC_REC_MIXER, 9, 1, 1),
  207 +SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5623_ADC_REC_MIXER, 8, 1, 1),
  208 +};
  209 +
  210 +/* Right Record Mixer */
  211 +static const struct snd_kcontrol_new alc5623_captureR_mixer_controls[] = {
  212 +SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5623_ADC_REC_MIXER, 6, 1, 1),
  213 +SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5623_ADC_REC_MIXER, 5, 1, 1),
  214 +SOC_DAPM_SINGLE("LineInR Capture Switch", ALC5623_ADC_REC_MIXER, 4, 1, 1),
  215 +SOC_DAPM_SINGLE("Right AuxI Capture Switch", ALC5623_ADC_REC_MIXER, 3, 1, 1),
  216 +SOC_DAPM_SINGLE("HPMixerR Capture Switch", ALC5623_ADC_REC_MIXER, 2, 1, 1),
  217 +SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5623_ADC_REC_MIXER, 1, 1, 1),
  218 +SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5623_ADC_REC_MIXER, 0, 1, 1),
  219 +};
  220 +
  221 +static const char *alc5623_spk_n_sour_sel[] = {
  222 + "RN/-R", "RP/+R", "LN/-R", "Vmid" };
  223 +static const char *alc5623_hpl_out_input_sel[] = {
  224 + "Vmid", "HP Left Mix"};
  225 +static const char *alc5623_hpr_out_input_sel[] = {
  226 + "Vmid", "HP Right Mix"};
  227 +static const char *alc5623_spkout_input_sel[] = {
  228 + "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
  229 +static const char *alc5623_aux_out_input_sel[] = {
  230 + "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
  231 +
  232 +/* auxout output mux */
  233 +static const struct soc_enum alc5623_aux_out_input_enum =
  234 +SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 6, 4, alc5623_aux_out_input_sel);
  235 +static const struct snd_kcontrol_new alc5623_auxout_mux_controls =
  236 +SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum);
  237 +
  238 +/* speaker output mux */
  239 +static const struct soc_enum alc5623_spkout_input_enum =
  240 +SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 10, 4, alc5623_spkout_input_sel);
  241 +static const struct snd_kcontrol_new alc5623_spkout_mux_controls =
  242 +SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum);
  243 +
  244 +/* headphone left output mux */
  245 +static const struct soc_enum alc5623_hpl_out_input_enum =
  246 +SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 9, 2, alc5623_hpl_out_input_sel);
  247 +static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls =
  248 +SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum);
  249 +
  250 +/* headphone right output mux */
  251 +static const struct soc_enum alc5623_hpr_out_input_enum =
  252 +SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 8, 2, alc5623_hpr_out_input_sel);
  253 +static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls =
  254 +SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum);
  255 +
  256 +/* speaker output N select */
  257 +static const struct soc_enum alc5623_spk_n_sour_enum =
  258 +SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 14, 4, alc5623_spk_n_sour_sel);
  259 +static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls =
  260 +SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum);
  261 +
  262 +static const struct snd_soc_dapm_widget alc5623_dapm_widgets[] = {
  263 +/* Muxes */
  264 +SND_SOC_DAPM_MUX("AuxOut Mux", SND_SOC_NOPM, 0, 0,
  265 + &alc5623_auxout_mux_controls),
  266 +SND_SOC_DAPM_MUX("SpeakerOut Mux", SND_SOC_NOPM, 0, 0,
  267 + &alc5623_spkout_mux_controls),
  268 +SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0,
  269 + &alc5623_hpl_out_mux_controls),
  270 +SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,
  271 + &alc5623_hpr_out_mux_controls),
  272 +SND_SOC_DAPM_MUX("SpeakerOut N Mux", SND_SOC_NOPM, 0, 0,
  273 + &alc5623_spkoutn_mux_controls),
  274 +
  275 +/* output mixers */
  276 +SND_SOC_DAPM_MIXER("HP Mix", SND_SOC_NOPM, 0, 0,
  277 + &alc5623_hp_mixer_controls[0],
  278 + ARRAY_SIZE(alc5623_hp_mixer_controls)),
  279 +SND_SOC_DAPM_MIXER("HPR Mix", ALC5623_PWR_MANAG_ADD2, 4, 0,
  280 + &alc5623_hpr_mixer_controls[0],
  281 + ARRAY_SIZE(alc5623_hpr_mixer_controls)),
  282 +SND_SOC_DAPM_MIXER("HPL Mix", ALC5623_PWR_MANAG_ADD2, 5, 0,
  283 + &alc5623_hpl_mixer_controls[0],
  284 + ARRAY_SIZE(alc5623_hpl_mixer_controls)),
  285 +SND_SOC_DAPM_MIXER("HPOut Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
  286 +SND_SOC_DAPM_MIXER("Mono Mix", ALC5623_PWR_MANAG_ADD2, 2, 0,
  287 + &alc5623_mono_mixer_controls[0],
  288 + ARRAY_SIZE(alc5623_mono_mixer_controls)),
  289 +SND_SOC_DAPM_MIXER("Speaker Mix", ALC5623_PWR_MANAG_ADD2, 3, 0,
  290 + &alc5623_speaker_mixer_controls[0],
  291 + ARRAY_SIZE(alc5623_speaker_mixer_controls)),
  292 +
  293 +/* input mixers */
  294 +SND_SOC_DAPM_MIXER("Left Capture Mix", ALC5623_PWR_MANAG_ADD2, 1, 0,
  295 + &alc5623_captureL_mixer_controls[0],
  296 + ARRAY_SIZE(alc5623_captureL_mixer_controls)),
  297 +SND_SOC_DAPM_MIXER("Right Capture Mix", ALC5623_PWR_MANAG_ADD2, 0, 0,
  298 + &alc5623_captureR_mixer_controls[0],
  299 + ARRAY_SIZE(alc5623_captureR_mixer_controls)),
  300 +
  301 +SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback",
  302 + ALC5623_PWR_MANAG_ADD2, 9, 0),
  303 +SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback",
  304 + ALC5623_PWR_MANAG_ADD2, 8, 0),
  305 +SND_SOC_DAPM_MIXER("I2S Mix", ALC5623_PWR_MANAG_ADD1, 15, 0, NULL, 0),
  306 +SND_SOC_DAPM_MIXER("AuxI Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
  307 +SND_SOC_DAPM_MIXER("Line Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
  308 +SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture",
  309 + ALC5623_PWR_MANAG_ADD2, 7, 0),
  310 +SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture",
  311 + ALC5623_PWR_MANAG_ADD2, 6, 0),
  312 +SND_SOC_DAPM_PGA("Left Headphone", ALC5623_PWR_MANAG_ADD3, 10, 0, NULL, 0),
  313 +SND_SOC_DAPM_PGA("Right Headphone", ALC5623_PWR_MANAG_ADD3, 9, 0, NULL, 0),
  314 +SND_SOC_DAPM_PGA("SpeakerOut", ALC5623_PWR_MANAG_ADD3, 12, 0, NULL, 0),
  315 +SND_SOC_DAPM_PGA("Left AuxOut", ALC5623_PWR_MANAG_ADD3, 14, 0, NULL, 0),
  316 +SND_SOC_DAPM_PGA("Right AuxOut", ALC5623_PWR_MANAG_ADD3, 13, 0, NULL, 0),
  317 +SND_SOC_DAPM_PGA("Left LineIn", ALC5623_PWR_MANAG_ADD3, 7, 0, NULL, 0),
  318 +SND_SOC_DAPM_PGA("Right LineIn", ALC5623_PWR_MANAG_ADD3, 6, 0, NULL, 0),
  319 +SND_SOC_DAPM_PGA("Left AuxI", ALC5623_PWR_MANAG_ADD3, 5, 0, NULL, 0),
  320 +SND_SOC_DAPM_PGA("Right AuxI", ALC5623_PWR_MANAG_ADD3, 4, 0, NULL, 0),
  321 +SND_SOC_DAPM_PGA("MIC1 PGA", ALC5623_PWR_MANAG_ADD3, 3, 0, NULL, 0),
  322 +SND_SOC_DAPM_PGA("MIC2 PGA", ALC5623_PWR_MANAG_ADD3, 2, 0, NULL, 0),
  323 +SND_SOC_DAPM_PGA("MIC1 Pre Amp", ALC5623_PWR_MANAG_ADD3, 1, 0, NULL, 0),
  324 +SND_SOC_DAPM_PGA("MIC2 Pre Amp", ALC5623_PWR_MANAG_ADD3, 0, 0, NULL, 0),
  325 +SND_SOC_DAPM_MICBIAS("Mic Bias1", ALC5623_PWR_MANAG_ADD1, 11, 0),
  326 +
  327 +SND_SOC_DAPM_OUTPUT("AUXOUTL"),
  328 +SND_SOC_DAPM_OUTPUT("AUXOUTR"),
  329 +SND_SOC_DAPM_OUTPUT("HPL"),
  330 +SND_SOC_DAPM_OUTPUT("HPR"),
  331 +SND_SOC_DAPM_OUTPUT("SPKOUT"),
  332 +SND_SOC_DAPM_OUTPUT("SPKOUTN"),
  333 +SND_SOC_DAPM_INPUT("LINEINL"),
  334 +SND_SOC_DAPM_INPUT("LINEINR"),
  335 +SND_SOC_DAPM_INPUT("AUXINL"),
  336 +SND_SOC_DAPM_INPUT("AUXINR"),
  337 +SND_SOC_DAPM_INPUT("MIC1"),
  338 +SND_SOC_DAPM_INPUT("MIC2"),
  339 +SND_SOC_DAPM_VMID("Vmid"),
  340 +};
  341 +
  342 +static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"};
  343 +static const struct soc_enum alc5623_amp_enum =
  344 + SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 13, 2, alc5623_amp_names);
  345 +static const struct snd_kcontrol_new alc5623_amp_mux_controls =
  346 + SOC_DAPM_ENUM("Route", alc5623_amp_enum);
  347 +
  348 +static const struct snd_soc_dapm_widget alc5623_dapm_amp_widgets[] = {
  349 +SND_SOC_DAPM_PGA_E("D Amp", ALC5623_PWR_MANAG_ADD2, 14, 0, NULL, 0,
  350 + amp_mixer_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  351 +SND_SOC_DAPM_PGA("AB Amp", ALC5623_PWR_MANAG_ADD2, 15, 0, NULL, 0),
  352 +SND_SOC_DAPM_MUX("AB-D Amp Mux", SND_SOC_NOPM, 0, 0,
  353 + &alc5623_amp_mux_controls),
  354 +};
  355 +
  356 +static const struct snd_soc_dapm_route intercon[] = {
  357 + /* virtual mixer - mixes left & right channels */
  358 + {"I2S Mix", NULL, "Left DAC"},
  359 + {"I2S Mix", NULL, "Right DAC"},
  360 + {"Line Mix", NULL, "Right LineIn"},
  361 + {"Line Mix", NULL, "Left LineIn"},
  362 + {"AuxI Mix", NULL, "Left AuxI"},
  363 + {"AuxI Mix", NULL, "Right AuxI"},
  364 + {"AUXOUTL", NULL, "Left AuxOut"},
  365 + {"AUXOUTR", NULL, "Right AuxOut"},
  366 +
  367 + /* HP mixer */
  368 + {"HPL Mix", "ADC2HP_L Playback Switch", "Left Capture Mix"},
  369 + {"HPL Mix", NULL, "HP Mix"},
  370 + {"HPR Mix", "ADC2HP_R Playback Switch", "Right Capture Mix"},
  371 + {"HPR Mix", NULL, "HP Mix"},
  372 + {"HP Mix", "LI2HP Playback Switch", "Line Mix"},
  373 + {"HP Mix", "AUXI2HP Playback Switch", "AuxI Mix"},
  374 + {"HP Mix", "MIC12HP Playback Switch", "MIC1 PGA"},
  375 + {"HP Mix", "MIC22HP Playback Switch", "MIC2 PGA"},
  376 + {"HP Mix", "DAC2HP Playback Switch", "I2S Mix"},
  377 +
  378 + /* speaker mixer */
  379 + {"Speaker Mix", "LI2SPK Playback Switch", "Line Mix"},
  380 + {"Speaker Mix", "AUXI2SPK Playback Switch", "AuxI Mix"},
  381 + {"Speaker Mix", "MIC12SPK Playback Switch", "MIC1 PGA"},
  382 + {"Speaker Mix", "MIC22SPK Playback Switch", "MIC2 PGA"},
  383 + {"Speaker Mix", "DAC2SPK Playback Switch", "I2S Mix"},
  384 +
  385 + /* mono mixer */
  386 + {"Mono Mix", "ADC2MONO_L Playback Switch", "Left Capture Mix"},
  387 + {"Mono Mix", "ADC2MONO_R Playback Switch", "Right Capture Mix"},
  388 + {"Mono Mix", "LI2MONO Playback Switch", "Line Mix"},
  389 + {"Mono Mix", "AUXI2MONO Playback Switch", "AuxI Mix"},
  390 + {"Mono Mix", "MIC12MONO Playback Switch", "MIC1 PGA"},
  391 + {"Mono Mix", "MIC22MONO Playback Switch", "MIC2 PGA"},
  392 + {"Mono Mix", "DAC2MONO Playback Switch", "I2S Mix"},
  393 +
  394 + /* Left record mixer */
  395 + {"Left Capture Mix", "LineInL Capture Switch", "LINEINL"},
  396 + {"Left Capture Mix", "Left AuxI Capture Switch", "AUXINL"},
  397 + {"Left Capture Mix", "Mic1 Capture Switch", "MIC1 Pre Amp"},
  398 + {"Left Capture Mix", "Mic2 Capture Switch", "MIC2 Pre Amp"},
  399 + {"Left Capture Mix", "HPMixerL Capture Switch", "HPL Mix"},
  400 + {"Left Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
  401 + {"Left Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
  402 +
  403 + /*Right record mixer */
  404 + {"Right Capture Mix", "LineInR Capture Switch", "LINEINR"},
  405 + {"Right Capture Mix", "Right AuxI Capture Switch", "AUXINR"},
  406 + {"Right Capture Mix", "Mic1 Capture Switch", "MIC1 Pre Amp"},
  407 + {"Right Capture Mix", "Mic2 Capture Switch", "MIC2 Pre Amp"},
  408 + {"Right Capture Mix", "HPMixerR Capture Switch", "HPR Mix"},
  409 + {"Right Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
  410 + {"Right Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
  411 +
  412 + /* headphone left mux */
  413 + {"Left Headphone Mux", "HP Left Mix", "HPL Mix"},
  414 + {"Left Headphone Mux", "Vmid", "Vmid"},
  415 +
  416 + /* headphone right mux */
  417 + {"Right Headphone Mux", "HP Right Mix", "HPR Mix"},
  418 + {"Right Headphone Mux", "Vmid", "Vmid"},
  419 +
  420 + /* speaker out mux */
  421 + {"SpeakerOut Mux", "Vmid", "Vmid"},
  422 + {"SpeakerOut Mux", "HPOut Mix", "HPOut Mix"},
  423 + {"SpeakerOut Mux", "Speaker Mix", "Speaker Mix"},
  424 + {"SpeakerOut Mux", "Mono Mix", "Mono Mix"},
  425 +
  426 + /* Mono/Aux Out mux */
  427 + {"AuxOut Mux", "Vmid", "Vmid"},
  428 + {"AuxOut Mux", "HPOut Mix", "HPOut Mix"},
  429 + {"AuxOut Mux", "Speaker Mix", "Speaker Mix"},
  430 + {"AuxOut Mux", "Mono Mix", "Mono Mix"},
  431 +
  432 + /* output pga */
  433 + {"HPL", NULL, "Left Headphone"},
  434 + {"Left Headphone", NULL, "Left Headphone Mux"},
  435 + {"HPR", NULL, "Right Headphone"},
  436 + {"Right Headphone", NULL, "Right Headphone Mux"},
  437 + {"Left AuxOut", NULL, "AuxOut Mux"},
  438 + {"Right AuxOut", NULL, "AuxOut Mux"},
  439 +
  440 + /* input pga */
  441 + {"Left LineIn", NULL, "LINEINL"},
  442 + {"Right LineIn", NULL, "LINEINR"},
  443 + {"Left AuxI", NULL, "AUXINL"},
  444 + {"Right AuxI", NULL, "AUXINR"},
  445 + {"MIC1 Pre Amp", NULL, "MIC1"},
  446 + {"MIC2 Pre Amp", NULL, "MIC2"},
  447 + {"MIC1 PGA", NULL, "MIC1 Pre Amp"},
  448 + {"MIC2 PGA", NULL, "MIC2 Pre Amp"},
  449 +
  450 + /* left ADC */
  451 + {"Left ADC", NULL, "Left Capture Mix"},
  452 +
  453 + /* right ADC */
  454 + {"Right ADC", NULL, "Right Capture Mix"},
  455 +
  456 + {"SpeakerOut N Mux", "RN/-R", "SpeakerOut"},
  457 + {"SpeakerOut N Mux", "RP/+R", "SpeakerOut"},
  458 + {"SpeakerOut N Mux", "LN/-R", "SpeakerOut"},
  459 + {"SpeakerOut N Mux", "Vmid", "Vmid"},
  460 +
  461 + {"SPKOUT", NULL, "SpeakerOut"},
  462 + {"SPKOUTN", NULL, "SpeakerOut N Mux"},
  463 +};
  464 +
  465 +static const struct snd_soc_dapm_route intercon_spk[] = {
  466 + {"SpeakerOut", NULL, "SpeakerOut Mux"},
  467 +};
  468 +
  469 +static const struct snd_soc_dapm_route intercon_amp_spk[] = {
  470 + {"AB Amp", NULL, "SpeakerOut Mux"},
  471 + {"D Amp", NULL, "SpeakerOut Mux"},
  472 + {"AB-D Amp Mux", "AB Amp", "AB Amp"},
  473 + {"AB-D Amp Mux", "D Amp", "D Amp"},
  474 + {"SpeakerOut", NULL, "AB-D Amp Mux"},
  475 +};
  476 +
  477 +/* PLL divisors */
  478 +struct _pll_div {
  479 + u32 pll_in;
  480 + u32 pll_out;
  481 + u16 regvalue;
  482 +};
  483 +
  484 +/* Note : pll code from original alc5623 driver. Not sure of how good it is */
  485 +/* usefull only for master mode */
  486 +static const struct _pll_div codec_master_pll_div[] = {
  487 +
  488 + { 2048000, 8192000, 0x0ea0},
  489 + { 3686400, 8192000, 0x4e27},
  490 + { 12000000, 8192000, 0x456b},
  491 + { 13000000, 8192000, 0x495f},
  492 + { 13100000, 8192000, 0x0320},
  493 + { 2048000, 11289600, 0xf637},
  494 + { 3686400, 11289600, 0x2f22},
  495 + { 12000000, 11289600, 0x3e2f},
  496 + { 13000000, 11289600, 0x4d5b},
  497 + { 13100000, 11289600, 0x363b},
  498 + { 2048000, 16384000, 0x1ea0},
  499 + { 3686400, 16384000, 0x9e27},
  500 + { 12000000, 16384000, 0x452b},
  501 + { 13000000, 16384000, 0x542f},
  502 + { 13100000, 16384000, 0x03a0},
  503 + { 2048000, 16934400, 0xe625},
  504 + { 3686400, 16934400, 0x9126},
  505 + { 12000000, 16934400, 0x4d2c},
  506 + { 13000000, 16934400, 0x742f},
  507 + { 13100000, 16934400, 0x3c27},
  508 + { 2048000, 22579200, 0x2aa0},
  509 + { 3686400, 22579200, 0x2f20},
  510 + { 12000000, 22579200, 0x7e2f},
  511 + { 13000000, 22579200, 0x742f},
  512 + { 13100000, 22579200, 0x3c27},
  513 + { 2048000, 24576000, 0x2ea0},
  514 + { 3686400, 24576000, 0xee27},
  515 + { 12000000, 24576000, 0x2915},
  516 + { 13000000, 24576000, 0x772e},
  517 + { 13100000, 24576000, 0x0d20},
  518 +};
  519 +
  520 +static const struct _pll_div codec_slave_pll_div[] = {
  521 +
  522 + { 1024000, 16384000, 0x3ea0},
  523 + { 1411200, 22579200, 0x3ea0},
  524 + { 1536000, 24576000, 0x3ea0},
  525 + { 2048000, 16384000, 0x1ea0},
  526 + { 2822400, 22579200, 0x1ea0},
  527 + { 3072000, 24576000, 0x1ea0},
  528 +
  529 +};
  530 +
  531 +static int alc5623_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
  532 + int source, unsigned int freq_in, unsigned int freq_out)
  533 +{
  534 + int i;
  535 + struct snd_soc_codec *codec = codec_dai->codec;
  536 + int gbl_clk = 0, pll_div = 0;
  537 + u16 reg;
  538 +
  539 + if (pll_id < ALC5623_PLL_FR_MCLK || pll_id > ALC5623_PLL_FR_BCK)
  540 + return -ENODEV;
  541 +
  542 + /* Disable PLL power */
  543 + snd_soc_update_bits(codec, ALC5623_PWR_MANAG_ADD2,
  544 + ALC5623_PWR_ADD2_PLL,
  545 + 0);
  546 +
  547 + /* pll is not used in slave mode */
  548 + reg = snd_soc_read(codec, ALC5623_DAI_CONTROL);
  549 + if (reg & ALC5623_DAI_SDP_SLAVE_MODE)
  550 + return 0;
  551 +
  552 + if (!freq_in || !freq_out)
  553 + return 0;
  554 +
  555 + switch (pll_id) {
  556 + case ALC5623_PLL_FR_MCLK:
  557 + for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++) {
  558 + if (codec_master_pll_div[i].pll_in == freq_in
  559 + && codec_master_pll_div[i].pll_out == freq_out) {
  560 + /* PLL source from MCLK */
  561 + pll_div = codec_master_pll_div[i].regvalue;
  562 + break;
  563 + }
  564 + }
  565 + break;
  566 + case ALC5623_PLL_FR_BCK:
  567 + for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) {
  568 + if (codec_slave_pll_div[i].pll_in == freq_in
  569 + && codec_slave_pll_div[i].pll_out == freq_out) {
  570 + /* PLL source from Bitclk */
  571 + gbl_clk = ALC5623_GBL_CLK_PLL_SOUR_SEL_BITCLK;
  572 + pll_div = codec_slave_pll_div[i].regvalue;
  573 + break;
  574 + }
  575 + }
  576 + break;
  577 + default:
  578 + return -EINVAL;
  579 + }
  580 +
  581 + if (!pll_div)
  582 + return -EINVAL;
  583 +
  584 + snd_soc_write(codec, ALC5623_GLOBAL_CLK_CTRL_REG, gbl_clk);
  585 + snd_soc_write(codec, ALC5623_PLL_CTRL, pll_div);
  586 + snd_soc_update_bits(codec, ALC5623_PWR_MANAG_ADD2,
  587 + ALC5623_PWR_ADD2_PLL,
  588 + ALC5623_PWR_ADD2_PLL);
  589 + gbl_clk |= ALC5623_GBL_CLK_SYS_SOUR_SEL_PLL;
  590 + snd_soc_write(codec, ALC5623_GLOBAL_CLK_CTRL_REG, gbl_clk);
  591 +
  592 + return 0;
  593 +}
  594 +
  595 +struct _coeff_div {
  596 + u16 fs;
  597 + u16 regvalue;
  598 +};
  599 +
  600 +/* codec hifi mclk (after PLL) clock divider coefficients */
  601 +/* values inspired from column BCLK=32Fs of Appendix A table */
  602 +static const struct _coeff_div coeff_div[] = {
  603 + {256*8, 0x3a69},
  604 + {384*8, 0x3c6b},
  605 + {256*4, 0x2a69},
  606 + {384*4, 0x2c6b},
  607 + {256*2, 0x1a69},
  608 + {384*2, 0x1c6b},
  609 + {256*1, 0x0a69},
  610 + {384*1, 0x0c6b},
  611 +};
  612 +
  613 +static int get_coeff(struct snd_soc_codec *codec, int rate)
  614 +{
  615 + struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
  616 + int i;
  617 +
  618 + for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
  619 + if (coeff_div[i].fs * rate == alc5623->sysclk)
  620 + return i;
  621 + }
  622 + return -EINVAL;
  623 +}
  624 +
  625 +/*
  626 + * Clock after PLL and dividers
  627 + */
  628 +static int alc5623_set_dai_sysclk(struct snd_soc_dai *codec_dai,
  629 + int clk_id, unsigned int freq, int dir)
  630 +{
  631 + struct snd_soc_codec *codec = codec_dai->codec;
  632 + struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
  633 +
  634 + switch (freq) {
  635 + case 8192000:
  636 + case 11289600:
  637 + case 12288000:
  638 + case 16384000:
  639 + case 16934400:
  640 + case 18432000:
  641 + case 22579200:
  642 + case 24576000:
  643 + alc5623->sysclk = freq;
  644 + return 0;
  645 + }
  646 + return -EINVAL;
  647 +}
  648 +
  649 +static int alc5623_set_dai_fmt(struct snd_soc_dai *codec_dai,
  650 + unsigned int fmt)
  651 +{
  652 + struct snd_soc_codec *codec = codec_dai->codec;
  653 + u16 iface = 0;
  654 +
  655 + /* set master/slave audio interface */
  656 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  657 + case SND_SOC_DAIFMT_CBM_CFM:
  658 + iface = ALC5623_DAI_SDP_MASTER_MODE;
  659 + break;
  660 + case SND_SOC_DAIFMT_CBS_CFS:
  661 + iface = ALC5623_DAI_SDP_SLAVE_MODE;
  662 + break;
  663 + default:
  664 + return -EINVAL;
  665 + }
  666 +
  667 + /* interface format */
  668 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  669 + case SND_SOC_DAIFMT_I2S:
  670 + iface |= ALC5623_DAI_I2S_DF_I2S;
  671 + break;
  672 + case SND_SOC_DAIFMT_RIGHT_J:
  673 + iface |= ALC5623_DAI_I2S_DF_RIGHT;
  674 + break;
  675 + case SND_SOC_DAIFMT_LEFT_J:
  676 + iface |= ALC5623_DAI_I2S_DF_LEFT;
  677 + break;
  678 + case SND_SOC_DAIFMT_DSP_A:
  679 + iface |= ALC5623_DAI_I2S_DF_PCM;
  680 + break;
  681 + case SND_SOC_DAIFMT_DSP_B:
  682 + iface |= ALC5623_DAI_I2S_DF_PCM | ALC5623_DAI_I2S_PCM_MODE;
  683 + break;
  684 + default:
  685 + return -EINVAL;
  686 + }
  687 +
  688 + /* clock inversion */
  689 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  690 + case SND_SOC_DAIFMT_NB_NF:
  691 + break;
  692 + case SND_SOC_DAIFMT_IB_IF:
  693 + iface |= ALC5623_DAI_MAIN_I2S_BCLK_POL_CTRL;
  694 + break;
  695 + case SND_SOC_DAIFMT_IB_NF:
  696 + iface |= ALC5623_DAI_MAIN_I2S_BCLK_POL_CTRL;
  697 + break;
  698 + case SND_SOC_DAIFMT_NB_IF:
  699 + break;
  700 + default:
  701 + return -EINVAL;
  702 + }
  703 +
  704 + return snd_soc_write(codec, ALC5623_DAI_CONTROL, iface);
  705 +}
  706 +
  707 +static int alc5623_pcm_hw_params(struct snd_pcm_substream *substream,
  708 + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
  709 +{
  710 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  711 + struct snd_soc_codec *codec = rtd->codec;
  712 + struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
  713 + int coeff, rate;
  714 + u16 iface;
  715 +
  716 + iface = snd_soc_read(codec, ALC5623_DAI_CONTROL);
  717 + iface &= ~ALC5623_DAI_I2S_DL_MASK;
  718 +
  719 + /* bit size */
  720 + switch (params_format(params)) {
  721 + case SNDRV_PCM_FORMAT_S16_LE:
  722 + iface |= ALC5623_DAI_I2S_DL_16;
  723 + break;
  724 + case SNDRV_PCM_FORMAT_S20_3LE:
  725 + iface |= ALC5623_DAI_I2S_DL_20;
  726 + break;
  727 + case SNDRV_PCM_FORMAT_S24_LE:
  728 + iface |= ALC5623_DAI_I2S_DL_24;
  729 + break;
  730 + case SNDRV_PCM_FORMAT_S32_LE:
  731 + iface |= ALC5623_DAI_I2S_DL_32;
  732 + break;
  733 + default:
  734 + return -EINVAL;
  735 + }
  736 +
  737 + /* set iface & srate */
  738 + snd_soc_write(codec, ALC5623_DAI_CONTROL, iface);
  739 + rate = params_rate(params);
  740 + coeff = get_coeff(codec, rate);
  741 + if (coeff < 0)
  742 + return -EINVAL;
  743 +
  744 + coeff = coeff_div[coeff].regvalue;
  745 + dev_dbg(codec->dev, "%s: sysclk=%d,rate=%d,coeff=0x%04x\n",
  746 + __func__, alc5623->sysclk, rate, coeff);
  747 + snd_soc_write(codec, ALC5623_STEREO_AD_DA_CLK_CTRL, coeff);
  748 +
  749 + return 0;
  750 +}
  751 +
  752 +static int alc5623_mute(struct snd_soc_dai *dai, int mute)
  753 +{
  754 + struct snd_soc_codec *codec = dai->codec;
  755 + u16 hp_mute = ALC5623_MISC_M_DAC_L_INPUT | ALC5623_MISC_M_DAC_R_INPUT;
  756 + u16 mute_reg = snd_soc_read(codec, ALC5623_MISC_CTRL) & ~hp_mute;
  757 +
  758 + if (mute)
  759 + mute_reg |= hp_mute;
  760 +
  761 + return snd_soc_write(codec, ALC5623_MISC_CTRL, mute_reg);
  762 +}
  763 +
  764 +#define ALC5623_ADD2_POWER_EN (ALC5623_PWR_ADD2_VREF \
  765 + | ALC5623_PWR_ADD2_DAC_REF_CIR)
  766 +
  767 +#define ALC5623_ADD3_POWER_EN (ALC5623_PWR_ADD3_MAIN_BIAS \
  768 + | ALC5623_PWR_ADD3_MIC1_BOOST_AD)
  769 +
  770 +#define ALC5623_ADD1_POWER_EN \
  771 + (ALC5623_PWR_ADD1_SHORT_CURR_DET_EN | ALC5623_PWR_ADD1_SOFTGEN_EN \
  772 + | ALC5623_PWR_ADD1_DEPOP_BUF_HP | ALC5623_PWR_ADD1_HP_OUT_AMP \
  773 + | ALC5623_PWR_ADD1_HP_OUT_ENH_AMP)
  774 +
  775 +#define ALC5623_ADD1_POWER_EN_5622 \
  776 + (ALC5623_PWR_ADD1_SHORT_CURR_DET_EN \
  777 + | ALC5623_PWR_ADD1_HP_OUT_AMP)
  778 +
  779 +static void enable_power_depop(struct snd_soc_codec *codec)
  780 +{
  781 + struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
  782 +
  783 + snd_soc_update_bits(codec, ALC5623_PWR_MANAG_ADD1,
  784 + ALC5623_PWR_ADD1_SOFTGEN_EN,
  785 + ALC5623_PWR_ADD1_SOFTGEN_EN);
  786 +
  787 + snd_soc_write(codec, ALC5623_PWR_MANAG_ADD3, ALC5623_ADD3_POWER_EN);
  788 +
  789 + snd_soc_update_bits(codec, ALC5623_MISC_CTRL,
  790 + ALC5623_MISC_HP_DEPOP_MODE2_EN,
  791 + ALC5623_MISC_HP_DEPOP_MODE2_EN);
  792 +
  793 + msleep(500);
  794 +
  795 + snd_soc_write(codec, ALC5623_PWR_MANAG_ADD2, ALC5623_ADD2_POWER_EN);
  796 +
  797 + /* avoid writing '1' into 5622 reserved bits */
  798 + if (alc5623->id == 0x22)
  799 + snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1,
  800 + ALC5623_ADD1_POWER_EN_5622);
  801 + else
  802 + snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1,
  803 + ALC5623_ADD1_POWER_EN);
  804 +
  805 + /* disable HP Depop2 */
  806 + snd_soc_update_bits(codec, ALC5623_MISC_CTRL,
  807 + ALC5623_MISC_HP_DEPOP_MODE2_EN,
  808 + 0);
  809 +
  810 +}
  811 +
  812 +static int alc5623_set_bias_level(struct snd_soc_codec *codec,
  813 + enum snd_soc_bias_level level)
  814 +{
  815 + switch (level) {
  816 + case SND_SOC_BIAS_ON:
  817 + enable_power_depop(codec);
  818 + break;
  819 + case SND_SOC_BIAS_PREPARE:
  820 + break;
  821 + case SND_SOC_BIAS_STANDBY:
  822 + /* everything off except vref/vmid, */
  823 + snd_soc_write(codec, ALC5623_PWR_MANAG_ADD2,
  824 + ALC5623_PWR_ADD2_VREF);
  825 + snd_soc_write(codec, ALC5623_PWR_MANAG_ADD3,
  826 + ALC5623_PWR_ADD3_MAIN_BIAS);
  827 + break;
  828 + case SND_SOC_BIAS_OFF:
  829 + /* everything off, dac mute, inactive */
  830 + snd_soc_write(codec, ALC5623_PWR_MANAG_ADD2, 0);
  831 + snd_soc_write(codec, ALC5623_PWR_MANAG_ADD3, 0);
  832 + snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1, 0);
  833 + break;
  834 + }
  835 + codec->bias_level = level;
  836 + return 0;
  837 +}
  838 +
  839 +#define ALC5623_FORMATS (SNDRV_PCM_FMTBIT_S16_LE \
  840 + | SNDRV_PCM_FMTBIT_S24_LE \
  841 + | SNDRV_PCM_FMTBIT_S32_LE)
  842 +
  843 +static struct snd_soc_dai_ops alc5623_dai_ops = {
  844 + .hw_params = alc5623_pcm_hw_params,
  845 + .digital_mute = alc5623_mute,
  846 + .set_fmt = alc5623_set_dai_fmt,
  847 + .set_sysclk = alc5623_set_dai_sysclk,
  848 + .set_pll = alc5623_set_dai_pll,
  849 +};
  850 +
  851 +static struct snd_soc_dai_driver alc5623_dai = {
  852 + .name = "alc5623-hifi",
  853 + .playback = {
  854 + .stream_name = "Playback",
  855 + .channels_min = 1,
  856 + .channels_max = 2,
  857 + .rate_min = 8000,
  858 + .rate_max = 48000,
  859 + .rates = SNDRV_PCM_RATE_8000_48000,
  860 + .formats = ALC5623_FORMATS,},
  861 + .capture = {
  862 + .stream_name = "Capture",
  863 + .channels_min = 1,
  864 + .channels_max = 2,
  865 + .rate_min = 8000,
  866 + .rate_max = 48000,
  867 + .rates = SNDRV_PCM_RATE_8000_48000,
  868 + .formats = ALC5623_FORMATS,},
  869 +
  870 + .ops = &alc5623_dai_ops,
  871 +};
  872 +
  873 +static int alc5623_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
  874 +{
  875 + alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF);
  876 + return 0;
  877 +}
  878 +
  879 +static int alc5623_resume(struct snd_soc_codec *codec)
  880 +{
  881 + int i, step = codec->driver->reg_cache_step;
  882 + u16 *cache = codec->reg_cache;
  883 +
  884 + /* Sync reg_cache with the hardware */
  885 + for (i = 2 ; i < codec->driver->reg_cache_size ; i += step)
  886 + snd_soc_write(codec, i, cache[i]);
  887 +
  888 + alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
  889 +
  890 + /* charge alc5623 caps */
  891 + if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
  892 + alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
  893 + codec->bias_level = SND_SOC_BIAS_ON;
  894 + alc5623_set_bias_level(codec, codec->bias_level);
  895 + }
  896 +
  897 + return 0;
  898 +}
  899 +
  900 +static int alc5623_probe(struct snd_soc_codec *codec)
  901 +{
  902 + struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
  903 + int ret;
  904 +
  905 + ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5623->control_type);
  906 + if (ret < 0) {
  907 + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
  908 + return ret;
  909 + }
  910 +
  911 + alc5623_reset(codec);
  912 + alc5623_fill_cache(codec);
  913 +
  914 + /* power on device */
  915 + alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
  916 +
  917 + if (alc5623->add_ctrl) {
  918 + snd_soc_write(codec, ALC5623_ADD_CTRL_REG,
  919 + alc5623->add_ctrl);
  920 + }
  921 +
  922 + if (alc5623->jack_det_ctrl) {
  923 + snd_soc_write(codec, ALC5623_JACK_DET_CTRL,
  924 + alc5623->jack_det_ctrl);
  925 + }
  926 +
  927 + switch (alc5623->id) {
  928 + default:
  929 + case 0x21:
  930 + snd_soc_add_controls(codec, rt5621_vol_snd_controls,
  931 + ARRAY_SIZE(rt5621_vol_snd_controls));
  932 + break;
  933 + case 0x22:
  934 + snd_soc_add_controls(codec, rt5622_vol_snd_controls,
  935 + ARRAY_SIZE(rt5622_vol_snd_controls));
  936 + break;
  937 + case 0x23:
  938 + snd_soc_add_controls(codec, alc5623_vol_snd_controls,
  939 + ARRAY_SIZE(alc5623_vol_snd_controls));
  940 + break;
  941 + }
  942 +
  943 + snd_soc_add_controls(codec, alc5623_snd_controls,
  944 + ARRAY_SIZE(alc5623_snd_controls));
  945 +
  946 + snd_soc_dapm_new_controls(codec, alc5623_dapm_widgets,
  947 + ARRAY_SIZE(alc5623_dapm_widgets));
  948 +
  949 + /* set up audio path interconnects */
  950 + snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
  951 +
  952 + switch (alc5623->id) {
  953 + default:
  954 + case 0x21:
  955 + case 0x22:
  956 + snd_soc_dapm_new_controls(codec, alc5623_dapm_amp_widgets,
  957 + ARRAY_SIZE(alc5623_dapm_amp_widgets));
  958 + snd_soc_dapm_add_routes(codec, intercon_amp_spk,
  959 + ARRAY_SIZE(intercon_amp_spk));
  960 + break;
  961 + case 0x23:
  962 + snd_soc_dapm_add_routes(codec, intercon_spk,
  963 + ARRAY_SIZE(intercon_spk));
  964 + break;
  965 + }
  966 +
  967 + return ret;
  968 +}
  969 +
  970 +/* power down chip */
  971 +static int alc5623_remove(struct snd_soc_codec *codec)
  972 +{
  973 + alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF);
  974 + return 0;
  975 +}
  976 +
  977 +static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
  978 + .probe = alc5623_probe,
  979 + .remove = alc5623_remove,
  980 + .suspend = alc5623_suspend,
  981 + .resume = alc5623_resume,
  982 + .set_bias_level = alc5623_set_bias_level,
  983 + .reg_cache_size = ALC5623_VENDOR_ID2+2,
  984 + .reg_word_size = sizeof(u16),
  985 + .reg_cache_step = 2,
  986 +};
  987 +
  988 +/*
  989 + * ALC5623 2 wire address is determined by A1 pin
  990 + * state during powerup.
  991 + * low = 0x1a
  992 + * high = 0x1b
  993 + */
  994 +static int alc5623_i2c_probe(struct i2c_client *client,
  995 + const struct i2c_device_id *id)
  996 +{
  997 + struct alc5623_platform_data *pdata;
  998 + struct alc5623_priv *alc5623;
  999 + int ret, vid1, vid2;
  1000 +
  1001 + vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1);
  1002 + if (vid1 < 0) {
  1003 + dev_err(&client->dev, "failed to read I2C\n");
  1004 + return -EIO;
  1005 + }
  1006 + vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8);
  1007 +
  1008 + vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2);
  1009 + if (vid2 < 0) {
  1010 + dev_err(&client->dev, "failed to read I2C\n");
  1011 + return -EIO;
  1012 + }
  1013 +
  1014 + if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) {
  1015 + dev_err(&client->dev, "unknown or wrong codec\n");
  1016 + dev_err(&client->dev, "Expected %x:%lx, got %x:%x\n",
  1017 + 0x10ec, id->driver_data,
  1018 + vid1, vid2);
  1019 + return -ENODEV;
  1020 + }
  1021 +
  1022 + dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2);
  1023 +
  1024 + alc5623 = kzalloc(sizeof(struct alc5623_priv), GFP_KERNEL);
  1025 + if (alc5623 == NULL) {
  1026 + ret = -ENOMEM;
  1027 + goto err;
  1028 + }
  1029 +
  1030 + pdata = client->dev.platform_data;
  1031 + if (pdata) {
  1032 + alc5623->add_ctrl = pdata->add_ctrl;
  1033 + alc5623->jack_det_ctrl = pdata->jack_det_ctrl;
  1034 + }
  1035 +
  1036 + alc5623->id = vid2;
  1037 + switch (alc5623->id) {
  1038 + case 0x21:
  1039 + alc5623_dai.name = "alc5621-hifi";
  1040 + break;
  1041 + case 0x22:
  1042 + alc5623_dai.name = "alc5622-hifi";
  1043 + break;
  1044 + default:
  1045 + case 0x23:
  1046 + alc5623_dai.name = "alc5623-hifi";
  1047 + break;
  1048 + }
  1049 +
  1050 + i2c_set_clientdata(client, alc5623);
  1051 + alc5623->control_data = client;
  1052 + alc5623->control_type = SND_SOC_I2C;
  1053 + mutex_init(&alc5623->mutex);
  1054 +
  1055 + ret = snd_soc_register_codec(&client->dev,
  1056 + &soc_codec_device_alc5623, &alc5623_dai, 1);
  1057 + if (ret != 0) {
  1058 + dev_err(&client->dev, "Failed to register codec: %d\n", ret);
  1059 + goto err;
  1060 + }
  1061 +
  1062 + return 0;
  1063 +
  1064 +err:
  1065 + return ret;
  1066 +}
  1067 +
  1068 +static int alc5623_i2c_remove(struct i2c_client *client)
  1069 +{
  1070 + struct alc5623_priv *alc5623 = i2c_get_clientdata(client);
  1071 +
  1072 + snd_soc_unregister_codec(&client->dev);
  1073 + kfree(alc5623);
  1074 + return 0;
  1075 +}
  1076 +
  1077 +static const struct i2c_device_id alc5623_i2c_table[] = {
  1078 + {"alc5621", 0x21},
  1079 + {"alc5622", 0x22},
  1080 + {"alc5623", 0x23},
  1081 + {}
  1082 +};
  1083 +MODULE_DEVICE_TABLE(i2c, alc5623_i2c_table);
  1084 +
  1085 +/* i2c codec control layer */
  1086 +static struct i2c_driver alc5623_i2c_driver = {
  1087 + .driver = {
  1088 + .name = "alc562x-codec",
  1089 + .owner = THIS_MODULE,
  1090 + },
  1091 + .probe = alc5623_i2c_probe,
  1092 + .remove = __devexit_p(alc5623_i2c_remove),
  1093 + .id_table = alc5623_i2c_table,
  1094 +};
  1095 +
  1096 +static int __init alc5623_modinit(void)
  1097 +{
  1098 + int ret;
  1099 +
  1100 + ret = i2c_add_driver(&alc5623_i2c_driver);
  1101 + if (ret != 0) {
  1102 + printk(KERN_ERR "%s: can't add i2c driver", __func__);
  1103 + return ret;
  1104 + }
  1105 +
  1106 + return ret;
  1107 +}
  1108 +module_init(alc5623_modinit);
  1109 +
  1110 +static void __exit alc5623_modexit(void)
  1111 +{
  1112 + i2c_del_driver(&alc5623_i2c_driver);
  1113 +}
  1114 +module_exit(alc5623_modexit);
  1115 +
  1116 +MODULE_DESCRIPTION("ASoC alc5621/2/3 driver");
  1117 +MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
  1118 +MODULE_LICENSE("GPL");
sound/soc/codecs/alc5623.h
  1 +/*
  2 + * alc5623.h -- alc562[123] ALSA Soc Audio driver
  3 + *
  4 + * Copyright 2008 Realtek Microelectronics
  5 + * Copyright 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
  6 + *
  7 + * Author: flove <flove@realtek.com>
  8 + * Arnaud Patard <arnaud.patard@rtp-net.org>
  9 + *
  10 + * This program is free software; you can redistribute it and/or modify
  11 + * it under the terms of the GNU General Public License version 2 as
  12 + * published by the Free Software Foundation.
  13 + *
  14 + */
  15 +
  16 +#ifndef _ALC5623_H
  17 +#define _ALC5623_H
  18 +
  19 +#define ALC5623_RESET 0x00
  20 +/* 5621 5622 5623 */
  21 +/* speaker output vol 2 2 */
  22 +/* line output vol 4 2 */
  23 +/* HP output vol 4 0 4 */
  24 +#define ALC5623_SPK_OUT_VOL 0x02
  25 +#define ALC5623_HP_OUT_VOL 0x04
  26 +#define ALC5623_MONO_AUX_OUT_VOL 0x06
  27 +#define ALC5623_AUXIN_VOL 0x08
  28 +#define ALC5623_LINE_IN_VOL 0x0A
  29 +#define ALC5623_STEREO_DAC_VOL 0x0C
  30 +#define ALC5623_MIC_VOL 0x0E
  31 +#define ALC5623_MIC_ROUTING_CTRL 0x10
  32 +#define ALC5623_ADC_REC_GAIN 0x12
  33 +#define ALC5623_ADC_REC_MIXER 0x14
  34 +#define ALC5623_SOFT_VOL_CTRL_TIME 0x16
  35 +/* ALC5623_OUTPUT_MIXER_CTRL : */
  36 +/* same remark as for reg 2 line vs speaker */
  37 +#define ALC5623_OUTPUT_MIXER_CTRL 0x1C
  38 +#define ALC5623_MIC_CTRL 0x22
  39 +
  40 +#define ALC5623_DAI_CONTROL 0x34
  41 +#define ALC5623_DAI_SDP_MASTER_MODE (0 << 15)
  42 +#define ALC5623_DAI_SDP_SLAVE_MODE (1 << 15)
  43 +#define ALC5623_DAI_I2S_PCM_MODE (1 << 14)
  44 +#define ALC5623_DAI_MAIN_I2S_BCLK_POL_CTRL (1 << 7)
  45 +#define ALC5623_DAI_ADC_DATA_L_R_SWAP (1 << 5)
  46 +#define ALC5623_DAI_DAC_DATA_L_R_SWAP (1 << 4)
  47 +#define ALC5623_DAI_I2S_DL_MASK (3 << 2)
  48 +#define ALC5623_DAI_I2S_DL_32 (3 << 2)
  49 +#define ALC5623_DAI_I2S_DL_24 (2 << 2)
  50 +#define ALC5623_DAI_I2S_DL_20 (1 << 2)
  51 +#define ALC5623_DAI_I2S_DL_16 (0 << 2)
  52 +#define ALC5623_DAI_I2S_DF_PCM (3 << 0)
  53 +#define ALC5623_DAI_I2S_DF_LEFT (2 << 0)
  54 +#define ALC5623_DAI_I2S_DF_RIGHT (1 << 0)
  55 +#define ALC5623_DAI_I2S_DF_I2S (0 << 0)
  56 +
  57 +#define ALC5623_STEREO_AD_DA_CLK_CTRL 0x36
  58 +#define ALC5623_COMPANDING_CTRL 0x38
  59 +
  60 +#define ALC5623_PWR_MANAG_ADD1 0x3A
  61 +#define ALC5623_PWR_ADD1_MAIN_I2S_EN (1 << 15)
  62 +#define ALC5623_PWR_ADD1_ZC_DET_PD_EN (1 << 14)
  63 +#define ALC5623_PWR_ADD1_MIC1_BIAS_EN (1 << 11)
  64 +#define ALC5623_PWR_ADD1_SHORT_CURR_DET_EN (1 << 10)
  65 +#define ALC5623_PWR_ADD1_SOFTGEN_EN (1 << 8) /* rsvd on 5622 */
  66 +#define ALC5623_PWR_ADD1_DEPOP_BUF_HP (1 << 6) /* rsvd on 5622 */
  67 +#define ALC5623_PWR_ADD1_HP_OUT_AMP (1 << 5)
  68 +#define ALC5623_PWR_ADD1_HP_OUT_ENH_AMP (1 << 4) /* rsvd on 5622 */
  69 +#define ALC5623_PWR_ADD1_DEPOP_BUF_AUX (1 << 2)
  70 +#define ALC5623_PWR_ADD1_AUX_OUT_AMP (1 << 1)
  71 +#define ALC5623_PWR_ADD1_AUX_OUT_ENH_AMP (1 << 0) /* rsvd on 5622 */
  72 +
  73 +#define ALC5623_PWR_MANAG_ADD2 0x3C
  74 +#define ALC5623_PWR_ADD2_LINEOUT (1 << 15) /* rt5623 */
  75 +#define ALC5623_PWR_ADD2_CLASS_AB (1 << 15) /* rt5621 */
  76 +#define ALC5623_PWR_ADD2_CLASS_D (1 << 14) /* rt5621 */
  77 +#define ALC5623_PWR_ADD2_VREF (1 << 13)
  78 +#define ALC5623_PWR_ADD2_PLL (1 << 12)
  79 +#define ALC5623_PWR_ADD2_DAC_REF_CIR (1 << 10)
  80 +#define ALC5623_PWR_ADD2_L_DAC_CLK (1 << 9)
  81 +#define ALC5623_PWR_ADD2_R_DAC_CLK (1 << 8)
  82 +#define ALC5623_PWR_ADD2_L_ADC_CLK_GAIN (1 << 7)
  83 +#define ALC5623_PWR_ADD2_R_ADC_CLK_GAIN (1 << 6)
  84 +#define ALC5623_PWR_ADD2_L_HP_MIXER (1 << 5)
  85 +#define ALC5623_PWR_ADD2_R_HP_MIXER (1 << 4)
  86 +#define ALC5623_PWR_ADD2_SPK_MIXER (1 << 3)
  87 +#define ALC5623_PWR_ADD2_MONO_MIXER (1 << 2)
  88 +#define ALC5623_PWR_ADD2_L_ADC_REC_MIXER (1 << 1)
  89 +#define ALC5623_PWR_ADD2_R_ADC_REC_MIXER (1 << 0)
  90 +
  91 +#define ALC5623_PWR_MANAG_ADD3 0x3E
  92 +#define ALC5623_PWR_ADD3_MAIN_BIAS (1 << 15)
  93 +#define ALC5623_PWR_ADD3_AUXOUT_L_VOL_AMP (1 << 14)
  94 +#define ALC5623_PWR_ADD3_AUXOUT_R_VOL_AMP (1 << 13)
  95 +#define ALC5623_PWR_ADD3_SPK_OUT (1 << 12)
  96 +#define ALC5623_PWR_ADD3_HP_L_OUT_VOL (1 << 10)
  97 +#define ALC5623_PWR_ADD3_HP_R_OUT_VOL (1 << 9)
  98 +#define ALC5623_PWR_ADD3_LINEIN_L_VOL (1 << 7)
  99 +#define ALC5623_PWR_ADD3_LINEIN_R_VOL (1 << 6)
  100 +#define ALC5623_PWR_ADD3_AUXIN_L_VOL (1 << 5)
  101 +#define ALC5623_PWR_ADD3_AUXIN_R_VOL (1 << 4)
  102 +#define ALC5623_PWR_ADD3_MIC1_FUN_CTRL (1 << 3)
  103 +#define ALC5623_PWR_ADD3_MIC2_FUN_CTRL (1 << 2)
  104 +#define ALC5623_PWR_ADD3_MIC1_BOOST_AD (1 << 1)
  105 +#define ALC5623_PWR_ADD3_MIC2_BOOST_AD (1 << 0)
  106 +
  107 +#define ALC5623_ADD_CTRL_REG 0x40
  108 +
  109 +#define ALC5623_GLOBAL_CLK_CTRL_REG 0x42
  110 +#define ALC5623_GBL_CLK_SYS_SOUR_SEL_PLL (1 << 15)
  111 +#define ALC5623_GBL_CLK_SYS_SOUR_SEL_MCLK (0 << 15)
  112 +#define ALC5623_GBL_CLK_PLL_SOUR_SEL_BITCLK (1 << 14)
  113 +#define ALC5623_GBL_CLK_PLL_SOUR_SEL_MCLK (0 << 14)
  114 +#define ALC5623_GBL_CLK_PLL_DIV_RATIO_DIV8 (3 << 1)
  115 +#define ALC5623_GBL_CLK_PLL_DIV_RATIO_DIV4 (2 << 1)
  116 +#define ALC5623_GBL_CLK_PLL_DIV_RATIO_DIV2 (1 << 1)
  117 +#define ALC5623_GBL_CLK_PLL_DIV_RATIO_DIV1 (0 << 1)
  118 +#define ALC5623_GBL_CLK_PLL_PRE_DIV2 (1 << 0)
  119 +#define ALC5623_GBL_CLK_PLL_PRE_DIV1 (0 << 0)
  120 +
  121 +#define ALC5623_PLL_CTRL 0x44
  122 +#define ALC5623_PLL_CTRL_N_VAL(n) (((n)&0xff) << 8)
  123 +#define ALC5623_PLL_CTRL_K_VAL(k) (((k)&0x7) << 4)
  124 +#define ALC5623_PLL_CTRL_M_VAL(m) ((m)&0xf)
  125 +
  126 +#define ALC5623_GPIO_OUTPUT_PIN_CTRL 0x4A
  127 +#define ALC5623_GPIO_PIN_CONFIG 0x4C
  128 +#define ALC5623_GPIO_PIN_POLARITY 0x4E
  129 +#define ALC5623_GPIO_PIN_STICKY 0x50
  130 +#define ALC5623_GPIO_PIN_WAKEUP 0x52
  131 +#define ALC5623_GPIO_PIN_STATUS 0x54
  132 +#define ALC5623_GPIO_PIN_SHARING 0x56
  133 +#define ALC5623_OVER_CURR_STATUS 0x58
  134 +#define ALC5623_JACK_DET_CTRL 0x5A
  135 +
  136 +#define ALC5623_MISC_CTRL 0x5E
  137 +#define ALC5623_MISC_DISABLE_FAST_VREG (1 << 15)
  138 +#define ALC5623_MISC_SPK_CLASS_AB_OC_PD (1 << 13) /* 5621 */
  139 +#define ALC5623_MISC_SPK_CLASS_AB_OC_DET (1 << 12) /* 5621 */
  140 +#define ALC5623_MISC_HP_DEPOP_MODE3_EN (1 << 10)
  141 +#define ALC5623_MISC_HP_DEPOP_MODE2_EN (1 << 9)
  142 +#define ALC5623_MISC_HP_DEPOP_MODE1_EN (1 << 8)
  143 +#define ALC5623_MISC_AUXOUT_DEPOP_MODE3_EN (1 << 6)
  144 +#define ALC5623_MISC_AUXOUT_DEPOP_MODE2_EN (1 << 5)
  145 +#define ALC5623_MISC_AUXOUT_DEPOP_MODE1_EN (1 << 4)
  146 +#define ALC5623_MISC_M_DAC_L_INPUT (1 << 3)
  147 +#define ALC5623_MISC_M_DAC_R_INPUT (1 << 2)
  148 +#define ALC5623_MISC_IRQOUT_INV_CTRL (1 << 0)
  149 +
  150 +#define ALC5623_PSEDUEO_SPATIAL_CTRL 0x60
  151 +#define ALC5623_EQ_CTRL 0x62
  152 +#define ALC5623_EQ_MODE_ENABLE 0x66
  153 +#define ALC5623_AVC_CTRL 0x68
  154 +#define ALC5623_HID_CTRL_INDEX 0x6A
  155 +#define ALC5623_HID_CTRL_DATA 0x6C
  156 +#define ALC5623_VENDOR_ID1 0x7C
  157 +#define ALC5623_VENDOR_ID2 0x7E
  158 +
  159 +#define ALC5623_PLL_FR_MCLK 0
  160 +#define ALC5623_PLL_FR_BCK 1
  161 +#endif