linux/sound/soc/codecs/wm8741.c
<<
>>
Prefs
   1/*
   2 * wm8741.c  --  WM8741 ALSA SoC Audio driver
   3 *
   4 * Copyright 2010-1 Wolfson Microelectronics plc
   5 *
   6 * Author: Ian Lartey <ian@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/spi/spi.h>
  21#include <linux/regmap.h>
  22#include <linux/regulator/consumer.h>
  23#include <linux/slab.h>
  24#include <linux/of_device.h>
  25#include <sound/core.h>
  26#include <sound/pcm.h>
  27#include <sound/pcm_params.h>
  28#include <sound/soc.h>
  29#include <sound/initval.h>
  30#include <sound/tlv.h>
  31
  32#include "wm8741.h"
  33
  34#define WM8741_NUM_SUPPLIES 2
  35static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = {
  36        "AVDD",
  37        "DVDD",
  38};
  39
  40#define WM8741_NUM_RATES 6
  41
  42/* codec private data */
  43struct wm8741_priv {
  44        struct wm8741_platform_data pdata;
  45        struct regmap *regmap;
  46        struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];
  47        unsigned int sysclk;
  48        const struct snd_pcm_hw_constraint_list *sysclk_constraints;
  49};
  50
  51static const struct reg_default wm8741_reg_defaults[] = {
  52        {  0, 0x0000 },     /* R0  - DACLLSB Attenuation */
  53        {  1, 0x0000 },     /* R1  - DACLMSB Attenuation */
  54        {  2, 0x0000 },     /* R2  - DACRLSB Attenuation */
  55        {  3, 0x0000 },     /* R3  - DACRMSB Attenuation */
  56        {  4, 0x0000 },     /* R4  - Volume Control */
  57        {  5, 0x000A },     /* R5  - Format Control */
  58        {  6, 0x0000 },     /* R6  - Filter Control */
  59        {  7, 0x0000 },     /* R7  - Mode Control 1 */
  60        {  8, 0x0002 },     /* R8  - Mode Control 2 */
  61        { 32, 0x0002 },     /* R32 - ADDITONAL_CONTROL_1 */
  62};
  63
  64static int wm8741_reset(struct snd_soc_codec *codec)
  65{
  66        return snd_soc_write(codec, WM8741_RESET, 0);
  67}
  68
  69static const DECLARE_TLV_DB_SCALE(dac_tlv_fine, -12700, 13, 0);
  70static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 400, 0);
  71
  72static const struct snd_kcontrol_new wm8741_snd_controls_stereo[] = {
  73SOC_DOUBLE_R_TLV("Fine Playback Volume", WM8741_DACLLSB_ATTENUATION,
  74                 WM8741_DACRLSB_ATTENUATION, 1, 255, 1, dac_tlv_fine),
  75SOC_DOUBLE_R_TLV("Playback Volume", WM8741_DACLMSB_ATTENUATION,
  76                 WM8741_DACRMSB_ATTENUATION, 0, 511, 1, dac_tlv),
  77};
  78
  79static const struct snd_kcontrol_new wm8741_snd_controls_mono_left[] = {
  80SOC_SINGLE_TLV("Fine Playback Volume", WM8741_DACLLSB_ATTENUATION,
  81                 1, 255, 1, dac_tlv_fine),
  82SOC_SINGLE_TLV("Playback Volume", WM8741_DACLMSB_ATTENUATION,
  83                 0, 511, 1, dac_tlv),
  84};
  85
  86static const struct snd_kcontrol_new wm8741_snd_controls_mono_right[] = {
  87SOC_SINGLE_TLV("Fine Playback Volume", WM8741_DACRLSB_ATTENUATION,
  88                1, 255, 1, dac_tlv_fine),
  89SOC_SINGLE_TLV("Playback Volume", WM8741_DACRMSB_ATTENUATION,
  90                0, 511, 1, dac_tlv),
  91};
  92
  93static const struct snd_soc_dapm_widget wm8741_dapm_widgets[] = {
  94SND_SOC_DAPM_DAC("DACL", "Playback", SND_SOC_NOPM, 0, 0),
  95SND_SOC_DAPM_DAC("DACR", "Playback", SND_SOC_NOPM, 0, 0),
  96SND_SOC_DAPM_OUTPUT("VOUTLP"),
  97SND_SOC_DAPM_OUTPUT("VOUTLN"),
  98SND_SOC_DAPM_OUTPUT("VOUTRP"),
  99SND_SOC_DAPM_OUTPUT("VOUTRN"),
 100};
 101
 102static const struct snd_soc_dapm_route wm8741_dapm_routes[] = {
 103        { "VOUTLP", NULL, "DACL" },
 104        { "VOUTLN", NULL, "DACL" },
 105        { "VOUTRP", NULL, "DACR" },
 106        { "VOUTRN", NULL, "DACR" },
 107};
 108
 109static const unsigned int rates_11289[] = {
 110        44100, 88200,
 111};
 112
 113static const struct snd_pcm_hw_constraint_list constraints_11289 = {
 114        .count  = ARRAY_SIZE(rates_11289),
 115        .list   = rates_11289,
 116};
 117
 118static const unsigned int rates_12288[] = {
 119        32000, 48000, 96000,
 120};
 121
 122static const struct snd_pcm_hw_constraint_list constraints_12288 = {
 123        .count  = ARRAY_SIZE(rates_12288),
 124        .list   = rates_12288,
 125};
 126
 127static const unsigned int rates_16384[] = {
 128        32000,
 129};
 130
 131static const struct snd_pcm_hw_constraint_list constraints_16384 = {
 132        .count  = ARRAY_SIZE(rates_16384),
 133        .list   = rates_16384,
 134};
 135
 136static const unsigned int rates_16934[] = {
 137        44100, 88200,
 138};
 139
 140static const struct snd_pcm_hw_constraint_list constraints_16934 = {
 141        .count  = ARRAY_SIZE(rates_16934),
 142        .list   = rates_16934,
 143};
 144
 145static const unsigned int rates_18432[] = {
 146        48000, 96000,
 147};
 148
 149static const struct snd_pcm_hw_constraint_list constraints_18432 = {
 150        .count  = ARRAY_SIZE(rates_18432),
 151        .list   = rates_18432,
 152};
 153
 154static const unsigned int rates_22579[] = {
 155        44100, 88200, 176400
 156};
 157
 158static const struct snd_pcm_hw_constraint_list constraints_22579 = {
 159        .count  = ARRAY_SIZE(rates_22579),
 160        .list   = rates_22579,
 161};
 162
 163static const unsigned int rates_24576[] = {
 164        32000, 48000, 96000, 192000
 165};
 166
 167static const struct snd_pcm_hw_constraint_list constraints_24576 = {
 168        .count  = ARRAY_SIZE(rates_24576),
 169        .list   = rates_24576,
 170};
 171
 172static const unsigned int rates_36864[] = {
 173        48000, 96000, 192000
 174};
 175
 176static const struct snd_pcm_hw_constraint_list constraints_36864 = {
 177        .count  = ARRAY_SIZE(rates_36864),
 178        .list   = rates_36864,
 179};
 180
 181static int wm8741_startup(struct snd_pcm_substream *substream,
 182                          struct snd_soc_dai *dai)
 183{
 184        struct snd_soc_codec *codec = dai->codec;
 185        struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
 186
 187        if (wm8741->sysclk)
 188                snd_pcm_hw_constraint_list(substream->runtime, 0,
 189                                SNDRV_PCM_HW_PARAM_RATE,
 190                                wm8741->sysclk_constraints);
 191
 192        return 0;
 193}
 194
 195static int wm8741_hw_params(struct snd_pcm_substream *substream,
 196                            struct snd_pcm_hw_params *params,
 197                            struct snd_soc_dai *dai)
 198{
 199        struct snd_soc_codec *codec = dai->codec;
 200        struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
 201        u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC;
 202        int i;
 203
 204        /* The set of sample rates that can be supported depends on the
 205         * MCLK supplied to the CODEC - enforce this.
 206         */
 207        if (!wm8741->sysclk) {
 208                dev_err(codec->dev,
 209                        "No MCLK configured, call set_sysclk() on init or in hw_params\n");
 210                return -EINVAL;
 211        }
 212
 213        /* Find a supported LRCLK rate */
 214        for (i = 0; i < wm8741->sysclk_constraints->count; i++) {
 215                if (wm8741->sysclk_constraints->list[i] == params_rate(params))
 216                        break;
 217        }
 218
 219        if (i == wm8741->sysclk_constraints->count) {
 220                dev_err(codec->dev, "LRCLK %d unsupported with MCLK %d\n",
 221                        params_rate(params), wm8741->sysclk);
 222                return -EINVAL;
 223        }
 224
 225        /* bit size */
 226        switch (params_width(params)) {
 227        case 16:
 228                break;
 229        case 20:
 230                iface |= 0x0001;
 231                break;
 232        case 24:
 233                iface |= 0x0002;
 234                break;
 235        case 32:
 236                iface |= 0x0003;
 237                break;
 238        default:
 239                dev_dbg(codec->dev, "wm8741_hw_params:    Unsupported bit size param = %d",
 240                        params_width(params));
 241                return -EINVAL;
 242        }
 243
 244        dev_dbg(codec->dev, "wm8741_hw_params:    bit size param = %d, rate param = %d",
 245                params_width(params), params_rate(params));
 246
 247        snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface);
 248        return 0;
 249}
 250
 251static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 252                int clk_id, unsigned int freq, int dir)
 253{
 254        struct snd_soc_codec *codec = codec_dai->codec;
 255        struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
 256
 257        dev_dbg(codec->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq);
 258
 259        switch (freq) {
 260        case 0:
 261                wm8741->sysclk_constraints = NULL;
 262                break;
 263        case 11289600:
 264                wm8741->sysclk_constraints = &constraints_11289;
 265                break;
 266        case 12288000:
 267                wm8741->sysclk_constraints = &constraints_12288;
 268                break;
 269        case 16384000:
 270                wm8741->sysclk_constraints = &constraints_16384;
 271                break;
 272        case 16934400:
 273                wm8741->sysclk_constraints = &constraints_16934;
 274                break;
 275        case 18432000:
 276                wm8741->sysclk_constraints = &constraints_18432;
 277                break;
 278        case 22579200:
 279        case 33868800:
 280                wm8741->sysclk_constraints = &constraints_22579;
 281                break;
 282        case 24576000:
 283                wm8741->sysclk_constraints = &constraints_24576;
 284                break;
 285        case 36864000:
 286                wm8741->sysclk_constraints = &constraints_36864;
 287                break;
 288        default:
 289                return -EINVAL;
 290        }
 291
 292        wm8741->sysclk = freq;
 293        return 0;
 294}
 295
 296static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
 297                unsigned int fmt)
 298{
 299        struct snd_soc_codec *codec = codec_dai->codec;
 300        u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1C3;
 301
 302        /* check master/slave audio interface */
 303        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 304        case SND_SOC_DAIFMT_CBS_CFS:
 305                break;
 306        default:
 307                return -EINVAL;
 308        }
 309
 310        /* interface format */
 311        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 312        case SND_SOC_DAIFMT_I2S:
 313                iface |= 0x0008;
 314                break;
 315        case SND_SOC_DAIFMT_RIGHT_J:
 316                break;
 317        case SND_SOC_DAIFMT_LEFT_J:
 318                iface |= 0x0004;
 319                break;
 320        case SND_SOC_DAIFMT_DSP_A:
 321                iface |= 0x000C;
 322                break;
 323        case SND_SOC_DAIFMT_DSP_B:
 324                iface |= 0x001C;
 325                break;
 326        default:
 327                return -EINVAL;
 328        }
 329
 330        /* clock inversion */
 331        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 332        case SND_SOC_DAIFMT_NB_NF:
 333                break;
 334        case SND_SOC_DAIFMT_IB_IF:
 335                iface |= 0x0010;
 336                break;
 337        case SND_SOC_DAIFMT_IB_NF:
 338                iface |= 0x0020;
 339                break;
 340        case SND_SOC_DAIFMT_NB_IF:
 341                iface |= 0x0030;
 342                break;
 343        default:
 344                return -EINVAL;
 345        }
 346
 347
 348        dev_dbg(codec->dev, "wm8741_set_dai_fmt:    Format=%x, Clock Inv=%x\n",
 349                                fmt & SND_SOC_DAIFMT_FORMAT_MASK,
 350                                ((fmt & SND_SOC_DAIFMT_INV_MASK)));
 351
 352        snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface);
 353        return 0;
 354}
 355
 356#define WM8741_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
 357                        SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \
 358                        SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | \
 359                        SNDRV_PCM_RATE_192000)
 360
 361#define WM8741_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 362                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 363
 364static const struct snd_soc_dai_ops wm8741_dai_ops = {
 365        .startup        = wm8741_startup,
 366        .hw_params      = wm8741_hw_params,
 367        .set_sysclk     = wm8741_set_dai_sysclk,
 368        .set_fmt        = wm8741_set_dai_fmt,
 369};
 370
 371static struct snd_soc_dai_driver wm8741_dai = {
 372        .name = "wm8741",
 373        .playback = {
 374                .stream_name = "Playback",
 375                .channels_min = 2,
 376                .channels_max = 2,
 377                .rates = WM8741_RATES,
 378                .formats = WM8741_FORMATS,
 379        },
 380        .ops = &wm8741_dai_ops,
 381};
 382
 383#ifdef CONFIG_PM
 384static int wm8741_resume(struct snd_soc_codec *codec)
 385{
 386        snd_soc_cache_sync(codec);
 387        return 0;
 388}
 389#else
 390#define wm8741_resume NULL
 391#endif
 392
 393static int wm8741_configure(struct snd_soc_codec *codec)
 394{
 395        struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
 396
 397        /* Configure differential mode */
 398        switch (wm8741->pdata.diff_mode) {
 399        case WM8741_DIFF_MODE_STEREO:
 400        case WM8741_DIFF_MODE_STEREO_REVERSED:
 401        case WM8741_DIFF_MODE_MONO_LEFT:
 402        case WM8741_DIFF_MODE_MONO_RIGHT:
 403                snd_soc_update_bits(codec, WM8741_MODE_CONTROL_2,
 404                                WM8741_DIFF_MASK,
 405                                wm8741->pdata.diff_mode << WM8741_DIFF_SHIFT);
 406                break;
 407        default:
 408                return -EINVAL;
 409        }
 410
 411        /* Change some default settings - latch VU */
 412        snd_soc_update_bits(codec, WM8741_DACLLSB_ATTENUATION,
 413                        WM8741_UPDATELL, WM8741_UPDATELL);
 414        snd_soc_update_bits(codec, WM8741_DACLMSB_ATTENUATION,
 415                        WM8741_UPDATELM, WM8741_UPDATELM);
 416        snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
 417                        WM8741_UPDATERL, WM8741_UPDATERL);
 418        snd_soc_update_bits(codec, WM8741_DACRMSB_ATTENUATION,
 419                        WM8741_UPDATERM, WM8741_UPDATERM);
 420
 421        return 0;
 422}
 423
 424static int wm8741_add_controls(struct snd_soc_codec *codec)
 425{
 426        struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
 427
 428        switch (wm8741->pdata.diff_mode) {
 429        case WM8741_DIFF_MODE_STEREO:
 430        case WM8741_DIFF_MODE_STEREO_REVERSED:
 431                snd_soc_add_codec_controls(codec,
 432                                wm8741_snd_controls_stereo,
 433                                ARRAY_SIZE(wm8741_snd_controls_stereo));
 434                break;
 435        case WM8741_DIFF_MODE_MONO_LEFT:
 436                snd_soc_add_codec_controls(codec,
 437                                wm8741_snd_controls_mono_left,
 438                                ARRAY_SIZE(wm8741_snd_controls_mono_left));
 439                break;
 440        case WM8741_DIFF_MODE_MONO_RIGHT:
 441                snd_soc_add_codec_controls(codec,
 442                                wm8741_snd_controls_mono_right,
 443                                ARRAY_SIZE(wm8741_snd_controls_mono_right));
 444                break;
 445        default:
 446                return -EINVAL;
 447        }
 448
 449        return 0;
 450}
 451
 452static int wm8741_probe(struct snd_soc_codec *codec)
 453{
 454        struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
 455        int ret = 0;
 456
 457        ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies),
 458                                    wm8741->supplies);
 459        if (ret != 0) {
 460                dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
 461                goto err_get;
 462        }
 463
 464        ret = wm8741_reset(codec);
 465        if (ret < 0) {
 466                dev_err(codec->dev, "Failed to issue reset\n");
 467                goto err_enable;
 468        }
 469
 470        ret = wm8741_configure(codec);
 471        if (ret < 0) {
 472                dev_err(codec->dev, "Failed to change default settings\n");
 473                goto err_enable;
 474        }
 475
 476        ret = wm8741_add_controls(codec);
 477        if (ret < 0) {
 478                dev_err(codec->dev, "Failed to add controls\n");
 479                goto err_enable;
 480        }
 481
 482        dev_dbg(codec->dev, "Successful registration\n");
 483        return ret;
 484
 485err_enable:
 486        regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
 487err_get:
 488        return ret;
 489}
 490
 491static int wm8741_remove(struct snd_soc_codec *codec)
 492{
 493        struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
 494
 495        regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
 496
 497        return 0;
 498}
 499
 500static struct snd_soc_codec_driver soc_codec_dev_wm8741 = {
 501        .probe =        wm8741_probe,
 502        .remove =       wm8741_remove,
 503        .resume =       wm8741_resume,
 504
 505        .dapm_widgets = wm8741_dapm_widgets,
 506        .num_dapm_widgets = ARRAY_SIZE(wm8741_dapm_widgets),
 507        .dapm_routes = wm8741_dapm_routes,
 508        .num_dapm_routes = ARRAY_SIZE(wm8741_dapm_routes),
 509};
 510
 511static const struct of_device_id wm8741_of_match[] = {
 512        { .compatible = "wlf,wm8741", },
 513        { }
 514};
 515MODULE_DEVICE_TABLE(of, wm8741_of_match);
 516
 517static const struct regmap_config wm8741_regmap = {
 518        .reg_bits = 7,
 519        .val_bits = 9,
 520        .max_register = WM8741_MAX_REGISTER,
 521
 522        .reg_defaults = wm8741_reg_defaults,
 523        .num_reg_defaults = ARRAY_SIZE(wm8741_reg_defaults),
 524        .cache_type = REGCACHE_RBTREE,
 525};
 526
 527static int wm8741_set_pdata(struct device *dev, struct wm8741_priv *wm8741)
 528{
 529        const struct wm8741_platform_data *pdata = dev_get_platdata(dev);
 530        u32 diff_mode;
 531
 532        if (dev->of_node) {
 533                if (of_property_read_u32(dev->of_node, "diff-mode", &diff_mode)
 534                                >= 0)
 535                        wm8741->pdata.diff_mode = diff_mode;
 536        } else {
 537                if (pdata != NULL)
 538                        memcpy(&wm8741->pdata, pdata, sizeof(wm8741->pdata));
 539        }
 540
 541        return 0;
 542}
 543
 544#if IS_ENABLED(CONFIG_I2C)
 545static int wm8741_i2c_probe(struct i2c_client *i2c,
 546                            const struct i2c_device_id *id)
 547{
 548        struct wm8741_priv *wm8741;
 549        int ret, i;
 550
 551        wm8741 = devm_kzalloc(&i2c->dev, sizeof(struct wm8741_priv),
 552                              GFP_KERNEL);
 553        if (wm8741 == NULL)
 554                return -ENOMEM;
 555
 556        for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++)
 557                wm8741->supplies[i].supply = wm8741_supply_names[i];
 558
 559        ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies),
 560                                      wm8741->supplies);
 561        if (ret != 0) {
 562                dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
 563                return ret;
 564        }
 565
 566        wm8741->regmap = devm_regmap_init_i2c(i2c, &wm8741_regmap);
 567        if (IS_ERR(wm8741->regmap)) {
 568                ret = PTR_ERR(wm8741->regmap);
 569                dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
 570                return ret;
 571        }
 572
 573        ret = wm8741_set_pdata(&i2c->dev, wm8741);
 574        if (ret != 0) {
 575                dev_err(&i2c->dev, "Failed to set pdata: %d\n", ret);
 576                return ret;
 577        }
 578
 579        i2c_set_clientdata(i2c, wm8741);
 580
 581        ret = snd_soc_register_codec(&i2c->dev,
 582                                     &soc_codec_dev_wm8741, &wm8741_dai, 1);
 583
 584        return ret;
 585}
 586
 587static int wm8741_i2c_remove(struct i2c_client *client)
 588{
 589        snd_soc_unregister_codec(&client->dev);
 590        return 0;
 591}
 592
 593static const struct i2c_device_id wm8741_i2c_id[] = {
 594        { "wm8741", 0 },
 595        { }
 596};
 597MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id);
 598
 599static struct i2c_driver wm8741_i2c_driver = {
 600        .driver = {
 601                .name = "wm8741",
 602                .of_match_table = wm8741_of_match,
 603        },
 604        .probe =    wm8741_i2c_probe,
 605        .remove =   wm8741_i2c_remove,
 606        .id_table = wm8741_i2c_id,
 607};
 608#endif
 609
 610#if defined(CONFIG_SPI_MASTER)
 611static int wm8741_spi_probe(struct spi_device *spi)
 612{
 613        struct wm8741_priv *wm8741;
 614        int ret, i;
 615
 616        wm8741 = devm_kzalloc(&spi->dev, sizeof(struct wm8741_priv),
 617                             GFP_KERNEL);
 618        if (wm8741 == NULL)
 619                return -ENOMEM;
 620
 621        for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++)
 622                wm8741->supplies[i].supply = wm8741_supply_names[i];
 623
 624        ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8741->supplies),
 625                                      wm8741->supplies);
 626        if (ret != 0) {
 627                dev_err(&spi->dev, "Failed to request supplies: %d\n", ret);
 628                return ret;
 629        }
 630
 631        wm8741->regmap = devm_regmap_init_spi(spi, &wm8741_regmap);
 632        if (IS_ERR(wm8741->regmap)) {
 633                ret = PTR_ERR(wm8741->regmap);
 634                dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
 635                return ret;
 636        }
 637
 638        ret = wm8741_set_pdata(&spi->dev, wm8741);
 639        if (ret != 0) {
 640                dev_err(&spi->dev, "Failed to set pdata: %d\n", ret);
 641                return ret;
 642        }
 643
 644        spi_set_drvdata(spi, wm8741);
 645
 646        ret = snd_soc_register_codec(&spi->dev,
 647                        &soc_codec_dev_wm8741, &wm8741_dai, 1);
 648        return ret;
 649}
 650
 651static int wm8741_spi_remove(struct spi_device *spi)
 652{
 653        snd_soc_unregister_codec(&spi->dev);
 654        return 0;
 655}
 656
 657static struct spi_driver wm8741_spi_driver = {
 658        .driver = {
 659                .name   = "wm8741",
 660                .of_match_table = wm8741_of_match,
 661        },
 662        .probe          = wm8741_spi_probe,
 663        .remove         = wm8741_spi_remove,
 664};
 665#endif /* CONFIG_SPI_MASTER */
 666
 667static int __init wm8741_modinit(void)
 668{
 669        int ret = 0;
 670
 671#if IS_ENABLED(CONFIG_I2C)
 672        ret = i2c_add_driver(&wm8741_i2c_driver);
 673        if (ret != 0)
 674                pr_err("Failed to register WM8741 I2C driver: %d\n", ret);
 675#endif
 676#if defined(CONFIG_SPI_MASTER)
 677        ret = spi_register_driver(&wm8741_spi_driver);
 678        if (ret != 0) {
 679                printk(KERN_ERR "Failed to register wm8741 SPI driver: %d\n",
 680                       ret);
 681        }
 682#endif
 683
 684        return ret;
 685}
 686module_init(wm8741_modinit);
 687
 688static void __exit wm8741_exit(void)
 689{
 690#if defined(CONFIG_SPI_MASTER)
 691        spi_unregister_driver(&wm8741_spi_driver);
 692#endif
 693#if IS_ENABLED(CONFIG_I2C)
 694        i2c_del_driver(&wm8741_i2c_driver);
 695#endif
 696}
 697module_exit(wm8741_exit);
 698
 699MODULE_DESCRIPTION("ASoC WM8741 driver");
 700MODULE_AUTHOR("Ian Lartey <ian@opensource.wolfsonmicro.com>");
 701MODULE_LICENSE("GPL");
 702