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