root/sound/soc/codecs/wm8523.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wm8523_volatile_register
  2. wm8523_startup
  3. wm8523_hw_params
  4. wm8523_set_dai_sysclk
  5. wm8523_set_dai_fmt
  6. wm8523_set_bias_level
  7. wm8523_probe
  8. wm8523_i2c_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * wm8523.c  --  WM8523 ALSA SoC Audio driver
   4  *
   5  * Copyright 2009 Wolfson Microelectronics plc
   6  *
   7  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
   8  */
   9 
  10 #include <linux/module.h>
  11 #include <linux/moduleparam.h>
  12 #include <linux/init.h>
  13 #include <linux/delay.h>
  14 #include <linux/pm.h>
  15 #include <linux/i2c.h>
  16 #include <linux/regmap.h>
  17 #include <linux/regulator/consumer.h>
  18 #include <linux/slab.h>
  19 #include <linux/of_device.h>
  20 #include <sound/core.h>
  21 #include <sound/pcm.h>
  22 #include <sound/pcm_params.h>
  23 #include <sound/soc.h>
  24 #include <sound/initval.h>
  25 #include <sound/tlv.h>
  26 
  27 #include "wm8523.h"
  28 
  29 #define WM8523_NUM_SUPPLIES 2
  30 static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
  31         "AVDD",
  32         "LINEVDD",
  33 };
  34 
  35 #define WM8523_NUM_RATES 7
  36 
  37 /* codec private data */
  38 struct wm8523_priv {
  39         struct regmap *regmap;
  40         struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];
  41         unsigned int sysclk;
  42         unsigned int rate_constraint_list[WM8523_NUM_RATES];
  43         struct snd_pcm_hw_constraint_list rate_constraint;
  44 };
  45 
  46 static const struct reg_default wm8523_reg_defaults[] = {
  47         { 2, 0x0000 },     /* R2 - PSCTRL1 */
  48         { 3, 0x1812 },     /* R3 - AIF_CTRL1 */
  49         { 4, 0x0000 },     /* R4 - AIF_CTRL2 */
  50         { 5, 0x0001 },     /* R5 - DAC_CTRL3 */
  51         { 6, 0x0190 },     /* R6 - DAC_GAINL */
  52         { 7, 0x0190 },     /* R7 - DAC_GAINR */
  53         { 8, 0x0000 },     /* R8 - ZERO_DETECT */
  54 };
  55 
  56 static bool wm8523_volatile_register(struct device *dev, unsigned int reg)
  57 {
  58         switch (reg) {
  59         case WM8523_DEVICE_ID:
  60         case WM8523_REVISION:
  61                 return true;
  62         default:
  63                 return false;
  64         }
  65 }
  66 
  67 static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0);
  68 
  69 static const char *wm8523_zd_count_text[] = {
  70         "1024",
  71         "2048",
  72 };
  73 
  74 static SOC_ENUM_SINGLE_DECL(wm8523_zc_count, WM8523_ZERO_DETECT, 0,
  75                             wm8523_zd_count_text);
  76 
  77 static const struct snd_kcontrol_new wm8523_controls[] = {
  78 SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR,
  79                  0, 448, 0, dac_tlv),
  80 SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0),
  81 SOC_SINGLE("Playback Deemphasis Switch", WM8523_AIF_CTRL1, 8, 1, 0),
  82 SOC_DOUBLE("Playback Switch", WM8523_DAC_CTRL3, 2, 3, 1, 1),
  83 SOC_SINGLE("Volume Ramp Up Switch", WM8523_DAC_CTRL3, 1, 1, 0),
  84 SOC_SINGLE("Volume Ramp Down Switch", WM8523_DAC_CTRL3, 0, 1, 0),
  85 SOC_ENUM("Zero Detect Count", wm8523_zc_count),
  86 };
  87 
  88 static const struct snd_soc_dapm_widget wm8523_dapm_widgets[] = {
  89 SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
  90 SND_SOC_DAPM_OUTPUT("LINEVOUTL"),
  91 SND_SOC_DAPM_OUTPUT("LINEVOUTR"),
  92 };
  93 
  94 static const struct snd_soc_dapm_route wm8523_dapm_routes[] = {
  95         { "LINEVOUTL", NULL, "DAC" },
  96         { "LINEVOUTR", NULL, "DAC" },
  97 };
  98 
  99 static const struct {
 100         int value;
 101         int ratio;
 102 } lrclk_ratios[WM8523_NUM_RATES] = {
 103         { 1, 128 },
 104         { 2, 192 },
 105         { 3, 256 },
 106         { 4, 384 },
 107         { 5, 512 },
 108         { 6, 768 },
 109         { 7, 1152 },
 110 };
 111 
 112 static const struct {
 113         int value;
 114         int ratio;
 115 } bclk_ratios[] = {
 116         { 2, 32 },
 117         { 3, 64 },
 118         { 4, 128 },
 119 };
 120 
 121 static int wm8523_startup(struct snd_pcm_substream *substream,
 122                           struct snd_soc_dai *dai)
 123 {
 124         struct snd_soc_component *component = dai->component;
 125         struct wm8523_priv *wm8523 = snd_soc_component_get_drvdata(component);
 126 
 127         /* The set of sample rates that can be supported depends on the
 128          * MCLK supplied to the CODEC - enforce this.
 129          */
 130         if (!wm8523->sysclk) {
 131                 dev_err(component->dev,
 132                         "No MCLK configured, call set_sysclk() on init\n");
 133                 return -EINVAL;
 134         }
 135 
 136         snd_pcm_hw_constraint_list(substream->runtime, 0,
 137                                    SNDRV_PCM_HW_PARAM_RATE,
 138                                    &wm8523->rate_constraint);
 139 
 140         return 0;
 141 }
 142 
 143 static int wm8523_hw_params(struct snd_pcm_substream *substream,
 144                             struct snd_pcm_hw_params *params,
 145                             struct snd_soc_dai *dai)
 146 {
 147         struct snd_soc_component *component = dai->component;
 148         struct wm8523_priv *wm8523 = snd_soc_component_get_drvdata(component);
 149         int i;
 150         u16 aifctrl1 = snd_soc_component_read32(component, WM8523_AIF_CTRL1);
 151         u16 aifctrl2 = snd_soc_component_read32(component, WM8523_AIF_CTRL2);
 152 
 153         /* Find a supported LRCLK ratio */
 154         for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
 155                 if (wm8523->sysclk / params_rate(params) ==
 156                     lrclk_ratios[i].ratio)
 157                         break;
 158         }
 159 
 160         /* Should never happen, should be handled by constraints */
 161         if (i == ARRAY_SIZE(lrclk_ratios)) {
 162                 dev_err(component->dev, "MCLK/fs ratio %d unsupported\n",
 163                         wm8523->sysclk / params_rate(params));
 164                 return -EINVAL;
 165         }
 166 
 167         aifctrl2 &= ~WM8523_SR_MASK;
 168         aifctrl2 |= lrclk_ratios[i].value;
 169 
 170         if (aifctrl1 & WM8523_AIF_MSTR) {
 171                 /* Find a fs->bclk ratio */
 172                 for (i = 0; i < ARRAY_SIZE(bclk_ratios); i++)
 173                         if (params_width(params) * 2 <= bclk_ratios[i].ratio)
 174                                 break;
 175 
 176                 if (i == ARRAY_SIZE(bclk_ratios)) {
 177                         dev_err(component->dev,
 178                                 "No matching BCLK/fs ratio for word length %d\n",
 179                                 params_width(params));
 180                         return -EINVAL;
 181                 }
 182 
 183                 aifctrl2 &= ~WM8523_BCLKDIV_MASK;
 184                 aifctrl2 |= bclk_ratios[i].value << WM8523_BCLKDIV_SHIFT;
 185         }
 186 
 187         aifctrl1 &= ~WM8523_WL_MASK;
 188         switch (params_width(params)) {
 189         case 16:
 190                 break;
 191         case 20:
 192                 aifctrl1 |= 0x8;
 193                 break;
 194         case 24:
 195                 aifctrl1 |= 0x10;
 196                 break;
 197         case 32:
 198                 aifctrl1 |= 0x18;
 199                 break;
 200         }
 201 
 202         snd_soc_component_write(component, WM8523_AIF_CTRL1, aifctrl1);
 203         snd_soc_component_write(component, WM8523_AIF_CTRL2, aifctrl2);
 204 
 205         return 0;
 206 }
 207 
 208 static int wm8523_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 209                 int clk_id, unsigned int freq, int dir)
 210 {
 211         struct snd_soc_component *component = codec_dai->component;
 212         struct wm8523_priv *wm8523 = snd_soc_component_get_drvdata(component);
 213         unsigned int val;
 214         int i;
 215 
 216         wm8523->sysclk = freq;
 217 
 218         wm8523->rate_constraint.count = 0;
 219         for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
 220                 val = freq / lrclk_ratios[i].ratio;
 221                 /* Check that it's a standard rate since core can't
 222                  * cope with others and having the odd rates confuses
 223                  * constraint matching.
 224                  */
 225                 switch (val) {
 226                 case 8000:
 227                 case 11025:
 228                 case 16000:
 229                 case 22050:
 230                 case 32000:
 231                 case 44100:
 232                 case 48000:
 233                 case 64000:
 234                 case 88200:
 235                 case 96000:
 236                 case 176400:
 237                 case 192000:
 238                         dev_dbg(component->dev, "Supported sample rate: %dHz\n",
 239                                 val);
 240                         wm8523->rate_constraint_list[i] = val;
 241                         wm8523->rate_constraint.count++;
 242                         break;
 243                 default:
 244                         dev_dbg(component->dev, "Skipping sample rate: %dHz\n",
 245                                 val);
 246                 }
 247         }
 248 
 249         /* Need at least one supported rate... */
 250         if (wm8523->rate_constraint.count == 0)
 251                 return -EINVAL;
 252 
 253         return 0;
 254 }
 255 
 256 
 257 static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai,
 258                 unsigned int fmt)
 259 {
 260         struct snd_soc_component *component = codec_dai->component;
 261         u16 aifctrl1 = snd_soc_component_read32(component, WM8523_AIF_CTRL1);
 262 
 263         aifctrl1 &= ~(WM8523_BCLK_INV_MASK | WM8523_LRCLK_INV_MASK |
 264                       WM8523_FMT_MASK | WM8523_AIF_MSTR_MASK);
 265 
 266         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 267         case SND_SOC_DAIFMT_CBM_CFM:
 268                 aifctrl1 |= WM8523_AIF_MSTR;
 269                 break;
 270         case SND_SOC_DAIFMT_CBS_CFS:
 271                 break;
 272         default:
 273                 return -EINVAL;
 274         }
 275 
 276         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 277         case SND_SOC_DAIFMT_I2S:
 278                 aifctrl1 |= 0x0002;
 279                 break;
 280         case SND_SOC_DAIFMT_RIGHT_J:
 281                 break;
 282         case SND_SOC_DAIFMT_LEFT_J:
 283                 aifctrl1 |= 0x0001;
 284                 break;
 285         case SND_SOC_DAIFMT_DSP_A:
 286                 aifctrl1 |= 0x0003;
 287                 break;
 288         case SND_SOC_DAIFMT_DSP_B:
 289                 aifctrl1 |= 0x0023;
 290                 break;
 291         default:
 292                 return -EINVAL;
 293         }
 294 
 295         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 296         case SND_SOC_DAIFMT_NB_NF:
 297                 break;
 298         case SND_SOC_DAIFMT_IB_IF:
 299                 aifctrl1 |= WM8523_BCLK_INV | WM8523_LRCLK_INV;
 300                 break;
 301         case SND_SOC_DAIFMT_IB_NF:
 302                 aifctrl1 |= WM8523_BCLK_INV;
 303                 break;
 304         case SND_SOC_DAIFMT_NB_IF:
 305                 aifctrl1 |= WM8523_LRCLK_INV;
 306                 break;
 307         default:
 308                 return -EINVAL;
 309         }
 310 
 311         snd_soc_component_write(component, WM8523_AIF_CTRL1, aifctrl1);
 312 
 313         return 0;
 314 }
 315 
 316 static int wm8523_set_bias_level(struct snd_soc_component *component,
 317                                  enum snd_soc_bias_level level)
 318 {
 319         struct wm8523_priv *wm8523 = snd_soc_component_get_drvdata(component);
 320         int ret;
 321 
 322         switch (level) {
 323         case SND_SOC_BIAS_ON:
 324                 break;
 325 
 326         case SND_SOC_BIAS_PREPARE:
 327                 /* Full power on */
 328                 snd_soc_component_update_bits(component, WM8523_PSCTRL1,
 329                                     WM8523_SYS_ENA_MASK, 3);
 330                 break;
 331 
 332         case SND_SOC_BIAS_STANDBY:
 333                 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
 334                         ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
 335                                                     wm8523->supplies);
 336                         if (ret != 0) {
 337                                 dev_err(component->dev,
 338                                         "Failed to enable supplies: %d\n",
 339                                         ret);
 340                                 return ret;
 341                         }
 342 
 343                         /* Sync back default/cached values */
 344                         regcache_sync(wm8523->regmap);
 345 
 346                         /* Initial power up */
 347                         snd_soc_component_update_bits(component, WM8523_PSCTRL1,
 348                                             WM8523_SYS_ENA_MASK, 1);
 349 
 350                         msleep(100);
 351                 }
 352 
 353                 /* Power up to mute */
 354                 snd_soc_component_update_bits(component, WM8523_PSCTRL1,
 355                                     WM8523_SYS_ENA_MASK, 2);
 356 
 357                 break;
 358 
 359         case SND_SOC_BIAS_OFF:
 360                 /* The chip runs through the power down sequence for us. */
 361                 snd_soc_component_update_bits(component, WM8523_PSCTRL1,
 362                                     WM8523_SYS_ENA_MASK, 0);
 363                 msleep(100);
 364 
 365                 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies),
 366                                        wm8523->supplies);
 367                 break;
 368         }
 369         return 0;
 370 }
 371 
 372 #define WM8523_RATES SNDRV_PCM_RATE_8000_192000
 373 
 374 #define WM8523_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 375                         SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 376 
 377 static const struct snd_soc_dai_ops wm8523_dai_ops = {
 378         .startup        = wm8523_startup,
 379         .hw_params      = wm8523_hw_params,
 380         .set_sysclk     = wm8523_set_dai_sysclk,
 381         .set_fmt        = wm8523_set_dai_fmt,
 382 };
 383 
 384 static struct snd_soc_dai_driver wm8523_dai = {
 385         .name = "wm8523-hifi",
 386         .playback = {
 387                 .stream_name = "Playback",
 388                 .channels_min = 2,  /* Mono modes not yet supported */
 389                 .channels_max = 2,
 390                 .rates = WM8523_RATES,
 391                 .formats = WM8523_FORMATS,
 392         },
 393         .ops = &wm8523_dai_ops,
 394 };
 395 
 396 static int wm8523_probe(struct snd_soc_component *component)
 397 {
 398         struct wm8523_priv *wm8523 = snd_soc_component_get_drvdata(component);
 399 
 400         wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
 401         wm8523->rate_constraint.count =
 402                 ARRAY_SIZE(wm8523->rate_constraint_list);
 403 
 404         /* Change some default settings - latch VU and enable ZC */
 405         snd_soc_component_update_bits(component, WM8523_DAC_GAINR,
 406                             WM8523_DACR_VU, WM8523_DACR_VU);
 407         snd_soc_component_update_bits(component, WM8523_DAC_CTRL3, WM8523_ZC, WM8523_ZC);
 408 
 409         return 0;
 410 }
 411 
 412 static const struct snd_soc_component_driver soc_component_dev_wm8523 = {
 413         .probe                  = wm8523_probe,
 414         .set_bias_level         = wm8523_set_bias_level,
 415         .controls               = wm8523_controls,
 416         .num_controls           = ARRAY_SIZE(wm8523_controls),
 417         .dapm_widgets           = wm8523_dapm_widgets,
 418         .num_dapm_widgets       = ARRAY_SIZE(wm8523_dapm_widgets),
 419         .dapm_routes            = wm8523_dapm_routes,
 420         .num_dapm_routes        = ARRAY_SIZE(wm8523_dapm_routes),
 421         .suspend_bias_off       = 1,
 422         .idle_bias_on           = 1,
 423         .use_pmdown_time        = 1,
 424         .endianness             = 1,
 425         .non_legacy_dai_naming  = 1,
 426 };
 427 
 428 static const struct of_device_id wm8523_of_match[] = {
 429         { .compatible = "wlf,wm8523" },
 430         { },
 431 };
 432 MODULE_DEVICE_TABLE(of, wm8523_of_match);
 433 
 434 static const struct regmap_config wm8523_regmap = {
 435         .reg_bits = 8,
 436         .val_bits = 16,
 437         .max_register = WM8523_ZERO_DETECT,
 438 
 439         .reg_defaults = wm8523_reg_defaults,
 440         .num_reg_defaults = ARRAY_SIZE(wm8523_reg_defaults),
 441         .cache_type = REGCACHE_RBTREE,
 442 
 443         .volatile_reg = wm8523_volatile_register,
 444 };
 445 
 446 static int wm8523_i2c_probe(struct i2c_client *i2c,
 447                             const struct i2c_device_id *id)
 448 {
 449         struct wm8523_priv *wm8523;
 450         unsigned int val;
 451         int ret, i;
 452 
 453         wm8523 = devm_kzalloc(&i2c->dev, sizeof(struct wm8523_priv),
 454                               GFP_KERNEL);
 455         if (wm8523 == NULL)
 456                 return -ENOMEM;
 457 
 458         wm8523->regmap = devm_regmap_init_i2c(i2c, &wm8523_regmap);
 459         if (IS_ERR(wm8523->regmap)) {
 460                 ret = PTR_ERR(wm8523->regmap);
 461                 dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret);
 462                 return ret;
 463         }
 464 
 465         for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++)
 466                 wm8523->supplies[i].supply = wm8523_supply_names[i];
 467 
 468         ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8523->supplies),
 469                                       wm8523->supplies);
 470         if (ret != 0) {
 471                 dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
 472                 return ret;
 473         }
 474 
 475         ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
 476                                     wm8523->supplies);
 477         if (ret != 0) {
 478                 dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
 479                 return ret;
 480         }
 481 
 482         ret = regmap_read(wm8523->regmap, WM8523_DEVICE_ID, &val);
 483         if (ret < 0) {
 484                 dev_err(&i2c->dev, "Failed to read ID register\n");
 485                 goto err_enable;
 486         }
 487         if (val != 0x8523) {
 488                 dev_err(&i2c->dev, "Device is not a WM8523, ID is %x\n", ret);
 489                 ret = -EINVAL;
 490                 goto err_enable;
 491         }
 492 
 493         ret = regmap_read(wm8523->regmap, WM8523_REVISION, &val);
 494         if (ret < 0) {
 495                 dev_err(&i2c->dev, "Failed to read revision register\n");
 496                 goto err_enable;
 497         }
 498         dev_info(&i2c->dev, "revision %c\n",
 499                  (val & WM8523_CHIP_REV_MASK) + 'A');
 500 
 501         ret = regmap_write(wm8523->regmap, WM8523_DEVICE_ID, 0x8523);
 502         if (ret != 0) {
 503                 dev_err(&i2c->dev, "Failed to reset device: %d\n", ret);
 504                 goto err_enable;
 505         }
 506 
 507         regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
 508 
 509         i2c_set_clientdata(i2c, wm8523);
 510 
 511         ret = devm_snd_soc_register_component(&i2c->dev,
 512                         &soc_component_dev_wm8523, &wm8523_dai, 1);
 513 
 514         return ret;
 515 
 516 err_enable:
 517         regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
 518         return ret;
 519 }
 520 
 521 static const struct i2c_device_id wm8523_i2c_id[] = {
 522         { "wm8523", 0 },
 523         { }
 524 };
 525 MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);
 526 
 527 static struct i2c_driver wm8523_i2c_driver = {
 528         .driver = {
 529                 .name = "wm8523",
 530                 .of_match_table = wm8523_of_match,
 531         },
 532         .probe =    wm8523_i2c_probe,
 533         .id_table = wm8523_i2c_id,
 534 };
 535 
 536 module_i2c_driver(wm8523_i2c_driver);
 537 
 538 MODULE_DESCRIPTION("ASoC WM8523 driver");
 539 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 540 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */