Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * cs4349.c  --  CS4349 ALSA Soc Audio driver
0004  *
0005  * Copyright 2015 Cirrus Logic, Inc.
0006  *
0007  * Authors: Tim Howe <Tim.Howe@cirrus.com>
0008  */
0009 
0010 #include <linux/module.h>
0011 #include <linux/moduleparam.h>
0012 #include <linux/kernel.h>
0013 #include <linux/init.h>
0014 #include <linux/delay.h>
0015 #include <linux/gpio.h>
0016 #include <linux/gpio/consumer.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/pm.h>
0019 #include <linux/i2c.h>
0020 #include <linux/of_device.h>
0021 #include <linux/regmap.h>
0022 #include <linux/slab.h>
0023 #include <sound/core.h>
0024 #include <sound/pcm.h>
0025 #include <sound/pcm_params.h>
0026 #include <sound/soc.h>
0027 #include <sound/soc-dapm.h>
0028 #include <sound/initval.h>
0029 #include <sound/tlv.h>
0030 #include "cs4349.h"
0031 
0032 
0033 static const struct reg_default cs4349_reg_defaults[] = {
0034     { 2, 0x00 },    /* r02  - Mode Control */
0035     { 3, 0x09 },    /* r03  - Volume, Mixing and Inversion Control */
0036     { 4, 0x81 },    /* r04  - Mute Control */
0037     { 5, 0x00 },    /* r05  - Channel A Volume Control */
0038     { 6, 0x00 },    /* r06  - Channel B Volume Control */
0039     { 7, 0xB1 },    /* r07  - Ramp and Filter Control */
0040     { 8, 0x1C },    /* r08  - Misc. Control */
0041 };
0042 
0043 /* Private data for the CS4349 */
0044 struct  cs4349_private {
0045     struct regmap           *regmap;
0046     struct gpio_desc        *reset_gpio;
0047     unsigned int            mode;
0048     int             rate;
0049 };
0050 
0051 static bool cs4349_readable_register(struct device *dev, unsigned int reg)
0052 {
0053     switch (reg) {
0054     case CS4349_CHIPID ... CS4349_MISC:
0055         return true;
0056     default:
0057         return false;
0058     }
0059 }
0060 
0061 static bool cs4349_writeable_register(struct device *dev, unsigned int reg)
0062 {
0063     switch (reg) {
0064     case CS4349_MODE ...  CS4349_MISC:
0065         return true;
0066     default:
0067         return false;
0068     }
0069 }
0070 
0071 static int cs4349_set_dai_fmt(struct snd_soc_dai *codec_dai,
0072                   unsigned int format)
0073 {
0074     struct snd_soc_component *component = codec_dai->component;
0075     struct cs4349_private *cs4349 = snd_soc_component_get_drvdata(component);
0076     unsigned int fmt;
0077 
0078     fmt = format & SND_SOC_DAIFMT_FORMAT_MASK;
0079 
0080     switch (fmt) {
0081     case SND_SOC_DAIFMT_I2S:
0082     case SND_SOC_DAIFMT_LEFT_J:
0083     case SND_SOC_DAIFMT_RIGHT_J:
0084         cs4349->mode = format & SND_SOC_DAIFMT_FORMAT_MASK;
0085         break;
0086     default:
0087         return -EINVAL;
0088     }
0089 
0090     return 0;
0091 }
0092 
0093 static int cs4349_pcm_hw_params(struct snd_pcm_substream *substream,
0094                 struct snd_pcm_hw_params *params,
0095                 struct snd_soc_dai *dai)
0096 {
0097     struct snd_soc_component *component = dai->component;
0098     struct cs4349_private *cs4349 = snd_soc_component_get_drvdata(component);
0099     int fmt, ret;
0100 
0101     cs4349->rate = params_rate(params);
0102 
0103     switch (cs4349->mode) {
0104     case SND_SOC_DAIFMT_I2S:
0105         fmt = DIF_I2S;
0106         break;
0107     case SND_SOC_DAIFMT_LEFT_J:
0108         fmt = DIF_LEFT_JST;
0109         break;
0110     case SND_SOC_DAIFMT_RIGHT_J:
0111         switch (params_width(params)) {
0112         case 16:
0113             fmt = DIF_RGHT_JST16;
0114             break;
0115         case 24:
0116             fmt = DIF_RGHT_JST24;
0117             break;
0118         default:
0119             return -EINVAL;
0120         }
0121         break;
0122     default:
0123         return -EINVAL;
0124     }
0125 
0126     ret = snd_soc_component_update_bits(component, CS4349_MODE, DIF_MASK,
0127                   MODE_FORMAT(fmt));
0128     if (ret < 0)
0129         return ret;
0130 
0131     return 0;
0132 }
0133 
0134 static int cs4349_mute(struct snd_soc_dai *dai, int mute, int direction)
0135 {
0136     struct snd_soc_component *component = dai->component;
0137     int reg;
0138 
0139     reg = 0;
0140     if (mute)
0141         reg = MUTE_AB_MASK;
0142 
0143     return snd_soc_component_update_bits(component, CS4349_MUTE, MUTE_AB_MASK, reg);
0144 }
0145 
0146 static DECLARE_TLV_DB_SCALE(dig_tlv, -12750, 50, 0);
0147 
0148 static const char * const chan_mix_texts[] = {
0149     "Mute", "MuteA", "MuteA SwapB", "MuteA MonoB", "SwapA MuteB",
0150     "BothR", "Swap", "SwapA MonoB", "MuteB", "Normal", "BothL",
0151     "MonoB", "MonoA MuteB", "MonoA", "MonoA SwapB", "Mono",
0152     /*Normal == Channel A = Left, Channel B = Right*/
0153 };
0154 
0155 static const char * const fm_texts[] = {
0156     "Auto", "Single", "Double", "Quad",
0157 };
0158 
0159 static const char * const deemph_texts[] = {
0160     "None", "44.1k", "48k", "32k",
0161 };
0162 
0163 static const char * const softr_zeroc_texts[] = {
0164     "Immediate", "Zero Cross", "Soft Ramp", "SR on ZC",
0165 };
0166 
0167 static int deemph_values[] = {
0168     0, 4, 8, 12,
0169 };
0170 
0171 static int softr_zeroc_values[] = {
0172     0, 64, 128, 192,
0173 };
0174 
0175 static const struct soc_enum chan_mix_enum =
0176     SOC_ENUM_SINGLE(CS4349_VMI, 0,
0177             ARRAY_SIZE(chan_mix_texts),
0178             chan_mix_texts);
0179 
0180 static const struct soc_enum fm_mode_enum =
0181     SOC_ENUM_SINGLE(CS4349_MODE, 0,
0182             ARRAY_SIZE(fm_texts),
0183             fm_texts);
0184 
0185 static SOC_VALUE_ENUM_SINGLE_DECL(deemph_enum, CS4349_MODE, 0, DEM_MASK,
0186                 deemph_texts, deemph_values);
0187 
0188 static SOC_VALUE_ENUM_SINGLE_DECL(softr_zeroc_enum, CS4349_RMPFLT, 0,
0189                 SR_ZC_MASK, softr_zeroc_texts,
0190                 softr_zeroc_values);
0191 
0192 static const struct snd_kcontrol_new cs4349_snd_controls[] = {
0193     SOC_DOUBLE_R_TLV("Master Playback Volume",
0194              CS4349_VOLA, CS4349_VOLB, 0, 0xFF, 1, dig_tlv),
0195     SOC_ENUM("Functional Mode", fm_mode_enum),
0196     SOC_ENUM("De-Emphasis Control", deemph_enum),
0197     SOC_ENUM("Soft Ramp Zero Cross Control", softr_zeroc_enum),
0198     SOC_ENUM("Channel Mixer", chan_mix_enum),
0199     SOC_SINGLE("VolA = VolB Switch", CS4349_VMI, 7, 1, 0),
0200     SOC_SINGLE("InvertA Switch", CS4349_VMI, 6, 1, 0),
0201     SOC_SINGLE("InvertB Switch", CS4349_VMI, 5, 1, 0),
0202     SOC_SINGLE("Auto-Mute Switch", CS4349_MUTE, 7, 1, 0),
0203     SOC_SINGLE("MUTEC A = B Switch", CS4349_MUTE, 5, 1, 0),
0204     SOC_SINGLE("Soft Ramp Up Switch", CS4349_RMPFLT, 5, 1, 0),
0205     SOC_SINGLE("Soft Ramp Down Switch", CS4349_RMPFLT, 4, 1, 0),
0206     SOC_SINGLE("Slow Roll Off Filter Switch", CS4349_RMPFLT, 2, 1, 0),
0207     SOC_SINGLE("Freeze Switch", CS4349_MISC, 5, 1, 0),
0208     SOC_SINGLE("Popguard Switch", CS4349_MISC, 4, 1, 0),
0209 };
0210 
0211 static const struct snd_soc_dapm_widget cs4349_dapm_widgets[] = {
0212     SND_SOC_DAPM_DAC("HiFi DAC", NULL, SND_SOC_NOPM, 0, 0),
0213 
0214     SND_SOC_DAPM_OUTPUT("OutputA"),
0215     SND_SOC_DAPM_OUTPUT("OutputB"),
0216 };
0217 
0218 static const struct snd_soc_dapm_route cs4349_routes[] = {
0219     {"DAC Playback", NULL, "OutputA"},
0220     {"DAC Playback", NULL, "OutputB"},
0221 
0222     {"OutputA", NULL, "HiFi DAC"},
0223     {"OutputB", NULL, "HiFi DAC"},
0224 };
0225 
0226 #define CS4349_PCM_FORMATS (SNDRV_PCM_FMTBIT_S8  | SNDRV_PCM_FMTBIT_S16_LE  | \
0227             SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE | \
0228             SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE  | \
0229             SNDRV_PCM_FMTBIT_S32_LE)
0230 
0231 #define CS4349_PCM_RATES SNDRV_PCM_RATE_8000_192000
0232 
0233 static const struct snd_soc_dai_ops cs4349_dai_ops = {
0234     .hw_params  = cs4349_pcm_hw_params,
0235     .set_fmt    = cs4349_set_dai_fmt,
0236     .mute_stream    = cs4349_mute,
0237     .no_capture_mute = 1,
0238 };
0239 
0240 static struct snd_soc_dai_driver cs4349_dai = {
0241     .name = "cs4349_hifi",
0242     .playback = {
0243         .stream_name    = "DAC Playback",
0244         .channels_min   = 1,
0245         .channels_max   = 2,
0246         .rates      = CS4349_PCM_RATES,
0247         .formats    = CS4349_PCM_FORMATS,
0248     },
0249     .ops = &cs4349_dai_ops,
0250     .symmetric_rate = 1,
0251 };
0252 
0253 static const struct snd_soc_component_driver soc_component_dev_cs4349 = {
0254     .controls       = cs4349_snd_controls,
0255     .num_controls       = ARRAY_SIZE(cs4349_snd_controls),
0256     .dapm_widgets       = cs4349_dapm_widgets,
0257     .num_dapm_widgets   = ARRAY_SIZE(cs4349_dapm_widgets),
0258     .dapm_routes        = cs4349_routes,
0259     .num_dapm_routes    = ARRAY_SIZE(cs4349_routes),
0260     .idle_bias_on       = 1,
0261     .use_pmdown_time    = 1,
0262     .endianness     = 1,
0263 };
0264 
0265 static const struct regmap_config cs4349_regmap = {
0266     .reg_bits       = 8,
0267     .val_bits       = 8,
0268 
0269     .max_register       = CS4349_MISC,
0270     .reg_defaults       = cs4349_reg_defaults,
0271     .num_reg_defaults   = ARRAY_SIZE(cs4349_reg_defaults),
0272     .readable_reg       = cs4349_readable_register,
0273     .writeable_reg      = cs4349_writeable_register,
0274     .cache_type     = REGCACHE_RBTREE,
0275 };
0276 
0277 static int cs4349_i2c_probe(struct i2c_client *client)
0278 {
0279     struct cs4349_private *cs4349;
0280     int ret;
0281 
0282     cs4349 = devm_kzalloc(&client->dev, sizeof(*cs4349), GFP_KERNEL);
0283     if (!cs4349)
0284         return -ENOMEM;
0285 
0286     cs4349->regmap = devm_regmap_init_i2c(client, &cs4349_regmap);
0287     if (IS_ERR(cs4349->regmap)) {
0288         ret = PTR_ERR(cs4349->regmap);
0289         dev_err(&client->dev, "regmap_init() failed: %d\n", ret);
0290         return ret;
0291     }
0292 
0293     /* Reset the Device */
0294     cs4349->reset_gpio = devm_gpiod_get_optional(&client->dev,
0295         "reset", GPIOD_OUT_LOW);
0296     if (IS_ERR(cs4349->reset_gpio))
0297         return PTR_ERR(cs4349->reset_gpio);
0298 
0299     gpiod_set_value_cansleep(cs4349->reset_gpio, 1);
0300 
0301     i2c_set_clientdata(client, cs4349);
0302 
0303     return devm_snd_soc_register_component(&client->dev,
0304         &soc_component_dev_cs4349,
0305         &cs4349_dai, 1);
0306 }
0307 
0308 static int cs4349_i2c_remove(struct i2c_client *client)
0309 {
0310     struct cs4349_private *cs4349 = i2c_get_clientdata(client);
0311 
0312     /* Hold down reset */
0313     gpiod_set_value_cansleep(cs4349->reset_gpio, 0);
0314 
0315     return 0;
0316 }
0317 
0318 #ifdef CONFIG_PM
0319 static int cs4349_runtime_suspend(struct device *dev)
0320 {
0321     struct cs4349_private *cs4349 = dev_get_drvdata(dev);
0322     int ret;
0323 
0324     ret = regmap_update_bits(cs4349->regmap, CS4349_MISC, PWR_DWN, PWR_DWN);
0325     if (ret < 0)
0326         return ret;
0327 
0328     regcache_cache_only(cs4349->regmap, true);
0329 
0330     /* Hold down reset */
0331     gpiod_set_value_cansleep(cs4349->reset_gpio, 0);
0332 
0333     return 0;
0334 }
0335 
0336 static int cs4349_runtime_resume(struct device *dev)
0337 {
0338     struct cs4349_private *cs4349 = dev_get_drvdata(dev);
0339     int ret;
0340 
0341     ret = regmap_update_bits(cs4349->regmap, CS4349_MISC, PWR_DWN, 0);
0342     if (ret < 0)
0343         return ret;
0344 
0345     gpiod_set_value_cansleep(cs4349->reset_gpio, 1);
0346 
0347     regcache_cache_only(cs4349->regmap, false);
0348     regcache_sync(cs4349->regmap);
0349 
0350     return 0;
0351 }
0352 #endif
0353 
0354 static const struct dev_pm_ops cs4349_runtime_pm = {
0355     SET_RUNTIME_PM_OPS(cs4349_runtime_suspend, cs4349_runtime_resume,
0356                NULL)
0357 };
0358 
0359 static const struct of_device_id cs4349_of_match[] = {
0360     { .compatible = "cirrus,cs4349", },
0361     {},
0362 };
0363 
0364 MODULE_DEVICE_TABLE(of, cs4349_of_match);
0365 
0366 static const struct i2c_device_id cs4349_i2c_id[] = {
0367     {"cs4349", 0},
0368     {}
0369 };
0370 
0371 MODULE_DEVICE_TABLE(i2c, cs4349_i2c_id);
0372 
0373 static struct i2c_driver cs4349_i2c_driver = {
0374     .driver = {
0375         .name       = "cs4349",
0376         .of_match_table = cs4349_of_match,
0377         .pm = &cs4349_runtime_pm,
0378     },
0379     .id_table   = cs4349_i2c_id,
0380     .probe_new  = cs4349_i2c_probe,
0381     .remove     = cs4349_i2c_remove,
0382 };
0383 
0384 module_i2c_driver(cs4349_i2c_driver);
0385 
0386 MODULE_AUTHOR("Tim Howe <tim.howe@cirrus.com>");
0387 MODULE_DESCRIPTION("Cirrus Logic CS4349 ALSA SoC Codec Driver");
0388 MODULE_LICENSE("GPL");