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