wm8741.c (18037B)
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, int direction) 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 .mute_stream = wm8741_mute, 390 .no_capture_mute = 1, 391}; 392 393static struct snd_soc_dai_driver wm8741_dai = { 394 .name = "wm8741", 395 .playback = { 396 .stream_name = "Playback", 397 .channels_min = 2, 398 .channels_max = 2, 399 .rates = WM8741_RATES, 400 .formats = WM8741_FORMATS, 401 }, 402 .ops = &wm8741_dai_ops, 403}; 404 405#ifdef CONFIG_PM 406static int wm8741_resume(struct snd_soc_component *component) 407{ 408 snd_soc_component_cache_sync(component); 409 return 0; 410} 411#else 412#define wm8741_resume NULL 413#endif 414 415static int wm8741_configure(struct snd_soc_component *component) 416{ 417 struct wm8741_priv *wm8741 = snd_soc_component_get_drvdata(component); 418 419 /* Configure differential mode */ 420 switch (wm8741->pdata.diff_mode) { 421 case WM8741_DIFF_MODE_STEREO: 422 case WM8741_DIFF_MODE_STEREO_REVERSED: 423 case WM8741_DIFF_MODE_MONO_LEFT: 424 case WM8741_DIFF_MODE_MONO_RIGHT: 425 snd_soc_component_update_bits(component, WM8741_MODE_CONTROL_2, 426 WM8741_DIFF_MASK, 427 wm8741->pdata.diff_mode << WM8741_DIFF_SHIFT); 428 break; 429 default: 430 return -EINVAL; 431 } 432 433 /* Change some default settings - latch VU */ 434 snd_soc_component_update_bits(component, WM8741_DACLLSB_ATTENUATION, 435 WM8741_UPDATELL, WM8741_UPDATELL); 436 snd_soc_component_update_bits(component, WM8741_DACLMSB_ATTENUATION, 437 WM8741_UPDATELM, WM8741_UPDATELM); 438 snd_soc_component_update_bits(component, WM8741_DACRLSB_ATTENUATION, 439 WM8741_UPDATERL, WM8741_UPDATERL); 440 snd_soc_component_update_bits(component, WM8741_DACRMSB_ATTENUATION, 441 WM8741_UPDATERM, WM8741_UPDATERM); 442 443 return 0; 444} 445 446static int wm8741_add_controls(struct snd_soc_component *component) 447{ 448 struct wm8741_priv *wm8741 = snd_soc_component_get_drvdata(component); 449 450 switch (wm8741->pdata.diff_mode) { 451 case WM8741_DIFF_MODE_STEREO: 452 case WM8741_DIFF_MODE_STEREO_REVERSED: 453 snd_soc_add_component_controls(component, 454 wm8741_snd_controls_stereo, 455 ARRAY_SIZE(wm8741_snd_controls_stereo)); 456 break; 457 case WM8741_DIFF_MODE_MONO_LEFT: 458 snd_soc_add_component_controls(component, 459 wm8741_snd_controls_mono_left, 460 ARRAY_SIZE(wm8741_snd_controls_mono_left)); 461 break; 462 case WM8741_DIFF_MODE_MONO_RIGHT: 463 snd_soc_add_component_controls(component, 464 wm8741_snd_controls_mono_right, 465 ARRAY_SIZE(wm8741_snd_controls_mono_right)); 466 break; 467 default: 468 return -EINVAL; 469 } 470 471 return 0; 472} 473 474static int wm8741_probe(struct snd_soc_component *component) 475{ 476 struct wm8741_priv *wm8741 = snd_soc_component_get_drvdata(component); 477 int ret = 0; 478 479 ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), 480 wm8741->supplies); 481 if (ret != 0) { 482 dev_err(component->dev, "Failed to enable supplies: %d\n", ret); 483 goto err_get; 484 } 485 486 ret = wm8741_reset(component); 487 if (ret < 0) { 488 dev_err(component->dev, "Failed to issue reset\n"); 489 goto err_enable; 490 } 491 492 ret = wm8741_configure(component); 493 if (ret < 0) { 494 dev_err(component->dev, "Failed to change default settings\n"); 495 goto err_enable; 496 } 497 498 ret = wm8741_add_controls(component); 499 if (ret < 0) { 500 dev_err(component->dev, "Failed to add controls\n"); 501 goto err_enable; 502 } 503 504 dev_dbg(component->dev, "Successful registration\n"); 505 return ret; 506 507err_enable: 508 regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); 509err_get: 510 return ret; 511} 512 513static void wm8741_remove(struct snd_soc_component *component) 514{ 515 struct wm8741_priv *wm8741 = snd_soc_component_get_drvdata(component); 516 517 regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); 518} 519 520static const struct snd_soc_component_driver soc_component_dev_wm8741 = { 521 .probe = wm8741_probe, 522 .remove = wm8741_remove, 523 .resume = wm8741_resume, 524 .dapm_widgets = wm8741_dapm_widgets, 525 .num_dapm_widgets = ARRAY_SIZE(wm8741_dapm_widgets), 526 .dapm_routes = wm8741_dapm_routes, 527 .num_dapm_routes = ARRAY_SIZE(wm8741_dapm_routes), 528 .idle_bias_on = 1, 529 .use_pmdown_time = 1, 530 .endianness = 1, 531 .non_legacy_dai_naming = 1, 532}; 533 534static const struct of_device_id wm8741_of_match[] = { 535 { .compatible = "wlf,wm8741", }, 536 { } 537}; 538MODULE_DEVICE_TABLE(of, wm8741_of_match); 539 540static const struct regmap_config wm8741_regmap = { 541 .reg_bits = 7, 542 .val_bits = 9, 543 .max_register = WM8741_MAX_REGISTER, 544 545 .reg_defaults = wm8741_reg_defaults, 546 .num_reg_defaults = ARRAY_SIZE(wm8741_reg_defaults), 547 .cache_type = REGCACHE_RBTREE, 548}; 549 550static int wm8741_set_pdata(struct device *dev, struct wm8741_priv *wm8741) 551{ 552 const struct wm8741_platform_data *pdata = dev_get_platdata(dev); 553 u32 diff_mode; 554 555 if (dev->of_node) { 556 if (of_property_read_u32(dev->of_node, "diff-mode", &diff_mode) 557 >= 0) 558 wm8741->pdata.diff_mode = diff_mode; 559 } else { 560 if (pdata != NULL) 561 memcpy(&wm8741->pdata, pdata, sizeof(wm8741->pdata)); 562 } 563 564 return 0; 565} 566 567#if IS_ENABLED(CONFIG_I2C) 568static int wm8741_i2c_probe(struct i2c_client *i2c) 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_new = 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");