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/of.h> 18 #include <linux/regmap.h> 19 #include <linux/regulator/consumer.h> 20 #include <linux/slab.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 31 static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { 32 "AVDD", 33 "DVDD", 34 }; 35 36 /* codec private data */ 37 struct 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 45 static 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 58 static int wm8741_reset(struct snd_soc_component *component) 59 { 60 return snd_soc_component_write(component, WM8741_RESET, 0); 61 } 62 63 static const DECLARE_TLV_DB_SCALE(dac_tlv_fine, -12700, 13, 0); 64 static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 400, 0); 65 66 static const struct snd_kcontrol_new wm8741_snd_controls_stereo[] = { 67 SOC_DOUBLE_R_TLV("Fine Playback Volume", WM8741_DACLLSB_ATTENUATION, 68 WM8741_DACRLSB_ATTENUATION, 1, 255, 1, dac_tlv_fine), 69 SOC_DOUBLE_R_TLV("Playback Volume", WM8741_DACLMSB_ATTENUATION, 70 WM8741_DACRMSB_ATTENUATION, 0, 511, 1, dac_tlv), 71 }; 72 73 static const struct snd_kcontrol_new wm8741_snd_controls_mono_left[] = { 74 SOC_SINGLE_TLV("Fine Playback Volume", WM8741_DACLLSB_ATTENUATION, 75 1, 255, 1, dac_tlv_fine), 76 SOC_SINGLE_TLV("Playback Volume", WM8741_DACLMSB_ATTENUATION, 77 0, 511, 1, dac_tlv), 78 }; 79 80 static const struct snd_kcontrol_new wm8741_snd_controls_mono_right[] = { 81 SOC_SINGLE_TLV("Fine Playback Volume", WM8741_DACRLSB_ATTENUATION, 82 1, 255, 1, dac_tlv_fine), 83 SOC_SINGLE_TLV("Playback Volume", WM8741_DACRMSB_ATTENUATION, 84 0, 511, 1, dac_tlv), 85 }; 86 87 static const struct snd_soc_dapm_widget wm8741_dapm_widgets[] = { 88 SND_SOC_DAPM_DAC("DACL", "Playback", SND_SOC_NOPM, 0, 0), 89 SND_SOC_DAPM_DAC("DACR", "Playback", SND_SOC_NOPM, 0, 0), 90 SND_SOC_DAPM_OUTPUT("VOUTLP"), 91 SND_SOC_DAPM_OUTPUT("VOUTLN"), 92 SND_SOC_DAPM_OUTPUT("VOUTRP"), 93 SND_SOC_DAPM_OUTPUT("VOUTRN"), 94 }; 95 96 static 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 103 static const unsigned int rates_11289[] = { 104 44100, 88200, 105 }; 106 107 static const struct snd_pcm_hw_constraint_list constraints_11289 = { 108 .count = ARRAY_SIZE(rates_11289), 109 .list = rates_11289, 110 }; 111 112 static const unsigned int rates_12288[] = { 113 32000, 48000, 96000, 114 }; 115 116 static const struct snd_pcm_hw_constraint_list constraints_12288 = { 117 .count = ARRAY_SIZE(rates_12288), 118 .list = rates_12288, 119 }; 120 121 static const unsigned int rates_16384[] = { 122 32000, 123 }; 124 125 static const struct snd_pcm_hw_constraint_list constraints_16384 = { 126 .count = ARRAY_SIZE(rates_16384), 127 .list = rates_16384, 128 }; 129 130 static const unsigned int rates_16934[] = { 131 44100, 88200, 132 }; 133 134 static const struct snd_pcm_hw_constraint_list constraints_16934 = { 135 .count = ARRAY_SIZE(rates_16934), 136 .list = rates_16934, 137 }; 138 139 static const unsigned int rates_18432[] = { 140 48000, 96000, 141 }; 142 143 static const struct snd_pcm_hw_constraint_list constraints_18432 = { 144 .count = ARRAY_SIZE(rates_18432), 145 .list = rates_18432, 146 }; 147 148 static const unsigned int rates_22579[] = { 149 44100, 88200, 176400 150 }; 151 152 static const struct snd_pcm_hw_constraint_list constraints_22579 = { 153 .count = ARRAY_SIZE(rates_22579), 154 .list = rates_22579, 155 }; 156 157 static const unsigned int rates_24576[] = { 158 32000, 48000, 96000, 192000 159 }; 160 161 static const struct snd_pcm_hw_constraint_list constraints_24576 = { 162 .count = ARRAY_SIZE(rates_24576), 163 .list = rates_24576, 164 }; 165 166 static const unsigned int rates_36864[] = { 167 48000, 96000, 192000 168 }; 169 170 static const struct snd_pcm_hw_constraint_list constraints_36864 = { 171 .count = ARRAY_SIZE(rates_36864), 172 .list = rates_36864, 173 }; 174 175 static 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 189 static 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 258 static 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 303 static 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 367 static 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 384 static 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 393 static 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 406 static 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 415 static 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 446 static 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 474 static 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 507 err_enable: 508 regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); 509 err_get: 510 return ret; 511 } 512 513 static 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 520 static 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 }; 532 533 static const struct of_device_id wm8741_of_match[] = { 534 { .compatible = "wlf,wm8741", }, 535 { } 536 }; 537 MODULE_DEVICE_TABLE(of, wm8741_of_match); 538 539 static 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_MAPLE, 547 }; 548 549 static 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) 567 static int wm8741_i2c_probe(struct i2c_client *i2c) 568 { 569 struct wm8741_priv *wm8741; 570 int ret, i; 571 572 wm8741 = devm_kzalloc(&i2c->dev, sizeof(struct wm8741_priv), 573 GFP_KERNEL); 574 if (wm8741 == NULL) 575 return -ENOMEM; 576 577 for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) 578 wm8741->supplies[i].supply = wm8741_supply_names[i]; 579 580 ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), 581 wm8741->supplies); 582 if (ret != 0) { 583 dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); 584 return ret; 585 } 586 587 wm8741->regmap = devm_regmap_init_i2c(i2c, &wm8741_regmap); 588 if (IS_ERR(wm8741->regmap)) { 589 ret = PTR_ERR(wm8741->regmap); 590 dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); 591 return ret; 592 } 593 594 ret = wm8741_set_pdata(&i2c->dev, wm8741); 595 if (ret != 0) { 596 dev_err(&i2c->dev, "Failed to set pdata: %d\n", ret); 597 return ret; 598 } 599 600 i2c_set_clientdata(i2c, wm8741); 601 602 ret = devm_snd_soc_register_component(&i2c->dev, 603 &soc_component_dev_wm8741, &wm8741_dai, 1); 604 605 return ret; 606 } 607 608 static const struct i2c_device_id wm8741_i2c_id[] = { 609 { "wm8741" }, 610 { } 611 }; 612 MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); 613 614 static struct i2c_driver wm8741_i2c_driver = { 615 .driver = { 616 .name = "wm8741", 617 .of_match_table = wm8741_of_match, 618 }, 619 .probe = wm8741_i2c_probe, 620 .id_table = wm8741_i2c_id, 621 }; 622 #endif 623 624 #if defined(CONFIG_SPI_MASTER) 625 static int wm8741_spi_probe(struct spi_device *spi) 626 { 627 struct wm8741_priv *wm8741; 628 int ret, i; 629 630 wm8741 = devm_kzalloc(&spi->dev, sizeof(struct wm8741_priv), 631 GFP_KERNEL); 632 if (wm8741 == NULL) 633 return -ENOMEM; 634 635 for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) 636 wm8741->supplies[i].supply = wm8741_supply_names[i]; 637 638 ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8741->supplies), 639 wm8741->supplies); 640 if (ret != 0) { 641 dev_err(&spi->dev, "Failed to request supplies: %d\n", ret); 642 return ret; 643 } 644 645 wm8741->regmap = devm_regmap_init_spi(spi, &wm8741_regmap); 646 if (IS_ERR(wm8741->regmap)) { 647 ret = PTR_ERR(wm8741->regmap); 648 dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); 649 return ret; 650 } 651 652 ret = wm8741_set_pdata(&spi->dev, wm8741); 653 if (ret != 0) { 654 dev_err(&spi->dev, "Failed to set pdata: %d\n", ret); 655 return ret; 656 } 657 658 spi_set_drvdata(spi, wm8741); 659 660 ret = devm_snd_soc_register_component(&spi->dev, 661 &soc_component_dev_wm8741, &wm8741_dai, 1); 662 return ret; 663 } 664 665 static struct spi_driver wm8741_spi_driver = { 666 .driver = { 667 .name = "wm8741", 668 .of_match_table = wm8741_of_match, 669 }, 670 .probe = wm8741_spi_probe, 671 }; 672 #endif /* CONFIG_SPI_MASTER */ 673 674 static int __init wm8741_modinit(void) 675 { 676 int ret = 0; 677 678 #if IS_ENABLED(CONFIG_I2C) 679 ret = i2c_add_driver(&wm8741_i2c_driver); 680 if (ret != 0) 681 pr_err("Failed to register WM8741 I2C driver: %d\n", ret); 682 #endif 683 #if defined(CONFIG_SPI_MASTER) 684 ret = spi_register_driver(&wm8741_spi_driver); 685 if (ret != 0) { 686 printk(KERN_ERR "Failed to register wm8741 SPI driver: %d\n", 687 ret); 688 } 689 #endif 690 691 return ret; 692 } 693 module_init(wm8741_modinit); 694 695 static void __exit wm8741_exit(void) 696 { 697 #if defined(CONFIG_SPI_MASTER) 698 spi_unregister_driver(&wm8741_spi_driver); 699 #endif 700 #if IS_ENABLED(CONFIG_I2C) 701 i2c_del_driver(&wm8741_i2c_driver); 702 #endif 703 } 704 module_exit(wm8741_exit); 705 706 MODULE_DESCRIPTION("ASoC WM8741 driver"); 707 MODULE_AUTHOR("Ian Lartey <ian@opensource.wolfsonmicro.com>"); 708 MODULE_LICENSE("GPL"); 709
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.