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