410 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2 /*3 * Audio Codec driver supporting:4 * AD1835A, AD1836, AD1837A, AD1838A, AD1839A5 *6 * Copyright 2009-2011 Analog Devices Inc.7 */8 9#include <linux/init.h>10#include <linux/slab.h>11#include <linux/module.h>12#include <linux/kernel.h>13#include <linux/device.h>14#include <sound/core.h>15#include <sound/pcm.h>16#include <sound/pcm_params.h>17#include <sound/initval.h>18#include <sound/soc.h>19#include <sound/tlv.h>20#include <linux/spi/spi.h>21#include <linux/regmap.h>22 23#include "ad1836.h"24 25enum ad1836_type {26 AD1835,27 AD1836,28 AD1838,29};30 31/* codec private data */32struct ad1836_priv {33 enum ad1836_type type;34 struct regmap *regmap;35};36 37/*38 * AD1836 volume/mute/de-emphasis etc. controls39 */40static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"};41 42static SOC_ENUM_SINGLE_DECL(ad1836_deemp_enum,43 AD1836_DAC_CTRL1, 8, ad1836_deemp);44 45#define AD1836_DAC_VOLUME(x) \46 SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \47 AD1836_DAC_R_VOL(x), 0, 0x3FF, 0)48 49#define AD1836_DAC_SWITCH(x) \50 SOC_DOUBLE("DAC" #x " Playback Switch", AD1836_DAC_CTRL2, \51 AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1)52 53#define AD1836_ADC_SWITCH(x) \54 SOC_DOUBLE("ADC" #x " Capture Switch", AD1836_ADC_CTRL2, \55 AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1)56 57static const struct snd_kcontrol_new ad183x_dac_controls[] = {58 AD1836_DAC_VOLUME(1),59 AD1836_DAC_SWITCH(1),60 AD1836_DAC_VOLUME(2),61 AD1836_DAC_SWITCH(2),62 AD1836_DAC_VOLUME(3),63 AD1836_DAC_SWITCH(3),64 AD1836_DAC_VOLUME(4),65 AD1836_DAC_SWITCH(4),66};67 68static const struct snd_soc_dapm_widget ad183x_dac_dapm_widgets[] = {69 SND_SOC_DAPM_OUTPUT("DAC1OUT"),70 SND_SOC_DAPM_OUTPUT("DAC2OUT"),71 SND_SOC_DAPM_OUTPUT("DAC3OUT"),72 SND_SOC_DAPM_OUTPUT("DAC4OUT"),73};74 75static const struct snd_soc_dapm_route ad183x_dac_routes[] = {76 { "DAC1OUT", NULL, "DAC" },77 { "DAC2OUT", NULL, "DAC" },78 { "DAC3OUT", NULL, "DAC" },79 { "DAC4OUT", NULL, "DAC" },80};81 82static const struct snd_kcontrol_new ad183x_adc_controls[] = {83 AD1836_ADC_SWITCH(1),84 AD1836_ADC_SWITCH(2),85 AD1836_ADC_SWITCH(3),86};87 88static const struct snd_soc_dapm_widget ad183x_adc_dapm_widgets[] = {89 SND_SOC_DAPM_INPUT("ADC1IN"),90 SND_SOC_DAPM_INPUT("ADC2IN"),91};92 93static const struct snd_soc_dapm_route ad183x_adc_routes[] = {94 { "ADC", NULL, "ADC1IN" },95 { "ADC", NULL, "ADC2IN" },96};97 98static const struct snd_kcontrol_new ad183x_controls[] = {99 /* ADC high-pass filter */100 SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1,101 AD1836_ADC_HIGHPASS_FILTER, 1, 0),102 103 /* DAC de-emphasis */104 SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum),105};106 107static const struct snd_soc_dapm_widget ad183x_dapm_widgets[] = {108 SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1,109 AD1836_DAC_POWERDOWN, 1),110 SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),111 SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1,112 AD1836_ADC_POWERDOWN, 1, NULL, 0),113};114 115static const struct snd_soc_dapm_route ad183x_dapm_routes[] = {116 { "DAC", NULL, "ADC_PWR" },117 { "ADC", NULL, "ADC_PWR" },118};119 120static const DECLARE_TLV_DB_SCALE(ad1836_in_tlv, 0, 300, 0);121 122static const struct snd_kcontrol_new ad1836_controls[] = {123 SOC_DOUBLE_TLV("ADC2 Capture Volume", AD1836_ADC_CTRL1, 3, 0, 4, 0,124 ad1836_in_tlv),125};126 127/*128 * DAI ops entries129 */130 131static int ad1836_set_dai_fmt(struct snd_soc_dai *codec_dai,132 unsigned int fmt)133{134 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {135 /* at present, we support adc aux mode to interface with136 * blackfin sport tdm mode137 */138 case SND_SOC_DAIFMT_DSP_A:139 break;140 default:141 return -EINVAL;142 }143 144 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {145 case SND_SOC_DAIFMT_IB_IF:146 break;147 default:148 return -EINVAL;149 }150 151 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {152 /* ALCLK,ABCLK are both output, AD1836 can only be provider */153 case SND_SOC_DAIFMT_CBP_CFP:154 break;155 default:156 return -EINVAL;157 }158 159 return 0;160}161 162static int ad1836_hw_params(struct snd_pcm_substream *substream,163 struct snd_pcm_hw_params *params,164 struct snd_soc_dai *dai)165{166 struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(dai->component);167 int word_len = 0;168 169 /* bit size */170 switch (params_width(params)) {171 case 16:172 word_len = AD1836_WORD_LEN_16;173 break;174 case 20:175 word_len = AD1836_WORD_LEN_20;176 break;177 case 24:178 case 32:179 word_len = AD1836_WORD_LEN_24;180 break;181 default:182 return -EINVAL;183 }184 185 regmap_update_bits(ad1836->regmap, AD1836_DAC_CTRL1,186 AD1836_DAC_WORD_LEN_MASK,187 word_len << AD1836_DAC_WORD_LEN_OFFSET);188 189 regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,190 AD1836_ADC_WORD_LEN_MASK,191 word_len << AD1836_ADC_WORD_OFFSET);192 193 return 0;194}195 196static const struct snd_soc_dai_ops ad1836_dai_ops = {197 .hw_params = ad1836_hw_params,198 .set_fmt = ad1836_set_dai_fmt,199};200 201#define AD183X_DAI(_name, num_dacs, num_adcs) \202{ \203 .name = _name "-hifi", \204 .playback = { \205 .stream_name = "Playback", \206 .channels_min = 2, \207 .channels_max = (num_dacs) * 2, \208 .rates = SNDRV_PCM_RATE_48000, \209 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \210 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \211 }, \212 .capture = { \213 .stream_name = "Capture", \214 .channels_min = 2, \215 .channels_max = (num_adcs) * 2, \216 .rates = SNDRV_PCM_RATE_48000, \217 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \218 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \219 }, \220 .ops = &ad1836_dai_ops, \221}222 223static struct snd_soc_dai_driver ad183x_dais[] = {224 [AD1835] = AD183X_DAI("ad1835", 4, 1),225 [AD1836] = AD183X_DAI("ad1836", 3, 2),226 [AD1838] = AD183X_DAI("ad1838", 3, 1),227};228 229#ifdef CONFIG_PM230static int ad1836_suspend(struct snd_soc_component *component)231{232 struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);233 /* reset clock control mode */234 return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,235 AD1836_ADC_SERFMT_MASK, 0);236}237 238static int ad1836_resume(struct snd_soc_component *component)239{240 struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);241 /* restore clock control mode */242 return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,243 AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX);244}245#else246#define ad1836_suspend NULL247#define ad1836_resume NULL248#endif249 250static int ad1836_probe(struct snd_soc_component *component)251{252 struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);253 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);254 int num_dacs, num_adcs;255 int ret = 0;256 int i;257 258 num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2;259 num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2;260 261 /* default setting for ad1836 */262 /* de-emphasis: 48kHz, power-on dac */263 regmap_write(ad1836->regmap, AD1836_DAC_CTRL1, 0x300);264 /* unmute dac channels */265 regmap_write(ad1836->regmap, AD1836_DAC_CTRL2, 0x0);266 /* high-pass filter enable, power-on adc */267 regmap_write(ad1836->regmap, AD1836_ADC_CTRL1, 0x100);268 /* unmute adc channles, adc aux mode */269 regmap_write(ad1836->regmap, AD1836_ADC_CTRL2, 0x180);270 /* volume */271 for (i = 1; i <= num_dacs; ++i) {272 regmap_write(ad1836->regmap, AD1836_DAC_L_VOL(i), 0x3FF);273 regmap_write(ad1836->regmap, AD1836_DAC_R_VOL(i), 0x3FF);274 }275 276 if (ad1836->type == AD1836) {277 /* left/right diff:PGA/MUX */278 regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x3A);279 ret = snd_soc_add_component_controls(component, ad1836_controls,280 ARRAY_SIZE(ad1836_controls));281 if (ret)282 return ret;283 } else {284 regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x00);285 }286 287 ret = snd_soc_add_component_controls(component, ad183x_dac_controls, num_dacs * 2);288 if (ret)289 return ret;290 291 ret = snd_soc_add_component_controls(component, ad183x_adc_controls, num_adcs);292 if (ret)293 return ret;294 295 ret = snd_soc_dapm_new_controls(dapm, ad183x_dac_dapm_widgets, num_dacs);296 if (ret)297 return ret;298 299 ret = snd_soc_dapm_new_controls(dapm, ad183x_adc_dapm_widgets, num_adcs);300 if (ret)301 return ret;302 303 ret = snd_soc_dapm_add_routes(dapm, ad183x_dac_routes, num_dacs);304 if (ret)305 return ret;306 307 ret = snd_soc_dapm_add_routes(dapm, ad183x_adc_routes, num_adcs);308 309 return ret;310}311 312/* power down chip */313static void ad1836_remove(struct snd_soc_component *component)314{315 struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);316 /* reset clock control mode */317 regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,318 AD1836_ADC_SERFMT_MASK, 0);319}320 321static const struct snd_soc_component_driver soc_component_dev_ad1836 = {322 .probe = ad1836_probe,323 .remove = ad1836_remove,324 .suspend = ad1836_suspend,325 .resume = ad1836_resume,326 .controls = ad183x_controls,327 .num_controls = ARRAY_SIZE(ad183x_controls),328 .dapm_widgets = ad183x_dapm_widgets,329 .num_dapm_widgets = ARRAY_SIZE(ad183x_dapm_widgets),330 .dapm_routes = ad183x_dapm_routes,331 .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes),332 .idle_bias_on = 1,333 .use_pmdown_time = 1,334 .endianness = 1,335};336 337static const struct reg_default ad1836_reg_defaults[] = {338 { AD1836_DAC_CTRL1, 0x0000 },339 { AD1836_DAC_CTRL2, 0x0000 },340 { AD1836_DAC_L_VOL(0), 0x0000 },341 { AD1836_DAC_R_VOL(0), 0x0000 },342 { AD1836_DAC_L_VOL(1), 0x0000 },343 { AD1836_DAC_R_VOL(1), 0x0000 },344 { AD1836_DAC_L_VOL(2), 0x0000 },345 { AD1836_DAC_R_VOL(2), 0x0000 },346 { AD1836_DAC_L_VOL(3), 0x0000 },347 { AD1836_DAC_R_VOL(3), 0x0000 },348 { AD1836_ADC_CTRL1, 0x0000 },349 { AD1836_ADC_CTRL2, 0x0000 },350 { AD1836_ADC_CTRL3, 0x0000 },351};352 353static const struct regmap_config ad1836_regmap_config = {354 .val_bits = 12,355 .reg_bits = 4,356 .read_flag_mask = 0x08,357 358 .max_register = AD1836_ADC_CTRL3,359 .reg_defaults = ad1836_reg_defaults,360 .num_reg_defaults = ARRAY_SIZE(ad1836_reg_defaults),361 .cache_type = REGCACHE_MAPLE,362};363 364static int ad1836_spi_probe(struct spi_device *spi)365{366 struct ad1836_priv *ad1836;367 int ret;368 369 ad1836 = devm_kzalloc(&spi->dev, sizeof(struct ad1836_priv),370 GFP_KERNEL);371 if (ad1836 == NULL)372 return -ENOMEM;373 374 ad1836->regmap = devm_regmap_init_spi(spi, &ad1836_regmap_config);375 if (IS_ERR(ad1836->regmap))376 return PTR_ERR(ad1836->regmap);377 378 ad1836->type = spi_get_device_id(spi)->driver_data;379 380 spi_set_drvdata(spi, ad1836);381 382 ret = devm_snd_soc_register_component(&spi->dev,383 &soc_component_dev_ad1836, &ad183x_dais[ad1836->type], 1);384 return ret;385}386 387static const struct spi_device_id ad1836_ids[] = {388 { "ad1835", AD1835 },389 { "ad1836", AD1836 },390 { "ad1837", AD1835 },391 { "ad1838", AD1838 },392 { "ad1839", AD1838 },393 { },394};395MODULE_DEVICE_TABLE(spi, ad1836_ids);396 397static struct spi_driver ad1836_spi_driver = {398 .driver = {399 .name = "ad1836",400 },401 .probe = ad1836_spi_probe,402 .id_table = ad1836_ids,403};404 405module_spi_driver(ad1836_spi_driver);406 407MODULE_DESCRIPTION("ASoC ad1836 driver");408MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");409MODULE_LICENSE("GPL");410