linux/sound/soc/codecs/wm8804.c
<<
>>
Prefs
   1/*
   2 * wm8804.c  --  WM8804 S/PDIF transceiver driver
   3 *
   4 * Copyright 2010 Wolfson Microelectronics plc
   5 *
   6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/moduleparam.h>
  15#include <linux/init.h>
  16#include <linux/delay.h>
  17#include <linux/pm.h>
  18#include <linux/i2c.h>
  19#include <linux/spi/spi.h>
  20#include <linux/regulator/consumer.h>
  21#include <linux/slab.h>
  22#include <sound/core.h>
  23#include <sound/pcm.h>
  24#include <sound/pcm_params.h>
  25#include <sound/soc.h>
  26#include <sound/initval.h>
  27#include <sound/tlv.h>
  28
  29#include "wm8804.h"
  30
  31#define WM8804_NUM_SUPPLIES 2
  32static const char *wm8804_supply_names[WM8804_NUM_SUPPLIES] = {
  33        "PVDD",
  34        "DVDD"
  35};
  36
  37static const u8 wm8804_reg_defs[] = {
  38        0x05,     /* R0  - RST/DEVID1 */
  39        0x88,     /* R1  - DEVID2 */
  40        0x04,     /* R2  - DEVREV */
  41        0x21,     /* R3  - PLL1 */
  42        0xFD,     /* R4  - PLL2 */
  43        0x36,     /* R5  - PLL3 */
  44        0x07,     /* R6  - PLL4 */
  45        0x16,     /* R7  - PLL5 */
  46        0x18,     /* R8  - PLL6 */
  47        0xFF,     /* R9  - SPDMODE */
  48        0x00,     /* R10 - INTMASK */
  49        0x00,     /* R11 - INTSTAT */
  50        0x00,     /* R12 - SPDSTAT */
  51        0x00,     /* R13 - RXCHAN1 */
  52        0x00,     /* R14 - RXCHAN2 */
  53        0x00,     /* R15 - RXCHAN3 */
  54        0x00,     /* R16 - RXCHAN4 */
  55        0x00,     /* R17 - RXCHAN5 */
  56        0x00,     /* R18 - SPDTX1 */
  57        0x00,     /* R19 - SPDTX2 */
  58        0x00,     /* R20 - SPDTX3 */
  59        0x71,     /* R21 - SPDTX4 */
  60        0x0B,     /* R22 - SPDTX5 */
  61        0x70,     /* R23 - GPO0 */
  62        0x57,     /* R24 - GPO1 */
  63        0x00,     /* R25 */
  64        0x42,     /* R26 - GPO2 */
  65        0x06,     /* R27 - AIFTX */
  66        0x06,     /* R28 - AIFRX */
  67        0x80,     /* R29 - SPDRX1 */
  68        0x07,     /* R30 - PWRDN */
  69};
  70
  71struct wm8804_priv {
  72        enum snd_soc_control_type control_type;
  73        struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES];
  74        struct notifier_block disable_nb[WM8804_NUM_SUPPLIES];
  75        struct snd_soc_codec *codec;
  76};
  77
  78static int txsrc_get(struct snd_kcontrol *kcontrol,
  79                     struct snd_ctl_elem_value *ucontrol);
  80
  81static int txsrc_put(struct snd_kcontrol *kcontrol,
  82                     struct snd_ctl_elem_value *ucontrol);
  83
  84/*
  85 * We can't use the same notifier block for more than one supply and
  86 * there's no way I can see to get from a callback to the caller
  87 * except container_of().
  88 */
  89#define WM8804_REGULATOR_EVENT(n) \
  90static int wm8804_regulator_event_##n(struct notifier_block *nb, \
  91                                      unsigned long event, void *data)    \
  92{ \
  93        struct wm8804_priv *wm8804 = container_of(nb, struct wm8804_priv, \
  94                                                  disable_nb[n]); \
  95        if (event & REGULATOR_EVENT_DISABLE) { \
  96                wm8804->codec->cache_sync = 1; \
  97        } \
  98        return 0; \
  99}
 100
 101WM8804_REGULATOR_EVENT(0)
 102WM8804_REGULATOR_EVENT(1)
 103
 104static const char *txsrc_text[] = { "S/PDIF RX", "AIF" };
 105static const SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text);
 106
 107static const struct snd_kcontrol_new wm8804_snd_controls[] = {
 108        SOC_ENUM_EXT("Input Source", txsrc, txsrc_get, txsrc_put),
 109        SOC_SINGLE("TX Playback Switch", WM8804_PWRDN, 2, 1, 1),
 110        SOC_SINGLE("AIF Playback Switch", WM8804_PWRDN, 4, 1, 1)
 111};
 112
 113static int txsrc_get(struct snd_kcontrol *kcontrol,
 114                     struct snd_ctl_elem_value *ucontrol)
 115{
 116        struct snd_soc_codec *codec;
 117        unsigned int src;
 118
 119        codec = snd_kcontrol_chip(kcontrol);
 120        src = snd_soc_read(codec, WM8804_SPDTX4);
 121        if (src & 0x40)
 122                ucontrol->value.integer.value[0] = 1;
 123        else
 124                ucontrol->value.integer.value[0] = 0;
 125
 126        return 0;
 127}
 128
 129static int txsrc_put(struct snd_kcontrol *kcontrol,
 130                     struct snd_ctl_elem_value *ucontrol)
 131{
 132        struct snd_soc_codec *codec;
 133        unsigned int src, txpwr;
 134
 135        codec = snd_kcontrol_chip(kcontrol);
 136
 137        if (ucontrol->value.integer.value[0] != 0
 138                        && ucontrol->value.integer.value[0] != 1)
 139                return -EINVAL;
 140
 141        src = snd_soc_read(codec, WM8804_SPDTX4);
 142        switch ((src & 0x40) >> 6) {
 143        case 0:
 144                if (!ucontrol->value.integer.value[0])
 145                        return 0;
 146                break;
 147        case 1:
 148                if (ucontrol->value.integer.value[1])
 149                        return 0;
 150                break;
 151        }
 152
 153        /* save the current power state of the transmitter */
 154        txpwr = snd_soc_read(codec, WM8804_PWRDN) & 0x4;
 155        /* power down the transmitter */
 156        snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x4);
 157        /* set the tx source */
 158        snd_soc_update_bits(codec, WM8804_SPDTX4, 0x40,
 159                            ucontrol->value.integer.value[0] << 6);
 160
 161        if (ucontrol->value.integer.value[0]) {
 162                /* power down the receiver */
 163                snd_soc_update_bits(codec, WM8804_PWRDN, 0x2, 0x2);
 164                /* power up the AIF */
 165                snd_soc_update_bits(codec, WM8804_PWRDN, 0x10, 0);
 166        } else {
 167                /* don't power down the AIF -- may be used as an output */
 168                /* power up the receiver */
 169                snd_soc_update_bits(codec, WM8804_PWRDN, 0x2, 0);
 170        }
 171
 172        /* restore the transmitter's configuration */
 173        snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, txpwr);
 174
 175        return 0;
 176}
 177
 178static int wm8804_volatile(unsigned int reg)
 179{
 180        switch (reg) {
 181        case WM8804_RST_DEVID1:
 182        case WM8804_DEVID2:
 183        case WM8804_DEVREV:
 184        case WM8804_INTSTAT:
 185        case WM8804_SPDSTAT:
 186        case WM8804_RXCHAN1:
 187        case WM8804_RXCHAN2:
 188        case WM8804_RXCHAN3:
 189        case WM8804_RXCHAN4:
 190        case WM8804_RXCHAN5:
 191                return 1;
 192        default:
 193                break;
 194        }
 195
 196        return 0;
 197}
 198
 199static int wm8804_reset(struct snd_soc_codec *codec)
 200{
 201        return snd_soc_write(codec, WM8804_RST_DEVID1, 0x0);
 202}
 203
 204static int wm8804_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 205{
 206        struct snd_soc_codec *codec;
 207        u16 format, master, bcp, lrp;
 208
 209        codec = dai->codec;
 210
 211        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 212        case SND_SOC_DAIFMT_I2S:
 213                format = 0x2;
 214                break;
 215        case SND_SOC_DAIFMT_RIGHT_J:
 216                format = 0x0;
 217                break;
 218        case SND_SOC_DAIFMT_LEFT_J:
 219                format = 0x1;
 220                break;
 221        case SND_SOC_DAIFMT_DSP_A:
 222        case SND_SOC_DAIFMT_DSP_B:
 223                format = 0x3;
 224                break;
 225        default:
 226                dev_err(dai->dev, "Unknown dai format\n");
 227                return -EINVAL;
 228        }
 229
 230        /* set data format */
 231        snd_soc_update_bits(codec, WM8804_AIFTX, 0x3, format);
 232        snd_soc_update_bits(codec, WM8804_AIFRX, 0x3, format);
 233
 234        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 235        case SND_SOC_DAIFMT_CBM_CFM:
 236                master = 1;
 237                break;
 238        case SND_SOC_DAIFMT_CBS_CFS:
 239                master = 0;
 240                break;
 241        default:
 242                dev_err(dai->dev, "Unknown master/slave configuration\n");
 243                return -EINVAL;
 244        }
 245
 246        /* set master/slave mode */
 247        snd_soc_update_bits(codec, WM8804_AIFRX, 0x40, master << 6);
 248
 249        bcp = lrp = 0;
 250        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 251        case SND_SOC_DAIFMT_NB_NF:
 252                break;
 253        case SND_SOC_DAIFMT_IB_IF:
 254                bcp = lrp = 1;
 255                break;
 256        case SND_SOC_DAIFMT_IB_NF:
 257                bcp = 1;
 258                break;
 259        case SND_SOC_DAIFMT_NB_IF:
 260                lrp = 1;
 261                break;
 262        default:
 263                dev_err(dai->dev, "Unknown polarity configuration\n");
 264                return -EINVAL;
 265        }
 266
 267        /* set frame inversion */
 268        snd_soc_update_bits(codec, WM8804_AIFTX, 0x10 | 0x20,
 269                            (bcp << 4) | (lrp << 5));
 270        snd_soc_update_bits(codec, WM8804_AIFRX, 0x10 | 0x20,
 271                            (bcp << 4) | (lrp << 5));
 272        return 0;
 273}
 274
 275static int wm8804_hw_params(struct snd_pcm_substream *substream,
 276                            struct snd_pcm_hw_params *params,
 277                            struct snd_soc_dai *dai)
 278{
 279        struct snd_soc_codec *codec;
 280        u16 blen;
 281
 282        codec = dai->codec;
 283
 284        switch (params_format(params)) {
 285        case SNDRV_PCM_FORMAT_S16_LE:
 286                blen = 0x0;
 287                break;
 288        case SNDRV_PCM_FORMAT_S20_3LE:
 289                blen = 0x1;
 290                break;
 291        case SNDRV_PCM_FORMAT_S24_LE:
 292                blen = 0x2;
 293                break;
 294        default:
 295                dev_err(dai->dev, "Unsupported word length: %u\n",
 296                        params_format(params));
 297                return -EINVAL;
 298        }
 299
 300        /* set word length */
 301        snd_soc_update_bits(codec, WM8804_AIFTX, 0xc, blen << 2);
 302        snd_soc_update_bits(codec, WM8804_AIFRX, 0xc, blen << 2);
 303
 304        return 0;
 305}
 306
 307struct pll_div {
 308        u32 prescale:1;
 309        u32 mclkdiv:1;
 310        u32 freqmode:2;
 311        u32 n:4;
 312        u32 k:22;
 313};
 314
 315/* PLL rate to output rate divisions */
 316static struct {
 317        unsigned int div;
 318        unsigned int freqmode;
 319        unsigned int mclkdiv;
 320} post_table[] = {
 321        {  2,  0, 0 },
 322        {  4,  0, 1 },
 323        {  4,  1, 0 },
 324        {  8,  1, 1 },
 325        {  8,  2, 0 },
 326        { 16,  2, 1 },
 327        { 12,  3, 0 },
 328        { 24,  3, 1 }
 329};
 330
 331#define FIXED_PLL_SIZE ((1ULL << 22) * 10)
 332static int pll_factors(struct pll_div *pll_div, unsigned int target,
 333                       unsigned int source)
 334{
 335        u64 Kpart;
 336        unsigned long int K, Ndiv, Nmod, tmp;
 337        int i;
 338
 339        /*
 340         * Scale the output frequency up; the PLL should run in the
 341         * region of 90-100MHz.
 342         */
 343        for (i = 0; i < ARRAY_SIZE(post_table); i++) {
 344                tmp = target * post_table[i].div;
 345                if (tmp >= 90000000 && tmp <= 100000000) {
 346                        pll_div->freqmode = post_table[i].freqmode;
 347                        pll_div->mclkdiv = post_table[i].mclkdiv;
 348                        target *= post_table[i].div;
 349                        break;
 350                }
 351        }
 352
 353        if (i == ARRAY_SIZE(post_table)) {
 354                pr_err("%s: Unable to scale output frequency: %uHz\n",
 355                       __func__, target);
 356                return -EINVAL;
 357        }
 358
 359        pll_div->prescale = 0;
 360        Ndiv = target / source;
 361        if (Ndiv < 5) {
 362                source >>= 1;
 363                pll_div->prescale = 1;
 364                Ndiv = target / source;
 365        }
 366
 367        if (Ndiv < 5 || Ndiv > 13) {
 368                pr_err("%s: WM8804 N value is not within the recommended range: %lu\n",
 369                       __func__, Ndiv);
 370                return -EINVAL;
 371        }
 372        pll_div->n = Ndiv;
 373
 374        Nmod = target % source;
 375        Kpart = FIXED_PLL_SIZE * (u64)Nmod;
 376
 377        do_div(Kpart, source);
 378
 379        K = Kpart & 0xffffffff;
 380        if ((K % 10) >= 5)
 381                K += 5;
 382        K /= 10;
 383        pll_div->k = K;
 384
 385        return 0;
 386}
 387
 388static int wm8804_set_pll(struct snd_soc_dai *dai, int pll_id,
 389                          int source, unsigned int freq_in,
 390                          unsigned int freq_out)
 391{
 392        struct snd_soc_codec *codec;
 393
 394        codec = dai->codec;
 395        if (!freq_in || !freq_out) {
 396                /* disable the PLL */
 397                snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0x1);
 398                return 0;
 399        } else {
 400                int ret;
 401                struct pll_div pll_div;
 402
 403                ret = pll_factors(&pll_div, freq_out, freq_in);
 404                if (ret)
 405                        return ret;
 406
 407                /* power down the PLL before reprogramming it */
 408                snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0x1);
 409
 410                if (!freq_in || !freq_out)
 411                        return 0;
 412
 413                /* set PLLN and PRESCALE */
 414                snd_soc_update_bits(codec, WM8804_PLL4, 0xf | 0x10,
 415                                    pll_div.n | (pll_div.prescale << 4));
 416                /* set mclkdiv and freqmode */
 417                snd_soc_update_bits(codec, WM8804_PLL5, 0x3 | 0x8,
 418                                    pll_div.freqmode | (pll_div.mclkdiv << 3));
 419                /* set PLLK */
 420                snd_soc_write(codec, WM8804_PLL1, pll_div.k & 0xff);
 421                snd_soc_write(codec, WM8804_PLL2, (pll_div.k >> 8) & 0xff);
 422                snd_soc_write(codec, WM8804_PLL3, pll_div.k >> 16);
 423
 424                /* power up the PLL */
 425                snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0);
 426        }
 427
 428        return 0;
 429}
 430
 431static int wm8804_set_sysclk(struct snd_soc_dai *dai,
 432                             int clk_id, unsigned int freq, int dir)
 433{
 434        struct snd_soc_codec *codec;
 435
 436        codec = dai->codec;
 437
 438        switch (clk_id) {
 439        case WM8804_TX_CLKSRC_MCLK:
 440                if ((freq >= 10000000 && freq <= 14400000)
 441                                || (freq >= 16280000 && freq <= 27000000))
 442                        snd_soc_update_bits(codec, WM8804_PLL6, 0x80, 0x80);
 443                else {
 444                        dev_err(dai->dev, "OSCCLOCK is not within the "
 445                                "recommended range: %uHz\n", freq);
 446                        return -EINVAL;
 447                }
 448                break;
 449        case WM8804_TX_CLKSRC_PLL:
 450                snd_soc_update_bits(codec, WM8804_PLL6, 0x80, 0);
 451                break;
 452        case WM8804_CLKOUT_SRC_CLK1:
 453                snd_soc_update_bits(codec, WM8804_PLL6, 0x8, 0);
 454                break;
 455        case WM8804_CLKOUT_SRC_OSCCLK:
 456                snd_soc_update_bits(codec, WM8804_PLL6, 0x8, 0x8);
 457                break;
 458        default:
 459                dev_err(dai->dev, "Unknown clock source: %d\n", clk_id);
 460                return -EINVAL;
 461        }
 462
 463        return 0;
 464}
 465
 466static int wm8804_set_clkdiv(struct snd_soc_dai *dai,
 467                             int div_id, int div)
 468{
 469        struct snd_soc_codec *codec;
 470
 471        codec = dai->codec;
 472        switch (div_id) {
 473        case WM8804_CLKOUT_DIV:
 474                snd_soc_update_bits(codec, WM8804_PLL5, 0x30,
 475                                    (div & 0x3) << 4);
 476                break;
 477        default:
 478                dev_err(dai->dev, "Unknown clock divider: %d\n", div_id);
 479                return -EINVAL;
 480        }
 481        return 0;
 482}
 483
 484static void wm8804_sync_cache(struct snd_soc_codec *codec)
 485{
 486        short i;
 487        u8 *cache;
 488
 489        if (!codec->cache_sync)
 490                return;
 491
 492        codec->cache_only = 0;
 493        cache = codec->reg_cache;
 494        for (i = 0; i < codec->driver->reg_cache_size; i++) {
 495                if (i == WM8804_RST_DEVID1 || cache[i] == wm8804_reg_defs[i])
 496                        continue;
 497                snd_soc_write(codec, i, cache[i]);
 498        }
 499        codec->cache_sync = 0;
 500}
 501
 502static int wm8804_set_bias_level(struct snd_soc_codec *codec,
 503                                 enum snd_soc_bias_level level)
 504{
 505        int ret;
 506        struct wm8804_priv *wm8804;
 507
 508        wm8804 = snd_soc_codec_get_drvdata(codec);
 509        switch (level) {
 510        case SND_SOC_BIAS_ON:
 511                break;
 512        case SND_SOC_BIAS_PREPARE:
 513                /* power up the OSC and the PLL */
 514                snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0);
 515                break;
 516        case SND_SOC_BIAS_STANDBY:
 517                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
 518                        ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
 519                                                    wm8804->supplies);
 520                        if (ret) {
 521                                dev_err(codec->dev,
 522                                        "Failed to enable supplies: %d\n",
 523                                        ret);
 524                                return ret;
 525                        }
 526                        wm8804_sync_cache(codec);
 527                }
 528                /* power down the OSC and the PLL */
 529                snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0x9);
 530                break;
 531        case SND_SOC_BIAS_OFF:
 532                /* power down the OSC and the PLL */
 533                snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0x9);
 534                regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies),
 535                                       wm8804->supplies);
 536                break;
 537        }
 538
 539        codec->dapm.bias_level = level;
 540        return 0;
 541}
 542
 543#ifdef CONFIG_PM
 544static int wm8804_suspend(struct snd_soc_codec *codec, pm_message_t state)
 545{
 546        wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF);
 547        return 0;
 548}
 549
 550static int wm8804_resume(struct snd_soc_codec *codec)
 551{
 552        wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 553        return 0;
 554}
 555#else
 556#define wm8804_suspend NULL
 557#define wm8804_resume NULL
 558#endif
 559
 560static int wm8804_remove(struct snd_soc_codec *codec)
 561{
 562        struct wm8804_priv *wm8804;
 563        int i;
 564
 565        wm8804 = snd_soc_codec_get_drvdata(codec);
 566        wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF);
 567
 568        for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i)
 569                regulator_unregister_notifier(wm8804->supplies[i].consumer,
 570                                              &wm8804->disable_nb[i]);
 571        regulator_bulk_free(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
 572        return 0;
 573}
 574
 575static int wm8804_probe(struct snd_soc_codec *codec)
 576{
 577        struct wm8804_priv *wm8804;
 578        int i, id1, id2, ret;
 579
 580        wm8804 = snd_soc_codec_get_drvdata(codec);
 581        wm8804->codec = codec;
 582
 583        codec->dapm.idle_bias_off = 1;
 584
 585        ret = snd_soc_codec_set_cache_io(codec, 8, 8, wm8804->control_type);
 586        if (ret < 0) {
 587                dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
 588                return ret;
 589        }
 590
 591        for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++)
 592                wm8804->supplies[i].supply = wm8804_supply_names[i];
 593
 594        ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8804->supplies),
 595                                 wm8804->supplies);
 596        if (ret) {
 597                dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
 598                return ret;
 599        }
 600
 601        wm8804->disable_nb[0].notifier_call = wm8804_regulator_event_0;
 602        wm8804->disable_nb[1].notifier_call = wm8804_regulator_event_1;
 603
 604        /* This should really be moved into the regulator core */
 605        for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) {
 606                ret = regulator_register_notifier(wm8804->supplies[i].consumer,
 607                                                  &wm8804->disable_nb[i]);
 608                if (ret != 0) {
 609                        dev_err(codec->dev,
 610                                "Failed to register regulator notifier: %d\n",
 611                                ret);
 612                }
 613        }
 614
 615        ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
 616                                    wm8804->supplies);
 617        if (ret) {
 618                dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
 619                goto err_reg_get;
 620        }
 621
 622        id1 = snd_soc_read(codec, WM8804_RST_DEVID1);
 623        if (id1 < 0) {
 624                dev_err(codec->dev, "Failed to read device ID: %d\n", id1);
 625                ret = id1;
 626                goto err_reg_enable;
 627        }
 628
 629        id2 = snd_soc_read(codec, WM8804_DEVID2);
 630        if (id2 < 0) {
 631                dev_err(codec->dev, "Failed to read device ID: %d\n", id2);
 632                ret = id2;
 633                goto err_reg_enable;
 634        }
 635
 636        id2 = (id2 << 8) | id1;
 637
 638        if (id2 != ((wm8804_reg_defs[WM8804_DEVID2] << 8)
 639                        | wm8804_reg_defs[WM8804_RST_DEVID1])) {
 640                dev_err(codec->dev, "Invalid device ID: %#x\n", id2);
 641                ret = -EINVAL;
 642                goto err_reg_enable;
 643        }
 644
 645        ret = snd_soc_read(codec, WM8804_DEVREV);
 646        if (ret < 0) {
 647                dev_err(codec->dev, "Failed to read device revision: %d\n",
 648                        ret);
 649                goto err_reg_enable;
 650        }
 651        dev_info(codec->dev, "revision %c\n", ret + 'A');
 652
 653        ret = wm8804_reset(codec);
 654        if (ret < 0) {
 655                dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
 656                goto err_reg_enable;
 657        }
 658
 659        wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 660
 661        snd_soc_add_controls(codec, wm8804_snd_controls,
 662                             ARRAY_SIZE(wm8804_snd_controls));
 663        return 0;
 664
 665err_reg_enable:
 666        regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
 667err_reg_get:
 668        regulator_bulk_free(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
 669        return ret;
 670}
 671
 672static struct snd_soc_dai_ops wm8804_dai_ops = {
 673        .hw_params = wm8804_hw_params,
 674        .set_fmt = wm8804_set_fmt,
 675        .set_sysclk = wm8804_set_sysclk,
 676        .set_clkdiv = wm8804_set_clkdiv,
 677        .set_pll = wm8804_set_pll
 678};
 679
 680#define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
 681                        SNDRV_PCM_FMTBIT_S24_LE)
 682
 683static struct snd_soc_dai_driver wm8804_dai = {
 684        .name = "wm8804-spdif",
 685        .playback = {
 686                .stream_name = "Playback",
 687                .channels_min = 2,
 688                .channels_max = 2,
 689                .rates = SNDRV_PCM_RATE_8000_192000,
 690                .formats = WM8804_FORMATS,
 691        },
 692        .capture = {
 693                .stream_name = "Capture",
 694                .channels_min = 2,
 695                .channels_max = 2,
 696                .rates = SNDRV_PCM_RATE_8000_192000,
 697                .formats = WM8804_FORMATS,
 698        },
 699        .ops = &wm8804_dai_ops,
 700        .symmetric_rates = 1
 701};
 702
 703static struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
 704        .probe = wm8804_probe,
 705        .remove = wm8804_remove,
 706        .suspend = wm8804_suspend,
 707        .resume = wm8804_resume,
 708        .set_bias_level = wm8804_set_bias_level,
 709        .reg_cache_size = ARRAY_SIZE(wm8804_reg_defs),
 710        .reg_word_size = sizeof(u8),
 711        .reg_cache_default = wm8804_reg_defs,
 712        .volatile_register = wm8804_volatile
 713};
 714
 715#if defined(CONFIG_SPI_MASTER)
 716static int __devinit wm8804_spi_probe(struct spi_device *spi)
 717{
 718        struct wm8804_priv *wm8804;
 719        int ret;
 720
 721        wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
 722        if (!wm8804)
 723                return -ENOMEM;
 724
 725        wm8804->control_type = SND_SOC_SPI;
 726        spi_set_drvdata(spi, wm8804);
 727
 728        ret = snd_soc_register_codec(&spi->dev,
 729                                     &soc_codec_dev_wm8804, &wm8804_dai, 1);
 730        if (ret < 0)
 731                kfree(wm8804);
 732        return ret;
 733}
 734
 735static int __devexit wm8804_spi_remove(struct spi_device *spi)
 736{
 737        snd_soc_unregister_codec(&spi->dev);
 738        kfree(spi_get_drvdata(spi));
 739        return 0;
 740}
 741
 742static struct spi_driver wm8804_spi_driver = {
 743        .driver = {
 744                .name = "wm8804",
 745                .owner = THIS_MODULE,
 746        },
 747        .probe = wm8804_spi_probe,
 748        .remove = __devexit_p(wm8804_spi_remove)
 749};
 750#endif
 751
 752#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 753static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
 754                                      const struct i2c_device_id *id)
 755{
 756        struct wm8804_priv *wm8804;
 757        int ret;
 758
 759        wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
 760        if (!wm8804)
 761                return -ENOMEM;
 762
 763        wm8804->control_type = SND_SOC_I2C;
 764        i2c_set_clientdata(i2c, wm8804);
 765
 766        ret = snd_soc_register_codec(&i2c->dev,
 767                                     &soc_codec_dev_wm8804, &wm8804_dai, 1);
 768        if (ret < 0)
 769                kfree(wm8804);
 770        return ret;
 771}
 772
 773static __devexit int wm8804_i2c_remove(struct i2c_client *client)
 774{
 775        snd_soc_unregister_codec(&client->dev);
 776        kfree(i2c_get_clientdata(client));
 777        return 0;
 778}
 779
 780static const struct i2c_device_id wm8804_i2c_id[] = {
 781        { "wm8804", 0 },
 782        { }
 783};
 784MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id);
 785
 786static struct i2c_driver wm8804_i2c_driver = {
 787        .driver = {
 788                .name = "wm8804",
 789                .owner = THIS_MODULE,
 790        },
 791        .probe = wm8804_i2c_probe,
 792        .remove = __devexit_p(wm8804_i2c_remove),
 793        .id_table = wm8804_i2c_id
 794};
 795#endif
 796
 797static int __init wm8804_modinit(void)
 798{
 799        int ret = 0;
 800
 801#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 802        ret = i2c_add_driver(&wm8804_i2c_driver);
 803        if (ret) {
 804                printk(KERN_ERR "Failed to register wm8804 I2C driver: %d\n",
 805                       ret);
 806        }
 807#endif
 808#if defined(CONFIG_SPI_MASTER)
 809        ret = spi_register_driver(&wm8804_spi_driver);
 810        if (ret != 0) {
 811                printk(KERN_ERR "Failed to register wm8804 SPI driver: %d\n",
 812                       ret);
 813        }
 814#endif
 815        return ret;
 816}
 817module_init(wm8804_modinit);
 818
 819static void __exit wm8804_exit(void)
 820{
 821#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 822        i2c_del_driver(&wm8804_i2c_driver);
 823#endif
 824#if defined(CONFIG_SPI_MASTER)
 825        spi_unregister_driver(&wm8804_spi_driver);
 826#endif
 827}
 828module_exit(wm8804_exit);
 829
 830MODULE_DESCRIPTION("ASoC WM8804 driver");
 831MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");
 832MODULE_LICENSE("GPL");
 833