Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ALSA SoC TLV320AIC23 codec driver
0004  *
0005  * Author:      Arun KS, <arunks@mistralsolutions.com>
0006  * Copyright:   (C) 2008 Mistral Solutions Pvt Ltd.,
0007  *
0008  * Based on sound/soc/codecs/wm8731.c by Richard Purdie
0009  *
0010  * Notes:
0011  *  The AIC23 is a driver for a low power stereo audio
0012  *  codec tlv320aic23
0013  *
0014  *  The machine layer should disable unsupported inputs/outputs by
0015  *  snd_soc_dapm_disable_pin(codec, "LHPOUT"), etc.
0016  */
0017 
0018 #include <linux/module.h>
0019 #include <linux/moduleparam.h>
0020 #include <linux/init.h>
0021 #include <linux/delay.h>
0022 #include <linux/pm.h>
0023 #include <linux/regmap.h>
0024 #include <linux/slab.h>
0025 #include <sound/core.h>
0026 #include <sound/pcm.h>
0027 #include <sound/pcm_params.h>
0028 #include <sound/soc.h>
0029 #include <sound/tlv.h>
0030 #include <sound/initval.h>
0031 
0032 #include "tlv320aic23.h"
0033 
0034 /*
0035  * AIC23 register cache
0036  */
0037 static const struct reg_default tlv320aic23_reg[] = {
0038     {  0, 0x0097 },
0039     {  1, 0x0097 },
0040     {  2, 0x00F9 },
0041     {  3, 0x00F9 },
0042     {  4, 0x001A },
0043     {  5, 0x0004 },
0044     {  6, 0x0007 },
0045     {  7, 0x0001 },
0046     {  8, 0x0020 },
0047     {  9, 0x0000 },
0048 };
0049 
0050 const struct regmap_config tlv320aic23_regmap = {
0051     .reg_bits = 7,
0052     .val_bits = 9,
0053 
0054     .max_register = TLV320AIC23_RESET,
0055     .reg_defaults = tlv320aic23_reg,
0056     .num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg),
0057     .cache_type = REGCACHE_RBTREE,
0058 };
0059 EXPORT_SYMBOL(tlv320aic23_regmap);
0060 
0061 static const char *rec_src_text[] = { "Line", "Mic" };
0062 static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"};
0063 
0064 static SOC_ENUM_SINGLE_DECL(rec_src_enum,
0065                 TLV320AIC23_ANLG, 2, rec_src_text);
0066 
0067 static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls =
0068 SOC_DAPM_ENUM("Input Select", rec_src_enum);
0069 
0070 static SOC_ENUM_SINGLE_DECL(tlv320aic23_deemph,
0071                 TLV320AIC23_DIGT, 1, deemph_text);
0072 
0073 static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0);
0074 static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0);
0075 static const DECLARE_TLV_DB_SCALE(sidetone_vol_tlv, -1800, 300, 0);
0076 
0077 static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
0078     struct snd_ctl_elem_value *ucontrol)
0079 {
0080     struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0081     u16 val, reg;
0082 
0083     val = (ucontrol->value.integer.value[0] & 0x07);
0084 
0085     /* linear conversion to userspace
0086     * 000   =   -6db
0087     * 001   =   -9db
0088     * 010   =   -12db
0089     * 011   =   -18db (Min)
0090     * 100   =   0db (Max)
0091     */
0092     val = (val >= 4) ? 4  : (3 - val);
0093 
0094     reg = snd_soc_component_read(component, TLV320AIC23_ANLG) & (~0x1C0);
0095     snd_soc_component_write(component, TLV320AIC23_ANLG, reg | (val << 6));
0096 
0097     return 0;
0098 }
0099 
0100 static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
0101     struct snd_ctl_elem_value *ucontrol)
0102 {
0103     struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0104     u16 val;
0105 
0106     val = snd_soc_component_read(component, TLV320AIC23_ANLG) & (0x1C0);
0107     val = val >> 6;
0108     val = (val >= 4) ? 4  : (3 -  val);
0109     ucontrol->value.integer.value[0] = val;
0110     return 0;
0111 
0112 }
0113 
0114 static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
0115     SOC_DOUBLE_R_TLV("Digital Playback Volume", TLV320AIC23_LCHNVOL,
0116              TLV320AIC23_RCHNVOL, 0, 127, 0, out_gain_tlv),
0117     SOC_SINGLE("Digital Playback Switch", TLV320AIC23_DIGT, 3, 1, 1),
0118     SOC_DOUBLE_R("Line Input Switch", TLV320AIC23_LINVOL,
0119              TLV320AIC23_RINVOL, 7, 1, 0),
0120     SOC_DOUBLE_R_TLV("Line Input Volume", TLV320AIC23_LINVOL,
0121              TLV320AIC23_RINVOL, 0, 31, 0, input_gain_tlv),
0122     SOC_SINGLE("Mic Input Switch", TLV320AIC23_ANLG, 1, 1, 1),
0123     SOC_SINGLE("Mic Booster Switch", TLV320AIC23_ANLG, 0, 1, 0),
0124     SOC_SINGLE_EXT_TLV("Sidetone Volume", TLV320AIC23_ANLG, 6, 4, 0,
0125                snd_soc_tlv320aic23_get_volsw,
0126                snd_soc_tlv320aic23_put_volsw, sidetone_vol_tlv),
0127     SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph),
0128 };
0129 
0130 /* PGA Mixer controls for Line and Mic switch */
0131 static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = {
0132     SOC_DAPM_SINGLE("Line Bypass Switch", TLV320AIC23_ANLG, 3, 1, 0),
0133     SOC_DAPM_SINGLE("Mic Sidetone Switch", TLV320AIC23_ANLG, 5, 1, 0),
0134     SOC_DAPM_SINGLE("Playback Switch", TLV320AIC23_ANLG, 4, 1, 0),
0135 };
0136 
0137 static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
0138     SND_SOC_DAPM_DAC("DAC", "Playback", TLV320AIC23_PWR, 3, 1),
0139     SND_SOC_DAPM_ADC("ADC", "Capture", TLV320AIC23_PWR, 2, 1),
0140     SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
0141              &tlv320aic23_rec_src_mux_controls),
0142     SND_SOC_DAPM_MIXER("Output Mixer", TLV320AIC23_PWR, 4, 1,
0143                &tlv320aic23_output_mixer_controls[0],
0144                ARRAY_SIZE(tlv320aic23_output_mixer_controls)),
0145     SND_SOC_DAPM_PGA("Line Input", TLV320AIC23_PWR, 0, 1, NULL, 0),
0146     SND_SOC_DAPM_PGA("Mic Input", TLV320AIC23_PWR, 1, 1, NULL, 0),
0147 
0148     SND_SOC_DAPM_OUTPUT("LHPOUT"),
0149     SND_SOC_DAPM_OUTPUT("RHPOUT"),
0150     SND_SOC_DAPM_OUTPUT("LOUT"),
0151     SND_SOC_DAPM_OUTPUT("ROUT"),
0152 
0153     SND_SOC_DAPM_INPUT("LLINEIN"),
0154     SND_SOC_DAPM_INPUT("RLINEIN"),
0155 
0156     SND_SOC_DAPM_INPUT("MICIN"),
0157 };
0158 
0159 static const struct snd_soc_dapm_route tlv320aic23_intercon[] = {
0160     /* Output Mixer */
0161     {"Output Mixer", "Line Bypass Switch", "Line Input"},
0162     {"Output Mixer", "Playback Switch", "DAC"},
0163     {"Output Mixer", "Mic Sidetone Switch", "Mic Input"},
0164 
0165     /* Outputs */
0166     {"RHPOUT", NULL, "Output Mixer"},
0167     {"LHPOUT", NULL, "Output Mixer"},
0168     {"LOUT", NULL, "Output Mixer"},
0169     {"ROUT", NULL, "Output Mixer"},
0170 
0171     /* Inputs */
0172     {"Line Input", NULL, "LLINEIN"},
0173     {"Line Input", NULL, "RLINEIN"},
0174     {"Mic Input", NULL, "MICIN"},
0175 
0176     /* input mux */
0177     {"Capture Source", "Line", "Line Input"},
0178     {"Capture Source", "Mic", "Mic Input"},
0179     {"ADC", NULL, "Capture Source"},
0180 
0181 };
0182 
0183 /* AIC23 driver data */
0184 struct aic23 {
0185     struct regmap *regmap;
0186     int mclk;
0187     int requested_adc;
0188     int requested_dac;
0189 };
0190 
0191 /*
0192  * Common Crystals used
0193  * 11.2896 Mhz /128 = *88.2k  /192 = 58.8k
0194  * 12.0000 Mhz /125 = *96k    /136 = 88.235K
0195  * 12.2880 Mhz /128 = *96k    /192 = 64k
0196  * 16.9344 Mhz /128 = 132.3k /192 = *88.2k
0197  * 18.4320 Mhz /128 = 144k   /192 = *96k
0198  */
0199 
0200 /*
0201  * Normal BOSR 0-256/2 = 128, 1-384/2 = 192
0202  * USB BOSR 0-250/2 = 125, 1-272/2 = 136
0203  */
0204 static const int bosr_usb_divisor_table[] = {
0205     128, 125, 192, 136
0206 };
0207 #define LOWER_GROUP ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<6) | (1<<7))
0208 #define UPPER_GROUP ((1<<8) | (1<<9) | (1<<10) | (1<<11)        | (1<<15))
0209 static const unsigned short sr_valid_mask[] = {
0210     LOWER_GROUP|UPPER_GROUP,    /* Normal, bosr - 0*/
0211     LOWER_GROUP,            /* Usb, bosr - 0*/
0212     LOWER_GROUP|UPPER_GROUP,    /* Normal, bosr - 1*/
0213     UPPER_GROUP,            /* Usb, bosr - 1*/
0214 };
0215 /*
0216  * Every divisor is a factor of 11*12
0217  */
0218 #define SR_MULT (11*12)
0219 #define A(x) (SR_MULT/x)
0220 static const unsigned char sr_adc_mult_table[] = {
0221     A(2), A(2), A(12), A(12),  0, 0, A(3), A(1),
0222     A(2), A(2), A(11), A(11),  0, 0, 0, A(1)
0223 };
0224 static const unsigned char sr_dac_mult_table[] = {
0225     A(2), A(12), A(2), A(12),  0, 0, A(3), A(1),
0226     A(2), A(11), A(2), A(11),  0, 0, 0, A(1)
0227 };
0228 
0229 static unsigned get_score(int adc, int adc_l, int adc_h, int need_adc,
0230         int dac, int dac_l, int dac_h, int need_dac)
0231 {
0232     if ((adc >= adc_l) && (adc <= adc_h) &&
0233             (dac >= dac_l) && (dac <= dac_h)) {
0234         int diff_adc = need_adc - adc;
0235         int diff_dac = need_dac - dac;
0236         return abs(diff_adc) + abs(diff_dac);
0237     }
0238     return UINT_MAX;
0239 }
0240 
0241 static int find_rate(int mclk, u32 need_adc, u32 need_dac)
0242 {
0243     int i, j;
0244     int best_i = -1;
0245     int best_j = -1;
0246     int best_div = 0;
0247     unsigned best_score = UINT_MAX;
0248     int adc_l, adc_h, dac_l, dac_h;
0249 
0250     need_adc *= SR_MULT;
0251     need_dac *= SR_MULT;
0252     /*
0253      * rates given are +/- 1/32
0254      */
0255     adc_l = need_adc - (need_adc >> 5);
0256     adc_h = need_adc + (need_adc >> 5);
0257     dac_l = need_dac - (need_dac >> 5);
0258     dac_h = need_dac + (need_dac >> 5);
0259     for (i = 0; i < ARRAY_SIZE(bosr_usb_divisor_table); i++) {
0260         int base = mclk / bosr_usb_divisor_table[i];
0261         int mask = sr_valid_mask[i];
0262         for (j = 0; j < ARRAY_SIZE(sr_adc_mult_table);
0263                 j++, mask >>= 1) {
0264             int adc;
0265             int dac;
0266             int score;
0267             if ((mask & 1) == 0)
0268                 continue;
0269             adc = base * sr_adc_mult_table[j];
0270             dac = base * sr_dac_mult_table[j];
0271             score = get_score(adc, adc_l, adc_h, need_adc,
0272                     dac, dac_l, dac_h, need_dac);
0273             if (best_score > score) {
0274                 best_score = score;
0275                 best_i = i;
0276                 best_j = j;
0277                 best_div = 0;
0278             }
0279             score = get_score((adc >> 1), adc_l, adc_h, need_adc,
0280                     (dac >> 1), dac_l, dac_h, need_dac);
0281             /* prefer to have a /2 */
0282             if ((score != UINT_MAX) && (best_score >= score)) {
0283                 best_score = score;
0284                 best_i = i;
0285                 best_j = j;
0286                 best_div = 1;
0287             }
0288         }
0289     }
0290     return (best_j << 2) | best_i | (best_div << TLV320AIC23_CLKIN_SHIFT);
0291 }
0292 
0293 #ifdef DEBUG
0294 static void get_current_sample_rates(struct snd_soc_component *component, int mclk,
0295         u32 *sample_rate_adc, u32 *sample_rate_dac)
0296 {
0297     int src = snd_soc_component_read(component, TLV320AIC23_SRATE);
0298     int sr = (src >> 2) & 0x0f;
0299     int val = (mclk / bosr_usb_divisor_table[src & 3]);
0300     int adc = (val * sr_adc_mult_table[sr]) / SR_MULT;
0301     int dac = (val * sr_dac_mult_table[sr]) / SR_MULT;
0302     if (src & TLV320AIC23_CLKIN_HALF) {
0303         adc >>= 1;
0304         dac >>= 1;
0305     }
0306     *sample_rate_adc = adc;
0307     *sample_rate_dac = dac;
0308 }
0309 #endif
0310 
0311 static int set_sample_rate_control(struct snd_soc_component *component, int mclk,
0312         u32 sample_rate_adc, u32 sample_rate_dac)
0313 {
0314     /* Search for the right sample rate */
0315     int data = find_rate(mclk, sample_rate_adc, sample_rate_dac);
0316     if (data < 0) {
0317         printk(KERN_ERR "%s:Invalid rate %u,%u requested\n",
0318                 __func__, sample_rate_adc, sample_rate_dac);
0319         return -EINVAL;
0320     }
0321     snd_soc_component_write(component, TLV320AIC23_SRATE, data);
0322 #ifdef DEBUG
0323     {
0324         u32 adc, dac;
0325         get_current_sample_rates(component, mclk, &adc, &dac);
0326         printk(KERN_DEBUG "actual samplerate = %u,%u reg=%x\n",
0327             adc, dac, data);
0328     }
0329 #endif
0330     return 0;
0331 }
0332 
0333 static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
0334                  struct snd_pcm_hw_params *params,
0335                  struct snd_soc_dai *dai)
0336 {
0337     struct snd_soc_component *component = dai->component;
0338     u16 iface_reg;
0339     int ret;
0340     struct aic23 *aic23 = snd_soc_component_get_drvdata(component);
0341     u32 sample_rate_adc = aic23->requested_adc;
0342     u32 sample_rate_dac = aic23->requested_dac;
0343     u32 sample_rate = params_rate(params);
0344 
0345     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0346         aic23->requested_dac = sample_rate_dac = sample_rate;
0347         if (!sample_rate_adc)
0348             sample_rate_adc = sample_rate;
0349     } else {
0350         aic23->requested_adc = sample_rate_adc = sample_rate;
0351         if (!sample_rate_dac)
0352             sample_rate_dac = sample_rate;
0353     }
0354     ret = set_sample_rate_control(component, aic23->mclk, sample_rate_adc,
0355             sample_rate_dac);
0356     if (ret < 0)
0357         return ret;
0358 
0359     iface_reg = snd_soc_component_read(component, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
0360 
0361     switch (params_width(params)) {
0362     case 16:
0363         break;
0364     case 20:
0365         iface_reg |= (0x01 << 2);
0366         break;
0367     case 24:
0368         iface_reg |= (0x02 << 2);
0369         break;
0370     case 32:
0371         iface_reg |= (0x03 << 2);
0372         break;
0373     }
0374     snd_soc_component_write(component, TLV320AIC23_DIGT_FMT, iface_reg);
0375 
0376     return 0;
0377 }
0378 
0379 static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
0380                    struct snd_soc_dai *dai)
0381 {
0382     struct snd_soc_component *component = dai->component;
0383 
0384     /* set active */
0385     snd_soc_component_write(component, TLV320AIC23_ACTIVE, 0x0001);
0386 
0387     return 0;
0388 }
0389 
0390 static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
0391                  struct snd_soc_dai *dai)
0392 {
0393     struct snd_soc_component *component = dai->component;
0394     struct aic23 *aic23 = snd_soc_component_get_drvdata(component);
0395 
0396     /* deactivate */
0397     if (!snd_soc_component_active(component)) {
0398         udelay(50);
0399         snd_soc_component_write(component, TLV320AIC23_ACTIVE, 0x0);
0400     }
0401     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
0402         aic23->requested_dac = 0;
0403     else
0404         aic23->requested_adc = 0;
0405 }
0406 
0407 static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute, int direction)
0408 {
0409     struct snd_soc_component *component = dai->component;
0410     u16 reg;
0411 
0412     reg = snd_soc_component_read(component, TLV320AIC23_DIGT);
0413     if (mute)
0414         reg |= TLV320AIC23_DACM_MUTE;
0415 
0416     else
0417         reg &= ~TLV320AIC23_DACM_MUTE;
0418 
0419     snd_soc_component_write(component, TLV320AIC23_DIGT, reg);
0420 
0421     return 0;
0422 }
0423 
0424 static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
0425                    unsigned int fmt)
0426 {
0427     struct snd_soc_component *component = codec_dai->component;
0428     u16 iface_reg;
0429 
0430     iface_reg = snd_soc_component_read(component, TLV320AIC23_DIGT_FMT) & (~0x03);
0431 
0432     switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
0433     case SND_SOC_DAIFMT_CBP_CFP:
0434         iface_reg |= TLV320AIC23_MS_MASTER;
0435         break;
0436     case SND_SOC_DAIFMT_CBC_CFC:
0437         iface_reg &= ~TLV320AIC23_MS_MASTER;
0438         break;
0439     default:
0440         return -EINVAL;
0441 
0442     }
0443 
0444     /* interface format */
0445     switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0446     case SND_SOC_DAIFMT_I2S:
0447         iface_reg |= TLV320AIC23_FOR_I2S;
0448         break;
0449     case SND_SOC_DAIFMT_DSP_A:
0450         iface_reg |= TLV320AIC23_LRP_ON;
0451         fallthrough;
0452     case SND_SOC_DAIFMT_DSP_B:
0453         iface_reg |= TLV320AIC23_FOR_DSP;
0454         break;
0455     case SND_SOC_DAIFMT_RIGHT_J:
0456         break;
0457     case SND_SOC_DAIFMT_LEFT_J:
0458         iface_reg |= TLV320AIC23_FOR_LJUST;
0459         break;
0460     default:
0461         return -EINVAL;
0462 
0463     }
0464 
0465     snd_soc_component_write(component, TLV320AIC23_DIGT_FMT, iface_reg);
0466 
0467     return 0;
0468 }
0469 
0470 static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
0471                       int clk_id, unsigned int freq, int dir)
0472 {
0473     struct aic23 *aic23 = snd_soc_dai_get_drvdata(codec_dai);
0474     aic23->mclk = freq;
0475     return 0;
0476 }
0477 
0478 static int tlv320aic23_set_bias_level(struct snd_soc_component *component,
0479                       enum snd_soc_bias_level level)
0480 {
0481     u16 reg = snd_soc_component_read(component, TLV320AIC23_PWR) & 0x17f;
0482 
0483     switch (level) {
0484     case SND_SOC_BIAS_ON:
0485         /* vref/mid, osc on, dac unmute */
0486         reg &= ~(TLV320AIC23_DEVICE_PWR_OFF | TLV320AIC23_OSC_OFF | \
0487             TLV320AIC23_DAC_OFF);
0488         snd_soc_component_write(component, TLV320AIC23_PWR, reg);
0489         break;
0490     case SND_SOC_BIAS_PREPARE:
0491         break;
0492     case SND_SOC_BIAS_STANDBY:
0493         /* everything off except vref/vmid, */
0494         snd_soc_component_write(component, TLV320AIC23_PWR,
0495                   reg | TLV320AIC23_CLK_OFF);
0496         break;
0497     case SND_SOC_BIAS_OFF:
0498         /* everything off, dac mute, inactive */
0499         snd_soc_component_write(component, TLV320AIC23_ACTIVE, 0x0);
0500         snd_soc_component_write(component, TLV320AIC23_PWR, 0x1ff);
0501         break;
0502     }
0503     return 0;
0504 }
0505 
0506 #define AIC23_RATES SNDRV_PCM_RATE_8000_96000
0507 #define AIC23_FORMATS   (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
0508              SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
0509 
0510 static const struct snd_soc_dai_ops tlv320aic23_dai_ops = {
0511     .prepare    = tlv320aic23_pcm_prepare,
0512     .hw_params  = tlv320aic23_hw_params,
0513     .shutdown   = tlv320aic23_shutdown,
0514     .mute_stream    = tlv320aic23_mute,
0515     .set_fmt    = tlv320aic23_set_dai_fmt,
0516     .set_sysclk = tlv320aic23_set_dai_sysclk,
0517     .no_capture_mute = 1,
0518 };
0519 
0520 static struct snd_soc_dai_driver tlv320aic23_dai = {
0521     .name = "tlv320aic23-hifi",
0522     .playback = {
0523              .stream_name = "Playback",
0524              .channels_min = 2,
0525              .channels_max = 2,
0526              .rates = AIC23_RATES,
0527              .formats = AIC23_FORMATS,},
0528     .capture = {
0529             .stream_name = "Capture",
0530             .channels_min = 2,
0531             .channels_max = 2,
0532             .rates = AIC23_RATES,
0533             .formats = AIC23_FORMATS,},
0534     .ops = &tlv320aic23_dai_ops,
0535 };
0536 
0537 static int tlv320aic23_resume(struct snd_soc_component *component)
0538 {
0539     struct aic23 *aic23 = snd_soc_component_get_drvdata(component);
0540     regcache_mark_dirty(aic23->regmap);
0541     regcache_sync(aic23->regmap);
0542 
0543     return 0;
0544 }
0545 
0546 static int tlv320aic23_component_probe(struct snd_soc_component *component)
0547 {
0548     /* Reset codec */
0549     snd_soc_component_write(component, TLV320AIC23_RESET, 0);
0550 
0551     snd_soc_component_write(component, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
0552 
0553     /* Unmute input */
0554     snd_soc_component_update_bits(component, TLV320AIC23_LINVOL,
0555                 TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED);
0556 
0557     snd_soc_component_update_bits(component, TLV320AIC23_RINVOL,
0558                 TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED);
0559 
0560     snd_soc_component_update_bits(component, TLV320AIC23_ANLG,
0561                 TLV320AIC23_BYPASS_ON | TLV320AIC23_MICM_MUTED,
0562                 0);
0563 
0564     /* Default output volume */
0565     snd_soc_component_write(component, TLV320AIC23_LCHNVOL,
0566               TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK);
0567     snd_soc_component_write(component, TLV320AIC23_RCHNVOL,
0568               TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK);
0569 
0570     snd_soc_component_write(component, TLV320AIC23_ACTIVE, 0x1);
0571 
0572     return 0;
0573 }
0574 
0575 static const struct snd_soc_component_driver soc_component_dev_tlv320aic23 = {
0576     .probe          = tlv320aic23_component_probe,
0577     .resume         = tlv320aic23_resume,
0578     .set_bias_level     = tlv320aic23_set_bias_level,
0579     .controls       = tlv320aic23_snd_controls,
0580     .num_controls       = ARRAY_SIZE(tlv320aic23_snd_controls),
0581     .dapm_widgets       = tlv320aic23_dapm_widgets,
0582     .num_dapm_widgets   = ARRAY_SIZE(tlv320aic23_dapm_widgets),
0583     .dapm_routes        = tlv320aic23_intercon,
0584     .num_dapm_routes    = ARRAY_SIZE(tlv320aic23_intercon),
0585     .suspend_bias_off   = 1,
0586     .idle_bias_on       = 1,
0587     .use_pmdown_time    = 1,
0588     .endianness     = 1,
0589 };
0590 
0591 int tlv320aic23_probe(struct device *dev, struct regmap *regmap)
0592 {
0593     struct aic23 *aic23;
0594 
0595     if (IS_ERR(regmap))
0596         return PTR_ERR(regmap);
0597 
0598     aic23 = devm_kzalloc(dev, sizeof(struct aic23), GFP_KERNEL);
0599     if (aic23 == NULL)
0600         return -ENOMEM;
0601 
0602     aic23->regmap = regmap;
0603 
0604     dev_set_drvdata(dev, aic23);
0605 
0606     return devm_snd_soc_register_component(dev,
0607                       &soc_component_dev_tlv320aic23,
0608                       &tlv320aic23_dai, 1);
0609 }
0610 EXPORT_SYMBOL(tlv320aic23_probe);
0611 
0612 MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
0613 MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
0614 MODULE_LICENSE("GPL");