Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * cs42l51.c
0004  *
0005  * ASoC Driver for Cirrus Logic CS42L51 codecs
0006  *
0007  * Copyright (c) 2010 Arnaud Patard <apatard@mandriva.com>
0008  *
0009  * Based on cs4270.c - Copyright (c) Freescale Semiconductor
0010  *
0011  * For now:
0012  *  - Only I2C is support. Not SPI
0013  *  - master mode *NOT* supported
0014  */
0015 
0016 #include <linux/clk.h>
0017 #include <linux/module.h>
0018 #include <linux/slab.h>
0019 #include <sound/core.h>
0020 #include <sound/soc.h>
0021 #include <sound/tlv.h>
0022 #include <sound/initval.h>
0023 #include <sound/pcm_params.h>
0024 #include <sound/pcm.h>
0025 #include <linux/gpio/consumer.h>
0026 #include <linux/regmap.h>
0027 #include <linux/regulator/consumer.h>
0028 
0029 #include "cs42l51.h"
0030 
0031 enum master_slave_mode {
0032     MODE_SLAVE,
0033     MODE_SLAVE_AUTO,
0034     MODE_MASTER,
0035 };
0036 
0037 static const char * const cs42l51_supply_names[] = {
0038     "VL",
0039     "VD",
0040     "VA",
0041     "VAHP",
0042 };
0043 
0044 struct cs42l51_private {
0045     unsigned int mclk;
0046     struct clk *mclk_handle;
0047     unsigned int audio_mode;    /* The mode (I2S or left-justified) */
0048     enum master_slave_mode func;
0049     struct regulator_bulk_data supplies[ARRAY_SIZE(cs42l51_supply_names)];
0050     struct gpio_desc *reset_gpio;
0051     struct regmap *regmap;
0052 };
0053 
0054 #define CS42L51_FORMATS (SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_S18_3LE | \
0055              SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
0056 
0057 static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
0058             struct snd_ctl_elem_value *ucontrol)
0059 {
0060     struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0061     unsigned long value = snd_soc_component_read(component, CS42L51_PCM_MIXER)&3;
0062 
0063     switch (value) {
0064     default:
0065     case 0:
0066         ucontrol->value.enumerated.item[0] = 0;
0067         break;
0068     /* same value : (L+R)/2 and (R+L)/2 */
0069     case 1:
0070     case 2:
0071         ucontrol->value.enumerated.item[0] = 1;
0072         break;
0073     case 3:
0074         ucontrol->value.enumerated.item[0] = 2;
0075         break;
0076     }
0077 
0078     return 0;
0079 }
0080 
0081 #define CHAN_MIX_NORMAL 0x00
0082 #define CHAN_MIX_BOTH   0x55
0083 #define CHAN_MIX_SWAP   0xFF
0084 
0085 static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol,
0086             struct snd_ctl_elem_value *ucontrol)
0087 {
0088     struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0089     unsigned char val;
0090 
0091     switch (ucontrol->value.enumerated.item[0]) {
0092     default:
0093     case 0:
0094         val = CHAN_MIX_NORMAL;
0095         break;
0096     case 1:
0097         val = CHAN_MIX_BOTH;
0098         break;
0099     case 2:
0100         val = CHAN_MIX_SWAP;
0101         break;
0102     }
0103 
0104     snd_soc_component_write(component, CS42L51_PCM_MIXER, val);
0105 
0106     return 1;
0107 }
0108 
0109 static const DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -5150, 50, 0);
0110 static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0);
0111 
0112 static const DECLARE_TLV_DB_SCALE(aout_tlv, -10200, 50, 0);
0113 
0114 static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0);
0115 static const DECLARE_TLV_DB_SCALE(adc_boost_tlv, 2000, 2000, 0);
0116 static const char *chan_mix[] = {
0117     "L R",
0118     "L+R",
0119     "R L",
0120 };
0121 
0122 static const DECLARE_TLV_DB_SCALE(pga_tlv, -300, 50, 0);
0123 static const DECLARE_TLV_DB_SCALE(adc_att_tlv, -9600, 100, 0);
0124 
0125 static SOC_ENUM_SINGLE_EXT_DECL(cs42l51_chan_mix, chan_mix);
0126 
0127 static const struct snd_kcontrol_new cs42l51_snd_controls[] = {
0128     SOC_DOUBLE_R_SX_TLV("PCM Playback Volume",
0129             CS42L51_PCMA_VOL, CS42L51_PCMB_VOL,
0130             0, 0x19, 0x7F, adc_pcm_tlv),
0131     SOC_DOUBLE_R("PCM Playback Switch",
0132             CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1),
0133     SOC_DOUBLE_R_SX_TLV("Analog Playback Volume",
0134             CS42L51_AOUTA_VOL, CS42L51_AOUTB_VOL,
0135             0, 0x34, 0xE4, aout_tlv),
0136     SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume",
0137             CS42L51_ADCA_VOL, CS42L51_ADCB_VOL,
0138             0, 0x19, 0x7F, adc_pcm_tlv),
0139     SOC_DOUBLE_R("ADC Mixer Switch",
0140             CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1),
0141     SOC_DOUBLE_R_SX_TLV("ADC Attenuator Volume",
0142             CS42L51_ADCA_ATT, CS42L51_ADCB_ATT,
0143             0, 0xA0, 96, adc_att_tlv),
0144     SOC_DOUBLE_R_SX_TLV("PGA Volume",
0145             CS42L51_ALC_PGA_CTL, CS42L51_ALC_PGB_CTL,
0146             0, 0x19, 30, pga_tlv),
0147     SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0),
0148     SOC_SINGLE("Auto-Mute Switch", CS42L51_DAC_CTL, 2, 1, 0),
0149     SOC_SINGLE("Soft Ramp Switch", CS42L51_DAC_CTL, 1, 1, 0),
0150     SOC_SINGLE("Zero Cross Switch", CS42L51_DAC_CTL, 0, 0, 0),
0151     SOC_DOUBLE_TLV("Mic Boost Volume",
0152             CS42L51_MIC_CTL, 0, 1, 1, 0, boost_tlv),
0153     SOC_DOUBLE_TLV("ADC Boost Volume",
0154                CS42L51_MIC_CTL, 5, 6, 1, 0, adc_boost_tlv),
0155     SOC_SINGLE_TLV("Bass Volume", CS42L51_TONE_CTL, 0, 0xf, 1, tone_tlv),
0156     SOC_SINGLE_TLV("Treble Volume", CS42L51_TONE_CTL, 4, 0xf, 1, tone_tlv),
0157     SOC_ENUM_EXT("PCM channel mixer",
0158             cs42l51_chan_mix,
0159             cs42l51_get_chan_mix, cs42l51_set_chan_mix),
0160 };
0161 
0162 /*
0163  * to power down, one must:
0164  * 1.) Enable the PDN bit
0165  * 2.) enable power-down for the select channels
0166  * 3.) disable the PDN bit.
0167  */
0168 static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w,
0169         struct snd_kcontrol *kcontrol, int event)
0170 {
0171     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0172 
0173     switch (event) {
0174     case SND_SOC_DAPM_PRE_PMD:
0175         snd_soc_component_update_bits(component, CS42L51_POWER_CTL1,
0176                     CS42L51_POWER_CTL1_PDN,
0177                     CS42L51_POWER_CTL1_PDN);
0178         break;
0179     default:
0180     case SND_SOC_DAPM_POST_PMD:
0181         snd_soc_component_update_bits(component, CS42L51_POWER_CTL1,
0182                     CS42L51_POWER_CTL1_PDN, 0);
0183         break;
0184     }
0185 
0186     return 0;
0187 }
0188 
0189 static const char *cs42l51_dac_names[] = {"Direct PCM",
0190     "DSP PCM", "ADC"};
0191 static SOC_ENUM_SINGLE_DECL(cs42l51_dac_mux_enum,
0192                 CS42L51_DAC_CTL, 6, cs42l51_dac_names);
0193 static const struct snd_kcontrol_new cs42l51_dac_mux_controls =
0194     SOC_DAPM_ENUM("Route", cs42l51_dac_mux_enum);
0195 
0196 static const char *cs42l51_adcl_names[] = {"AIN1 Left", "AIN2 Left",
0197     "MIC Left", "MIC+preamp Left"};
0198 static SOC_ENUM_SINGLE_DECL(cs42l51_adcl_mux_enum,
0199                 CS42L51_ADC_INPUT, 4, cs42l51_adcl_names);
0200 static const struct snd_kcontrol_new cs42l51_adcl_mux_controls =
0201     SOC_DAPM_ENUM("Route", cs42l51_adcl_mux_enum);
0202 
0203 static const char *cs42l51_adcr_names[] = {"AIN1 Right", "AIN2 Right",
0204     "MIC Right", "MIC+preamp Right"};
0205 static SOC_ENUM_SINGLE_DECL(cs42l51_adcr_mux_enum,
0206                 CS42L51_ADC_INPUT, 6, cs42l51_adcr_names);
0207 static const struct snd_kcontrol_new cs42l51_adcr_mux_controls =
0208     SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum);
0209 
0210 static const struct snd_soc_dapm_widget cs42l51_dapm_widgets[] = {
0211     SND_SOC_DAPM_SUPPLY("Mic Bias", CS42L51_MIC_POWER_CTL, 1, 1, NULL,
0212                 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0213     SND_SOC_DAPM_PGA_E("Left PGA", CS42L51_POWER_CTL1, 3, 1, NULL, 0,
0214         cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
0215     SND_SOC_DAPM_PGA_E("Right PGA", CS42L51_POWER_CTL1, 4, 1, NULL, 0,
0216         cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
0217     SND_SOC_DAPM_ADC_E("Left ADC", "Left HiFi Capture",
0218         CS42L51_POWER_CTL1, 1, 1,
0219         cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
0220     SND_SOC_DAPM_ADC_E("Right ADC", "Right HiFi Capture",
0221         CS42L51_POWER_CTL1, 2, 1,
0222         cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
0223     SND_SOC_DAPM_DAC_E("Left DAC", NULL, CS42L51_POWER_CTL1, 5, 1,
0224                cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
0225     SND_SOC_DAPM_DAC_E("Right DAC", NULL, CS42L51_POWER_CTL1, 6, 1,
0226                cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
0227 
0228     /* analog/mic */
0229     SND_SOC_DAPM_INPUT("AIN1L"),
0230     SND_SOC_DAPM_INPUT("AIN1R"),
0231     SND_SOC_DAPM_INPUT("AIN2L"),
0232     SND_SOC_DAPM_INPUT("AIN2R"),
0233     SND_SOC_DAPM_INPUT("MICL"),
0234     SND_SOC_DAPM_INPUT("MICR"),
0235 
0236     SND_SOC_DAPM_MIXER("Mic Preamp Left",
0237         CS42L51_MIC_POWER_CTL, 2, 1, NULL, 0),
0238     SND_SOC_DAPM_MIXER("Mic Preamp Right",
0239         CS42L51_MIC_POWER_CTL, 3, 1, NULL, 0),
0240 
0241     /* HP */
0242     SND_SOC_DAPM_OUTPUT("HPL"),
0243     SND_SOC_DAPM_OUTPUT("HPR"),
0244 
0245     /* mux */
0246     SND_SOC_DAPM_MUX("DAC Mux", SND_SOC_NOPM, 0, 0,
0247         &cs42l51_dac_mux_controls),
0248     SND_SOC_DAPM_MUX("PGA-ADC Mux Left", SND_SOC_NOPM, 0, 0,
0249         &cs42l51_adcl_mux_controls),
0250     SND_SOC_DAPM_MUX("PGA-ADC Mux Right", SND_SOC_NOPM, 0, 0,
0251         &cs42l51_adcr_mux_controls),
0252 };
0253 
0254 static int mclk_event(struct snd_soc_dapm_widget *w,
0255               struct snd_kcontrol *kcontrol, int event)
0256 {
0257     struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
0258     struct cs42l51_private *cs42l51 = snd_soc_component_get_drvdata(comp);
0259 
0260     switch (event) {
0261     case SND_SOC_DAPM_PRE_PMU:
0262         return clk_prepare_enable(cs42l51->mclk_handle);
0263     case SND_SOC_DAPM_POST_PMD:
0264         /* Delay mclk shutdown to fulfill power-down sequence requirements */
0265         msleep(20);
0266         clk_disable_unprepare(cs42l51->mclk_handle);
0267         break;
0268     }
0269 
0270     return 0;
0271 }
0272 
0273 static const struct snd_soc_dapm_widget cs42l51_dapm_mclk_widgets[] = {
0274     SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0, mclk_event,
0275                 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0276 };
0277 
0278 static const struct snd_soc_dapm_route cs42l51_routes[] = {
0279     {"HPL", NULL, "Left DAC"},
0280     {"HPR", NULL, "Right DAC"},
0281 
0282     {"Right DAC", NULL, "DAC Mux"},
0283     {"Left DAC", NULL, "DAC Mux"},
0284 
0285     {"DAC Mux", "Direct PCM", "Playback"},
0286     {"DAC Mux", "DSP PCM", "Playback"},
0287 
0288     {"Left ADC", NULL, "Left PGA"},
0289     {"Right ADC", NULL, "Right PGA"},
0290 
0291     {"Mic Preamp Left",  NULL,  "MICL"},
0292     {"Mic Preamp Right", NULL,  "MICR"},
0293 
0294     {"PGA-ADC Mux Left",  "AIN1 Left",        "AIN1L" },
0295     {"PGA-ADC Mux Left",  "AIN2 Left",        "AIN2L" },
0296     {"PGA-ADC Mux Left",  "MIC Left",         "MICL"  },
0297     {"PGA-ADC Mux Left",  "MIC+preamp Left",  "Mic Preamp Left" },
0298     {"PGA-ADC Mux Right", "AIN1 Right",       "AIN1R" },
0299     {"PGA-ADC Mux Right", "AIN2 Right",       "AIN2R" },
0300     {"PGA-ADC Mux Right", "MIC Right",        "MICR" },
0301     {"PGA-ADC Mux Right", "MIC+preamp Right", "Mic Preamp Right" },
0302 
0303     {"Left PGA", NULL, "PGA-ADC Mux Left"},
0304     {"Right PGA", NULL, "PGA-ADC Mux Right"},
0305 };
0306 
0307 static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
0308         unsigned int format)
0309 {
0310     struct snd_soc_component *component = codec_dai->component;
0311     struct cs42l51_private *cs42l51 = snd_soc_component_get_drvdata(component);
0312 
0313     switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
0314     case SND_SOC_DAIFMT_I2S:
0315     case SND_SOC_DAIFMT_LEFT_J:
0316     case SND_SOC_DAIFMT_RIGHT_J:
0317         cs42l51->audio_mode = format & SND_SOC_DAIFMT_FORMAT_MASK;
0318         break;
0319     default:
0320         dev_err(component->dev, "invalid DAI format\n");
0321         return -EINVAL;
0322     }
0323 
0324     switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
0325     case SND_SOC_DAIFMT_CBM_CFM:
0326         cs42l51->func = MODE_MASTER;
0327         break;
0328     case SND_SOC_DAIFMT_CBS_CFS:
0329         cs42l51->func = MODE_SLAVE_AUTO;
0330         break;
0331     default:
0332         dev_err(component->dev, "Unknown master/slave configuration\n");
0333         return -EINVAL;
0334     }
0335 
0336     return 0;
0337 }
0338 
0339 struct cs42l51_ratios {
0340     unsigned int ratio;
0341     unsigned char speed_mode;
0342     unsigned char mclk;
0343 };
0344 
0345 static struct cs42l51_ratios slave_ratios[] = {
0346     {  512, CS42L51_QSM_MODE, 0 }, {  768, CS42L51_QSM_MODE, 0 },
0347     { 1024, CS42L51_QSM_MODE, 0 }, { 1536, CS42L51_QSM_MODE, 0 },
0348     { 2048, CS42L51_QSM_MODE, 0 }, { 3072, CS42L51_QSM_MODE, 0 },
0349     {  256, CS42L51_HSM_MODE, 0 }, {  384, CS42L51_HSM_MODE, 0 },
0350     {  512, CS42L51_HSM_MODE, 0 }, {  768, CS42L51_HSM_MODE, 0 },
0351     { 1024, CS42L51_HSM_MODE, 0 }, { 1536, CS42L51_HSM_MODE, 0 },
0352     {  128, CS42L51_SSM_MODE, 0 }, {  192, CS42L51_SSM_MODE, 0 },
0353     {  256, CS42L51_SSM_MODE, 0 }, {  384, CS42L51_SSM_MODE, 0 },
0354     {  512, CS42L51_SSM_MODE, 0 }, {  768, CS42L51_SSM_MODE, 0 },
0355     {  128, CS42L51_DSM_MODE, 0 }, {  192, CS42L51_DSM_MODE, 0 },
0356     {  256, CS42L51_DSM_MODE, 0 }, {  384, CS42L51_DSM_MODE, 0 },
0357 };
0358 
0359 static struct cs42l51_ratios slave_auto_ratios[] = {
0360     { 1024, CS42L51_QSM_MODE, 0 }, { 1536, CS42L51_QSM_MODE, 0 },
0361     { 2048, CS42L51_QSM_MODE, 1 }, { 3072, CS42L51_QSM_MODE, 1 },
0362     {  512, CS42L51_HSM_MODE, 0 }, {  768, CS42L51_HSM_MODE, 0 },
0363     { 1024, CS42L51_HSM_MODE, 1 }, { 1536, CS42L51_HSM_MODE, 1 },
0364     {  256, CS42L51_SSM_MODE, 0 }, {  384, CS42L51_SSM_MODE, 0 },
0365     {  512, CS42L51_SSM_MODE, 1 }, {  768, CS42L51_SSM_MODE, 1 },
0366     {  128, CS42L51_DSM_MODE, 0 }, {  192, CS42L51_DSM_MODE, 0 },
0367     {  256, CS42L51_DSM_MODE, 1 }, {  384, CS42L51_DSM_MODE, 1 },
0368 };
0369 
0370 /*
0371  * Master mode mclk/fs ratios.
0372  * Recommended configurations are SSM for 4-50khz and DSM for 50-100kHz ranges
0373  * The table below provides support of following ratios:
0374  * 128: SSM (%128) with div2 disabled
0375  * 256: SSM (%128) with div2 enabled
0376  * In both cases, if sampling rate is above 50kHz, SSM is overridden
0377  * with DSM (%128) configuration
0378  */
0379 static struct cs42l51_ratios master_ratios[] = {
0380     { 128, CS42L51_SSM_MODE, 0 }, { 256, CS42L51_SSM_MODE, 1 },
0381 };
0382 
0383 static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai,
0384         int clk_id, unsigned int freq, int dir)
0385 {
0386     struct snd_soc_component *component = codec_dai->component;
0387     struct cs42l51_private *cs42l51 = snd_soc_component_get_drvdata(component);
0388 
0389     cs42l51->mclk = freq;
0390     return 0;
0391 }
0392 
0393 static int cs42l51_hw_params(struct snd_pcm_substream *substream,
0394         struct snd_pcm_hw_params *params,
0395         struct snd_soc_dai *dai)
0396 {
0397     struct snd_soc_component *component = dai->component;
0398     struct cs42l51_private *cs42l51 = snd_soc_component_get_drvdata(component);
0399     int ret;
0400     unsigned int i;
0401     unsigned int rate;
0402     unsigned int ratio;
0403     struct cs42l51_ratios *ratios = NULL;
0404     int nr_ratios = 0;
0405     int intf_ctl, power_ctl, fmt, mode;
0406 
0407     switch (cs42l51->func) {
0408     case MODE_MASTER:
0409         ratios = master_ratios;
0410         nr_ratios = ARRAY_SIZE(master_ratios);
0411         break;
0412     case MODE_SLAVE:
0413         ratios = slave_ratios;
0414         nr_ratios = ARRAY_SIZE(slave_ratios);
0415         break;
0416     case MODE_SLAVE_AUTO:
0417         ratios = slave_auto_ratios;
0418         nr_ratios = ARRAY_SIZE(slave_auto_ratios);
0419         break;
0420     }
0421 
0422     /* Figure out which MCLK/LRCK ratio to use */
0423     rate = params_rate(params);     /* Sampling rate, in Hz */
0424     ratio = cs42l51->mclk / rate;    /* MCLK/LRCK ratio */
0425     for (i = 0; i < nr_ratios; i++) {
0426         if (ratios[i].ratio == ratio)
0427             break;
0428     }
0429 
0430     if (i == nr_ratios) {
0431         /* We did not find a matching ratio */
0432         dev_err(component->dev, "could not find matching ratio\n");
0433         return -EINVAL;
0434     }
0435 
0436     intf_ctl = snd_soc_component_read(component, CS42L51_INTF_CTL);
0437     power_ctl = snd_soc_component_read(component, CS42L51_MIC_POWER_CTL);
0438 
0439     intf_ctl &= ~(CS42L51_INTF_CTL_MASTER | CS42L51_INTF_CTL_ADC_I2S
0440             | CS42L51_INTF_CTL_DAC_FORMAT(7));
0441     power_ctl &= ~(CS42L51_MIC_POWER_CTL_SPEED(3)
0442             | CS42L51_MIC_POWER_CTL_MCLK_DIV2);
0443 
0444     switch (cs42l51->func) {
0445     case MODE_MASTER:
0446         intf_ctl |= CS42L51_INTF_CTL_MASTER;
0447         mode = ratios[i].speed_mode;
0448         /* Force DSM mode if sampling rate is above 50kHz */
0449         if (rate > 50000)
0450             mode = CS42L51_DSM_MODE;
0451         power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(mode);
0452         /*
0453          * Auto detect mode is not applicable for master mode and has to
0454          * be disabled. Otherwise SPEED[1:0] bits will be ignored.
0455          */
0456         power_ctl &= ~CS42L51_MIC_POWER_CTL_AUTO;
0457         break;
0458     case MODE_SLAVE:
0459         power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode);
0460         break;
0461     case MODE_SLAVE_AUTO:
0462         power_ctl |= CS42L51_MIC_POWER_CTL_AUTO;
0463         break;
0464     }
0465 
0466     switch (cs42l51->audio_mode) {
0467     case SND_SOC_DAIFMT_I2S:
0468         intf_ctl |= CS42L51_INTF_CTL_ADC_I2S;
0469         intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_I2S);
0470         break;
0471     case SND_SOC_DAIFMT_LEFT_J:
0472         intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_LJ24);
0473         break;
0474     case SND_SOC_DAIFMT_RIGHT_J:
0475         switch (params_width(params)) {
0476         case 16:
0477             fmt = CS42L51_DAC_DIF_RJ16;
0478             break;
0479         case 18:
0480             fmt = CS42L51_DAC_DIF_RJ18;
0481             break;
0482         case 20:
0483             fmt = CS42L51_DAC_DIF_RJ20;
0484             break;
0485         case 24:
0486             fmt = CS42L51_DAC_DIF_RJ24;
0487             break;
0488         default:
0489             dev_err(component->dev, "unknown format\n");
0490             return -EINVAL;
0491         }
0492         intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(fmt);
0493         break;
0494     default:
0495         dev_err(component->dev, "unknown format\n");
0496         return -EINVAL;
0497     }
0498 
0499     if (ratios[i].mclk)
0500         power_ctl |= CS42L51_MIC_POWER_CTL_MCLK_DIV2;
0501 
0502     ret = snd_soc_component_write(component, CS42L51_INTF_CTL, intf_ctl);
0503     if (ret < 0)
0504         return ret;
0505 
0506     ret = snd_soc_component_write(component, CS42L51_MIC_POWER_CTL, power_ctl);
0507     if (ret < 0)
0508         return ret;
0509 
0510     return 0;
0511 }
0512 
0513 static int cs42l51_dai_mute(struct snd_soc_dai *dai, int mute, int direction)
0514 {
0515     struct snd_soc_component *component = dai->component;
0516     int reg;
0517     int mask = CS42L51_DAC_OUT_CTL_DACA_MUTE|CS42L51_DAC_OUT_CTL_DACB_MUTE;
0518 
0519     reg = snd_soc_component_read(component, CS42L51_DAC_OUT_CTL);
0520 
0521     if (mute)
0522         reg |= mask;
0523     else
0524         reg &= ~mask;
0525 
0526     return snd_soc_component_write(component, CS42L51_DAC_OUT_CTL, reg);
0527 }
0528 
0529 static int cs42l51_of_xlate_dai_id(struct snd_soc_component *component,
0530                    struct device_node *endpoint)
0531 {
0532     /* return dai id 0, whatever the endpoint index */
0533     return 0;
0534 }
0535 
0536 static const struct snd_soc_dai_ops cs42l51_dai_ops = {
0537     .hw_params      = cs42l51_hw_params,
0538     .set_sysclk     = cs42l51_set_dai_sysclk,
0539     .set_fmt        = cs42l51_set_dai_fmt,
0540     .mute_stream    = cs42l51_dai_mute,
0541     .no_capture_mute = 1,
0542 };
0543 
0544 static struct snd_soc_dai_driver cs42l51_dai = {
0545     .name = "cs42l51-hifi",
0546     .playback = {
0547         .stream_name = "Playback",
0548         .channels_min = 1,
0549         .channels_max = 2,
0550         .rates = SNDRV_PCM_RATE_8000_96000,
0551         .formats = CS42L51_FORMATS,
0552     },
0553     .capture = {
0554         .stream_name = "Capture",
0555         .channels_min = 1,
0556         .channels_max = 2,
0557         .rates = SNDRV_PCM_RATE_8000_96000,
0558         .formats = CS42L51_FORMATS,
0559     },
0560     .ops = &cs42l51_dai_ops,
0561 };
0562 
0563 static int cs42l51_component_probe(struct snd_soc_component *component)
0564 {
0565     int ret, reg;
0566     struct snd_soc_dapm_context *dapm;
0567     struct cs42l51_private *cs42l51;
0568 
0569     cs42l51 = snd_soc_component_get_drvdata(component);
0570     dapm = snd_soc_component_get_dapm(component);
0571 
0572     if (cs42l51->mclk_handle)
0573         snd_soc_dapm_new_controls(dapm, cs42l51_dapm_mclk_widgets, 1);
0574 
0575     /*
0576      * DAC configuration
0577      * - Use signal processor
0578      * - auto mute
0579      * - vol changes immediate
0580      * - no de-emphasize
0581      */
0582     reg = CS42L51_DAC_CTL_DATA_SEL(1)
0583         | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0);
0584     ret = snd_soc_component_write(component, CS42L51_DAC_CTL, reg);
0585     if (ret < 0)
0586         return ret;
0587 
0588     return 0;
0589 }
0590 
0591 static const struct snd_soc_component_driver soc_component_device_cs42l51 = {
0592     .probe          = cs42l51_component_probe,
0593     .controls       = cs42l51_snd_controls,
0594     .num_controls       = ARRAY_SIZE(cs42l51_snd_controls),
0595     .dapm_widgets       = cs42l51_dapm_widgets,
0596     .num_dapm_widgets   = ARRAY_SIZE(cs42l51_dapm_widgets),
0597     .dapm_routes        = cs42l51_routes,
0598     .num_dapm_routes    = ARRAY_SIZE(cs42l51_routes),
0599     .of_xlate_dai_id    = cs42l51_of_xlate_dai_id,
0600     .idle_bias_on       = 1,
0601     .use_pmdown_time    = 1,
0602     .endianness     = 1,
0603 };
0604 
0605 static bool cs42l51_writeable_reg(struct device *dev, unsigned int reg)
0606 {
0607     switch (reg) {
0608     case CS42L51_POWER_CTL1:
0609     case CS42L51_MIC_POWER_CTL:
0610     case CS42L51_INTF_CTL:
0611     case CS42L51_MIC_CTL:
0612     case CS42L51_ADC_CTL:
0613     case CS42L51_ADC_INPUT:
0614     case CS42L51_DAC_OUT_CTL:
0615     case CS42L51_DAC_CTL:
0616     case CS42L51_ALC_PGA_CTL:
0617     case CS42L51_ALC_PGB_CTL:
0618     case CS42L51_ADCA_ATT:
0619     case CS42L51_ADCB_ATT:
0620     case CS42L51_ADCA_VOL:
0621     case CS42L51_ADCB_VOL:
0622     case CS42L51_PCMA_VOL:
0623     case CS42L51_PCMB_VOL:
0624     case CS42L51_BEEP_FREQ:
0625     case CS42L51_BEEP_VOL:
0626     case CS42L51_BEEP_CONF:
0627     case CS42L51_TONE_CTL:
0628     case CS42L51_AOUTA_VOL:
0629     case CS42L51_AOUTB_VOL:
0630     case CS42L51_PCM_MIXER:
0631     case CS42L51_LIMIT_THRES_DIS:
0632     case CS42L51_LIMIT_REL:
0633     case CS42L51_LIMIT_ATT:
0634     case CS42L51_ALC_EN:
0635     case CS42L51_ALC_REL:
0636     case CS42L51_ALC_THRES:
0637     case CS42L51_NOISE_CONF:
0638     case CS42L51_CHARGE_FREQ:
0639         return true;
0640     default:
0641         return false;
0642     }
0643 }
0644 
0645 static bool cs42l51_volatile_reg(struct device *dev, unsigned int reg)
0646 {
0647     switch (reg) {
0648     case CS42L51_STATUS:
0649         return true;
0650     default:
0651         return false;
0652     }
0653 }
0654 
0655 static bool cs42l51_readable_reg(struct device *dev, unsigned int reg)
0656 {
0657     switch (reg) {
0658     case CS42L51_CHIP_REV_ID:
0659     case CS42L51_POWER_CTL1:
0660     case CS42L51_MIC_POWER_CTL:
0661     case CS42L51_INTF_CTL:
0662     case CS42L51_MIC_CTL:
0663     case CS42L51_ADC_CTL:
0664     case CS42L51_ADC_INPUT:
0665     case CS42L51_DAC_OUT_CTL:
0666     case CS42L51_DAC_CTL:
0667     case CS42L51_ALC_PGA_CTL:
0668     case CS42L51_ALC_PGB_CTL:
0669     case CS42L51_ADCA_ATT:
0670     case CS42L51_ADCB_ATT:
0671     case CS42L51_ADCA_VOL:
0672     case CS42L51_ADCB_VOL:
0673     case CS42L51_PCMA_VOL:
0674     case CS42L51_PCMB_VOL:
0675     case CS42L51_BEEP_FREQ:
0676     case CS42L51_BEEP_VOL:
0677     case CS42L51_BEEP_CONF:
0678     case CS42L51_TONE_CTL:
0679     case CS42L51_AOUTA_VOL:
0680     case CS42L51_AOUTB_VOL:
0681     case CS42L51_PCM_MIXER:
0682     case CS42L51_LIMIT_THRES_DIS:
0683     case CS42L51_LIMIT_REL:
0684     case CS42L51_LIMIT_ATT:
0685     case CS42L51_ALC_EN:
0686     case CS42L51_ALC_REL:
0687     case CS42L51_ALC_THRES:
0688     case CS42L51_NOISE_CONF:
0689     case CS42L51_STATUS:
0690     case CS42L51_CHARGE_FREQ:
0691         return true;
0692     default:
0693         return false;
0694     }
0695 }
0696 
0697 const struct regmap_config cs42l51_regmap = {
0698     .reg_bits = 8,
0699     .reg_stride = 1,
0700     .val_bits = 8,
0701     .use_single_write = true,
0702     .readable_reg = cs42l51_readable_reg,
0703     .volatile_reg = cs42l51_volatile_reg,
0704     .writeable_reg = cs42l51_writeable_reg,
0705     .max_register = CS42L51_CHARGE_FREQ,
0706     .cache_type = REGCACHE_RBTREE,
0707 };
0708 EXPORT_SYMBOL_GPL(cs42l51_regmap);
0709 
0710 int cs42l51_probe(struct device *dev, struct regmap *regmap)
0711 {
0712     struct cs42l51_private *cs42l51;
0713     unsigned int val;
0714     int ret, i;
0715 
0716     if (IS_ERR(regmap))
0717         return PTR_ERR(regmap);
0718 
0719     cs42l51 = devm_kzalloc(dev, sizeof(struct cs42l51_private),
0720                    GFP_KERNEL);
0721     if (!cs42l51)
0722         return -ENOMEM;
0723 
0724     dev_set_drvdata(dev, cs42l51);
0725     cs42l51->regmap = regmap;
0726 
0727     cs42l51->mclk_handle = devm_clk_get(dev, "MCLK");
0728     if (IS_ERR(cs42l51->mclk_handle)) {
0729         if (PTR_ERR(cs42l51->mclk_handle) != -ENOENT)
0730             return PTR_ERR(cs42l51->mclk_handle);
0731         cs42l51->mclk_handle = NULL;
0732     }
0733 
0734     for (i = 0; i < ARRAY_SIZE(cs42l51->supplies); i++)
0735         cs42l51->supplies[i].supply = cs42l51_supply_names[i];
0736 
0737     ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs42l51->supplies),
0738                       cs42l51->supplies);
0739     if (ret != 0) {
0740         dev_err(dev, "Failed to request supplies: %d\n", ret);
0741         return ret;
0742     }
0743 
0744     ret = regulator_bulk_enable(ARRAY_SIZE(cs42l51->supplies),
0745                     cs42l51->supplies);
0746     if (ret != 0) {
0747         dev_err(dev, "Failed to enable supplies: %d\n", ret);
0748         return ret;
0749     }
0750 
0751     cs42l51->reset_gpio = devm_gpiod_get_optional(dev, "reset",
0752                               GPIOD_OUT_LOW);
0753     if (IS_ERR(cs42l51->reset_gpio))
0754         return PTR_ERR(cs42l51->reset_gpio);
0755 
0756     if (cs42l51->reset_gpio) {
0757         dev_dbg(dev, "Release reset gpio\n");
0758         gpiod_set_value_cansleep(cs42l51->reset_gpio, 0);
0759         mdelay(2);
0760     }
0761 
0762     /* Verify that we have a CS42L51 */
0763     ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val);
0764     if (ret < 0) {
0765         dev_err(dev, "failed to read I2C\n");
0766         goto error;
0767     }
0768 
0769     if ((val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
0770         (val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
0771         dev_err(dev, "Invalid chip id: %x\n", val);
0772         ret = -ENODEV;
0773         goto error;
0774     }
0775     dev_info(dev, "Cirrus Logic CS42L51, Revision: %02X\n",
0776          val & CS42L51_CHIP_REV_MASK);
0777 
0778     ret = devm_snd_soc_register_component(dev,
0779             &soc_component_device_cs42l51, &cs42l51_dai, 1);
0780     if (ret < 0)
0781         goto error;
0782 
0783     return 0;
0784 
0785 error:
0786     regulator_bulk_disable(ARRAY_SIZE(cs42l51->supplies),
0787                    cs42l51->supplies);
0788     return ret;
0789 }
0790 EXPORT_SYMBOL_GPL(cs42l51_probe);
0791 
0792 void cs42l51_remove(struct device *dev)
0793 {
0794     struct cs42l51_private *cs42l51 = dev_get_drvdata(dev);
0795     int ret;
0796 
0797     gpiod_set_value_cansleep(cs42l51->reset_gpio, 1);
0798 
0799     ret = regulator_bulk_disable(ARRAY_SIZE(cs42l51->supplies),
0800                      cs42l51->supplies);
0801     if (ret)
0802         dev_warn(dev, "Failed to disable all regulators (%pe)\n",
0803              ERR_PTR(ret));
0804 
0805 }
0806 EXPORT_SYMBOL_GPL(cs42l51_remove);
0807 
0808 int __maybe_unused cs42l51_suspend(struct device *dev)
0809 {
0810     struct cs42l51_private *cs42l51 = dev_get_drvdata(dev);
0811 
0812     regcache_cache_only(cs42l51->regmap, true);
0813     regcache_mark_dirty(cs42l51->regmap);
0814 
0815     return 0;
0816 }
0817 EXPORT_SYMBOL_GPL(cs42l51_suspend);
0818 
0819 int __maybe_unused cs42l51_resume(struct device *dev)
0820 {
0821     struct cs42l51_private *cs42l51 = dev_get_drvdata(dev);
0822 
0823     regcache_cache_only(cs42l51->regmap, false);
0824 
0825     return regcache_sync(cs42l51->regmap);
0826 }
0827 EXPORT_SYMBOL_GPL(cs42l51_resume);
0828 
0829 const struct of_device_id cs42l51_of_match[] = {
0830     { .compatible = "cirrus,cs42l51", },
0831     { }
0832 };
0833 MODULE_DEVICE_TABLE(of, cs42l51_of_match);
0834 EXPORT_SYMBOL_GPL(cs42l51_of_match);
0835 
0836 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
0837 MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");
0838 MODULE_LICENSE("GPL");