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