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