1 /* 2 * wm8776.c -- WM8776 ALSA SoC Audio driver 3 * 4 * Copyright 2009 Wolfson Microelectronics plc 5 * 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 * TODO: Input ALC/limiter support 13 */ 14 15 #include <linux/module.h> 16 #include <linux/moduleparam.h> 17 #include <linux/init.h> 18 #include <linux/delay.h> 19 #include <linux/pm.h> 20 #include <linux/i2c.h> 21 #include <linux/platform_device.h> 22 #include <linux/spi/spi.h> 23 #include <sound/core.h> 24 #include <sound/pcm.h> 25 #include <sound/pcm_params.h> 26 #include <sound/soc.h> 27 #include <sound/soc-dapm.h> 28 #include <sound/initval.h> 29 #include <sound/tlv.h> 30 31 #include "wm8776.h" 32 33 static struct snd_soc_codec *wm8776_codec; 34 struct snd_soc_codec_device soc_codec_dev_wm8776; 35 36 /* codec private data */ 37 struct wm8776_priv { 38 struct snd_soc_codec codec; 39 u16 reg_cache[WM8776_CACHEREGNUM]; 40 int sysclk[2]; 41 }; 42 43 #ifdef CONFIG_SPI_MASTER 44 static int wm8776_spi_write(struct spi_device *spi, const char *data, int len); 45 #endif 46 47 static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { 48 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ 49 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ 50 0x22, 0x22, 0x22, 0x08, 0xcf, /* 14 */ 51 0xcf, 0x7b, 0x00, 0x32, 0x00, /* 19 */ 52 0xa6, 0x01, 0x01 53 }; 54 55 /* 56 * read wm8776 register cache 57 */ 58 static inline unsigned int wm8776_read_reg_cache(struct snd_soc_codec *codec, 59 unsigned int reg) 60 { 61 u16 *cache = codec->reg_cache; 62 if (reg >= WM8776_CACHEREGNUM) 63 return -1; 64 return cache[reg]; 65 } 66 67 /* 68 * write wm8776 register cache 69 */ 70 static inline void wm8776_write_reg_cache(struct snd_soc_codec *codec, 71 u16 reg, unsigned int value) 72 { 73 u16 *cache = codec->reg_cache; 74 if (reg >= WM8776_CACHEREGNUM) 75 return; 76 cache[reg] = value; 77 } 78 79 /* 80 * write to the WM8776 register space 81 */ 82 static int wm8776_write(struct snd_soc_codec *codec, unsigned int reg, 83 unsigned int value) 84 { 85 u8 data[2]; 86 87 data[0] = (reg << 1) | ((value >> 8) & 0x0001); 88 data[1] = value & 0x00ff; 89 90 wm8776_write_reg_cache(codec, reg, value); 91 if (codec->hw_write(codec->control_data, data, 2) == 2) 92 return 0; 93 else 94 return -EIO; 95 } 96 97 static int wm8776_reset(struct snd_soc_codec *codec) 98 { 99 return wm8776_write(codec, WM8776_RESET, 0); 100 } 101 102 static const DECLARE_TLV_DB_SCALE(hp_tlv, -12100, 100, 1); 103 static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); 104 static const DECLARE_TLV_DB_SCALE(adc_tlv, -10350, 50, 1); 105 106 static const struct snd_kcontrol_new wm8776_snd_controls[] = { 107 SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8776_HPLVOL, WM8776_HPRVOL, 108 0, 127, 0, hp_tlv), 109 SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8776_DACLVOL, WM8776_DACRVOL, 110 0, 255, 0, dac_tlv), 111 SOC_SINGLE("Digital Playback ZC Switch", WM8776_DACCTRL1, 0, 1, 0), 112 113 SOC_SINGLE("Deemphasis Switch", WM8776_DACCTRL2, 0, 1, 0), 114 115 SOC_DOUBLE_R_TLV("Capture Volume", WM8776_ADCLVOL, WM8776_ADCRVOL, 116 0, 255, 0, adc_tlv), 117 SOC_DOUBLE("Capture Switch", WM8776_ADCMUX, 7, 6, 1, 1), 118 SOC_DOUBLE_R("Capture ZC Switch", WM8776_ADCLVOL, WM8776_ADCRVOL, 8, 1, 0), 119 SOC_SINGLE("Capture HPF Switch", WM8776_ADCIFCTRL, 8, 1, 1), 120 }; 121 122 static const struct snd_kcontrol_new inmix_controls[] = { 123 SOC_DAPM_SINGLE("AIN1 Switch", WM8776_ADCMUX, 0, 1, 0), 124 SOC_DAPM_SINGLE("AIN2 Switch", WM8776_ADCMUX, 1, 1, 0), 125 SOC_DAPM_SINGLE("AIN3 Switch", WM8776_ADCMUX, 2, 1, 0), 126 SOC_DAPM_SINGLE("AIN4 Switch", WM8776_ADCMUX, 3, 1, 0), 127 SOC_DAPM_SINGLE("AIN5 Switch", WM8776_ADCMUX, 4, 1, 0), 128 }; 129 130 static const struct snd_kcontrol_new outmix_controls[] = { 131 SOC_DAPM_SINGLE("DAC Switch", WM8776_OUTMUX, 0, 1, 0), 132 SOC_DAPM_SINGLE("AUX Switch", WM8776_OUTMUX, 1, 1, 0), 133 SOC_DAPM_SINGLE("Bypass Switch", WM8776_OUTMUX, 2, 1, 0), 134 }; 135 136 static const struct snd_soc_dapm_widget wm8776_dapm_widgets[] = { 137 SND_SOC_DAPM_INPUT("AUX"), 138 SND_SOC_DAPM_INPUT("AUX"), 139 140 SND_SOC_DAPM_INPUT("AIN1"), 141 SND_SOC_DAPM_INPUT("AIN2"), 142 SND_SOC_DAPM_INPUT("AIN3"), 143 SND_SOC_DAPM_INPUT("AIN4"), 144 SND_SOC_DAPM_INPUT("AIN5"), 145 146 SND_SOC_DAPM_MIXER("Input Mixer", WM8776_PWRDOWN, 6, 1, 147 inmix_controls, ARRAY_SIZE(inmix_controls)), 148 149 SND_SOC_DAPM_ADC("ADC", "Capture", WM8776_PWRDOWN, 1, 1), 150 SND_SOC_DAPM_DAC("DAC", "Playback", WM8776_PWRDOWN, 2, 1), 151 152 SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0, 153 outmix_controls, ARRAY_SIZE(outmix_controls)), 154 155 SND_SOC_DAPM_PGA("Headphone PGA", WM8776_PWRDOWN, 3, 1, NULL, 0), 156 157 SND_SOC_DAPM_OUTPUT("VOUT"), 158 159 SND_SOC_DAPM_OUTPUT("HPOUTL"), 160 SND_SOC_DAPM_OUTPUT("HPOUTR"), 161 }; 162 163 static const struct snd_soc_dapm_route routes[] = { 164 { "Input Mixer", "AIN1 Switch", "AIN1" }, 165 { "Input Mixer", "AIN2 Switch", "AIN2" }, 166 { "Input Mixer", "AIN3 Switch", "AIN3" }, 167 { "Input Mixer", "AIN4 Switch", "AIN4" }, 168 { "Input Mixer", "AIN5 Switch", "AIN5" }, 169 170 { "ADC", NULL, "Input Mixer" }, 171 172 { "Output Mixer", "DAC Switch", "DAC" }, 173 { "Output Mixer", "AUX Switch", "AUX" }, 174 { "Output Mixer", "Bypass Switch", "Input Mixer" }, 175 176 { "VOUT", NULL, "Output Mixer" }, 177 178 { "Headphone PGA", NULL, "Output Mixer" }, 179 180 { "HPOUTL", NULL, "Headphone PGA" }, 181 { "HPOUTR", NULL, "Headphone PGA" }, 182 }; 183 184 static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 185 { 186 struct snd_soc_codec *codec = dai->codec; 187 int reg, iface, master; 188 189 switch (dai->id) { 190 case WM8776_DAI_DAC: 191 reg = WM8776_DACIFCTRL; 192 master = 0x80; 193 break; 194 case WM8776_DAI_ADC: 195 reg = WM8776_ADCIFCTRL; 196 master = 0x100; 197 break; 198 default: 199 return -EINVAL; 200 } 201 202 iface = 0; 203 204 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 205 case SND_SOC_DAIFMT_CBM_CFM: 206 break; 207 case SND_SOC_DAIFMT_CBS_CFS: 208 master = 0; 209 break; 210 default: 211 return -EINVAL; 212 } 213 214 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 215 case SND_SOC_DAIFMT_I2S: 216 iface |= 0x0002; 217 break; 218 case SND_SOC_DAIFMT_RIGHT_J: 219 break; 220 case SND_SOC_DAIFMT_LEFT_J: 221 iface |= 0x0001; 222 break; 223 /* FIXME: CHECK A/B */ 224 case SND_SOC_DAIFMT_DSP_A: 225 iface |= 0x0003; 226 break; 227 case SND_SOC_DAIFMT_DSP_B: 228 iface |= 0x0007; 229 break; 230 default: 231 return -EINVAL; 232 } 233 234 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 235 case SND_SOC_DAIFMT_NB_NF: 236 break; 237 case SND_SOC_DAIFMT_IB_IF: 238 iface |= 0x00c; 239 break; 240 case SND_SOC_DAIFMT_IB_NF: 241 iface |= 0x008; 242 break; 243 case SND_SOC_DAIFMT_NB_IF: 244 iface |= 0x004; 245 break; 246 default: 247 return -EINVAL; 248 } 249 250 /* Finally, write out the values */ 251 snd_soc_update_bits(codec, reg, 0xf, iface); 252 snd_soc_update_bits(codec, WM8776_MSTRCTRL, 0x180, master); 253 254 return 0; 255 } 256 257 static int mclk_ratios[] = { 258 128, 259 192, 260 256, 261 384, 262 512, 263 768, 264 }; 265 266 static int wm8776_hw_params(struct snd_pcm_substream *substream, 267 struct snd_pcm_hw_params *params, 268 struct snd_soc_dai *dai) 269 { 270 struct snd_soc_codec *codec = dai->codec; 271 struct wm8776_priv *wm8776 = codec->private_data; 272 int iface_reg, iface; 273 int ratio_shift, master; 274 int i; 275 276 iface = 0; 277 278 switch (dai->id) { 279 case WM8776_DAI_DAC: 280 iface_reg = WM8776_DACIFCTRL; 281 master = 0x80; 282 ratio_shift = 4; 283 break; 284 case WM8776_DAI_ADC: 285 iface_reg = WM8776_ADCIFCTRL; 286 master = 0x100; 287 ratio_shift = 0; 288 break; 289 default: 290 return -EINVAL; 291 } 292 293 294 /* Set word length */ 295 switch (params_format(params)) { 296 case SNDRV_PCM_FORMAT_S16_LE: 297 break; 298 case SNDRV_PCM_FORMAT_S20_3LE: 299 iface |= 0x10; 300 break; 301 case SNDRV_PCM_FORMAT_S24_LE: 302 iface |= 0x20; 303 break; 304 case SNDRV_PCM_FORMAT_S32_LE: 305 iface |= 0x30; 306 break; 307 } 308 309 /* Only need to set MCLK/LRCLK ratio if we're master */ 310 if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) { 311 for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) { 312 if (wm8776->sysclk[dai->id] / params_rate(params) 313 == mclk_ratios[i]) 314 break; 315 } 316 317 if (i == ARRAY_SIZE(mclk_ratios)) { 318 dev_err(codec->dev, 319 "Unable to configure MCLK ratio %d/%d\n", 320 wm8776->sysclk[dai->id], params_rate(params)); 321 return -EINVAL; 322 } 323 324 dev_dbg(codec->dev, "MCLK is %dfs\n", mclk_ratios[i]); 325 326 snd_soc_update_bits(codec, WM8776_MSTRCTRL, 327 0x7 << ratio_shift, i << ratio_shift); 328 } else { 329 dev_dbg(codec->dev, "DAI in slave mode\n"); 330 } 331 332 snd_soc_update_bits(codec, iface_reg, 0x30, iface); 333 334 return 0; 335 } 336 337 static int wm8776_mute(struct snd_soc_dai *dai, int mute) 338 { 339 struct snd_soc_codec *codec = dai->codec; 340 341 return snd_soc_write(codec, WM8776_DACMUTE, !!mute); 342 } 343 344 static int wm8776_set_sysclk(struct snd_soc_dai *dai, 345 int clk_id, unsigned int freq, int dir) 346 { 347 struct snd_soc_codec *codec = dai->codec; 348 struct wm8776_priv *wm8776 = codec->private_data; 349 350 BUG_ON(dai->id >= ARRAY_SIZE(wm8776->sysclk)); 351 352 wm8776->sysclk[dai->id] = freq; 353 354 return 0; 355 } 356 357 static int wm8776_set_bias_level(struct snd_soc_codec *codec, 358 enum snd_soc_bias_level level) 359 { 360 switch (level) { 361 case SND_SOC_BIAS_ON: 362 break; 363 case SND_SOC_BIAS_PREPARE: 364 break; 365 case SND_SOC_BIAS_STANDBY: 366 if (codec->bias_level == SND_SOC_BIAS_OFF) { 367 /* Disable the global powerdown; DAPM does the rest */ 368 snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); 369 } 370 371 break; 372 case SND_SOC_BIAS_OFF: 373 snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 1); 374 break; 375 } 376 377 codec->bias_level = level; 378 return 0; 379 } 380 381 #define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ 382 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ 383 SNDRV_PCM_RATE_96000) 384 385 386 #define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 387 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 388 389 static struct snd_soc_dai_ops wm8776_dac_ops = { 390 .digital_mute = wm8776_mute, 391 .hw_params = wm8776_hw_params, 392 .set_fmt = wm8776_set_fmt, 393 .set_sysclk = wm8776_set_sysclk, 394 }; 395 396 static struct snd_soc_dai_ops wm8776_adc_ops = { 397 .hw_params = wm8776_hw_params, 398 .set_fmt = wm8776_set_fmt, 399 .set_sysclk = wm8776_set_sysclk, 400 }; 401 402 struct snd_soc_dai wm8776_dai[] = { 403 { 404 .name = "WM8776 Playback", 405 .id = WM8776_DAI_DAC, 406 .playback = { 407 .stream_name = "Playback", 408 .channels_min = 2, 409 .channels_max = 2, 410 .rates = WM8776_RATES, 411 .formats = WM8776_FORMATS, 412 }, 413 .ops = &wm8776_dac_ops, 414 }, 415 { 416 .name = "WM8776 Capture", 417 .id = WM8776_DAI_ADC, 418 .capture = { 419 .stream_name = "Capture", 420 .channels_min = 2, 421 .channels_max = 2, 422 .rates = WM8776_RATES, 423 .formats = WM8776_FORMATS, 424 }, 425 .ops = &wm8776_adc_ops, 426 }, 427 }; 428 EXPORT_SYMBOL_GPL(wm8776_dai); 429 430 #ifdef CONFIG_PM 431 static int wm8776_suspend(struct platform_device *pdev, pm_message_t state) 432 { 433 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 434 struct snd_soc_codec *codec = socdev->card->codec; 435 436 wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); 437 438 return 0; 439 } 440 441 static int wm8776_resume(struct platform_device *pdev) 442 { 443 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 444 struct snd_soc_codec *codec = socdev->card->codec; 445 int i; 446 u8 data[2]; 447 u16 *cache = codec->reg_cache; 448 449 /* Sync reg_cache with the hardware */ 450 for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) { 451 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); 452 data[1] = cache[i] & 0x00ff; 453 codec->hw_write(codec->control_data, data, 2); 454 } 455 456 wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 457 458 return 0; 459 } 460 #else 461 #define wm8776_suspend NULL 462 #define wm8776_resume NULL 463 #endif 464 465 static int wm8776_probe(struct platform_device *pdev) 466 { 467 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 468 struct snd_soc_codec *codec; 469 int ret = 0; 470 471 if (wm8776_codec == NULL) { 472 dev_err(&pdev->dev, "Codec device not registered\n"); 473 return -ENODEV; 474 } 475 476 socdev->card->codec = wm8776_codec; 477 codec = wm8776_codec; 478 479 /* register pcms */ 480 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 481 if (ret < 0) { 482 dev_err(codec->dev, "failed to create pcms: %d\n", ret); 483 goto pcm_err; 484 } 485 486 snd_soc_add_controls(codec, wm8776_snd_controls, 487 ARRAY_SIZE(wm8776_snd_controls)); 488 snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets, 489 ARRAY_SIZE(wm8776_dapm_widgets)); 490 snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); 491 492 ret = snd_soc_init_card(socdev); 493 if (ret < 0) { 494 dev_err(codec->dev, "failed to register card: %d\n", ret); 495 goto card_err; 496 } 497 498 return ret; 499 500 card_err: 501 snd_soc_free_pcms(socdev); 502 snd_soc_dapm_free(socdev); 503 pcm_err: 504 return ret; 505 } 506 507 /* power down chip */ 508 static int wm8776_remove(struct platform_device *pdev) 509 { 510 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 511 512 snd_soc_free_pcms(socdev); 513 snd_soc_dapm_free(socdev); 514 515 return 0; 516 } 517 518 struct snd_soc_codec_device soc_codec_dev_wm8776 = { 519 .probe = wm8776_probe, 520 .remove = wm8776_remove, 521 .suspend = wm8776_suspend, 522 .resume = wm8776_resume, 523 }; 524 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8776); 525 526 static int wm8776_register(struct wm8776_priv *wm8776) 527 { 528 int ret, i; 529 struct snd_soc_codec *codec = &wm8776->codec; 530 531 if (wm8776_codec) { 532 dev_err(codec->dev, "Another WM8776 is registered\n"); 533 ret = -EINVAL; 534 goto err; 535 } 536 537 mutex_init(&codec->mutex); 538 INIT_LIST_HEAD(&codec->dapm_widgets); 539 INIT_LIST_HEAD(&codec->dapm_paths); 540 541 codec->private_data = wm8776; 542 codec->name = "WM8776"; 543 codec->owner = THIS_MODULE; 544 codec->read = wm8776_read_reg_cache; 545 codec->write = wm8776_write; 546 codec->bias_level = SND_SOC_BIAS_OFF; 547 codec->set_bias_level = wm8776_set_bias_level; 548 codec->dai = wm8776_dai; 549 codec->num_dai = ARRAY_SIZE(wm8776_dai); 550 codec->reg_cache_size = WM8776_CACHEREGNUM; 551 codec->reg_cache = &wm8776->reg_cache; 552 553 memcpy(codec->reg_cache, wm8776_reg, sizeof(wm8776_reg)); 554 555 for (i = 0; i < ARRAY_SIZE(wm8776_dai); i++) 556 wm8776_dai[i].dev = codec->dev; 557 558 ret = wm8776_reset(codec); 559 if (ret < 0) { 560 dev_err(codec->dev, "Failed to issue reset: %d\n", ret); 561 goto err; 562 } 563 564 wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 565 566 /* Latch the update bits; right channel only since we always 567 * update both. */ 568 snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); 569 snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100); 570 571 wm8776_codec = codec; 572 573 ret = snd_soc_register_codec(codec); 574 if (ret != 0) { 575 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 576 goto err; 577 } 578 579 ret = snd_soc_register_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai)); 580 if (ret != 0) { 581 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); 582 goto err_codec; 583 } 584 585 return 0; 586 587 err_codec: 588 snd_soc_unregister_codec(codec); 589 err: 590 kfree(wm8776); 591 return ret; 592 } 593 594 static void wm8776_unregister(struct wm8776_priv *wm8776) 595 { 596 wm8776_set_bias_level(&wm8776->codec, SND_SOC_BIAS_OFF); 597 snd_soc_unregister_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai)); 598 snd_soc_unregister_codec(&wm8776->codec); 599 kfree(wm8776); 600 wm8776_codec = NULL; 601 } 602 603 #if defined(CONFIG_SPI_MASTER) 604 static int wm8776_spi_write(struct spi_device *spi, const char *data, int len) 605 { 606 struct spi_transfer t; 607 struct spi_message m; 608 u8 msg[2]; 609 610 if (len <= 0) 611 return 0; 612 613 msg[0] = data[0]; 614 msg[1] = data[1]; 615 616 spi_message_init(&m); 617 memset(&t, 0, (sizeof t)); 618 619 t.tx_buf = &msg[0]; 620 t.len = len; 621 622 spi_message_add_tail(&t, &m); 623 spi_sync(spi, &m); 624 625 return len; 626 } 627 628 static int __devinit wm8776_spi_probe(struct spi_device *spi) 629 { 630 struct snd_soc_codec *codec; 631 struct wm8776_priv *wm8776; 632 633 wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); 634 if (wm8776 == NULL) 635 return -ENOMEM; 636 637 codec = &wm8776->codec; 638 codec->control_data = spi; 639 codec->hw_write = (hw_write_t)wm8776_spi_write; 640 codec->dev = &spi->dev; 641 642 dev_set_drvdata(&spi->dev, wm8776); 643 644 return wm8776_register(wm8776); 645 } 646 647 static int __devexit wm8776_spi_remove(struct spi_device *spi) 648 { 649 struct wm8776_priv *wm8776 = dev_get_drvdata(&spi->dev); 650 651 wm8776_unregister(wm8776); 652 653 return 0; 654 } 655 656 #ifdef CONFIG_PM 657 static int wm8776_spi_suspend(struct spi_device *spi, pm_message_t msg) 658 { 659 return snd_soc_suspend_device(&spi->dev); 660 } 661 662 static int wm8776_spi_resume(struct spi_device *spi) 663 { 664 return snd_soc_resume_device(&spi->dev); 665 } 666 #else 667 #define wm8776_spi_suspend NULL 668 #define wm8776_spi_resume NULL 669 #endif 670 671 static struct spi_driver wm8776_spi_driver = { 672 .driver = { 673 .name = "wm8776", 674 .bus = &spi_bus_type, 675 .owner = THIS_MODULE, 676 }, 677 .probe = wm8776_spi_probe, 678 .suspend = wm8776_spi_suspend, 679 .resume = wm8776_spi_resume, 680 .remove = __devexit_p(wm8776_spi_remove), 681 }; 682 #endif /* CONFIG_SPI_MASTER */ 683 684 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 685 static __devinit int wm8776_i2c_probe(struct i2c_client *i2c, 686 const struct i2c_device_id *id) 687 { 688 struct wm8776_priv *wm8776; 689 struct snd_soc_codec *codec; 690 691 wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); 692 if (wm8776 == NULL) 693 return -ENOMEM; 694 695 codec = &wm8776->codec; 696 codec->hw_write = (hw_write_t)i2c_master_send; 697 698 i2c_set_clientdata(i2c, wm8776); 699 codec->control_data = i2c; 700 701 codec->dev = &i2c->dev; 702 703 return wm8776_register(wm8776); 704 } 705 706 static __devexit int wm8776_i2c_remove(struct i2c_client *client) 707 { 708 struct wm8776_priv *wm8776 = i2c_get_clientdata(client); 709 wm8776_unregister(wm8776); 710 return 0; 711 } 712 713 #ifdef CONFIG_PM 714 static int wm8776_i2c_suspend(struct i2c_client *i2c, pm_message_t msg) 715 { 716 return snd_soc_suspend_device(&i2c->dev); 717 } 718 719 static int wm8776_i2c_resume(struct i2c_client *i2c) 720 { 721 return snd_soc_resume_device(&i2c->dev); 722 } 723 #else 724 #define wm8776_i2c_suspend NULL 725 #define wm8776_i2c_resume NULL 726 #endif 727 728 static const struct i2c_device_id wm8776_i2c_id[] = { 729 { "wm8776", 0 }, 730 { } 731 }; 732 MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id); 733 734 static struct i2c_driver wm8776_i2c_driver = { 735 .driver = { 736 .name = "wm8776", 737 .owner = THIS_MODULE, 738 }, 739 .probe = wm8776_i2c_probe, 740 .remove = __devexit_p(wm8776_i2c_remove), 741 .suspend = wm8776_i2c_suspend, 742 .resume = wm8776_i2c_resume, 743 .id_table = wm8776_i2c_id, 744 }; 745 #endif 746 747 static int __init wm8776_modinit(void) 748 { 749 int ret; 750 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 751 ret = i2c_add_driver(&wm8776_i2c_driver); 752 if (ret != 0) { 753 printk(KERN_ERR "Failed to register WM8776 I2C driver: %d\n", 754 ret); 755 } 756 #endif 757 #if defined(CONFIG_SPI_MASTER) 758 ret = spi_register_driver(&wm8776_spi_driver); 759 if (ret != 0) { 760 printk(KERN_ERR "Failed to register WM8776 SPI driver: %d\n", 761 ret); 762 } 763 #endif 764 return 0; 765 } 766 module_init(wm8776_modinit); 767 768 static void __exit wm8776_exit(void) 769 { 770 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 771 i2c_del_driver(&wm8776_i2c_driver); 772 #endif 773 #if defined(CONFIG_SPI_MASTER) 774 spi_unregister_driver(&wm8776_spi_driver); 775 #endif 776 } 777 module_exit(wm8776_exit); 778 779 MODULE_DESCRIPTION("ASoC WM8776 driver"); 780 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 781 MODULE_LICENSE("GPL"); 782