diff options
Diffstat (limited to 'sound/soc/codecs/wm8731.c')
-rw-r--r-- | sound/soc/codecs/wm8731.c | 432 |
1 files changed, 198 insertions, 234 deletions
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index c444b9f2701e..e043e3f60008 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -29,15 +29,20 @@ | |||
29 | 29 | ||
30 | #include "wm8731.h" | 30 | #include "wm8731.h" |
31 | 31 | ||
32 | #define WM8731_VERSION "0.13" | 32 | static struct snd_soc_codec *wm8731_codec; |
33 | |||
34 | struct snd_soc_codec_device soc_codec_dev_wm8731; | 33 | struct snd_soc_codec_device soc_codec_dev_wm8731; |
35 | 34 | ||
36 | /* codec private data */ | 35 | /* codec private data */ |
37 | struct wm8731_priv { | 36 | struct wm8731_priv { |
37 | struct snd_soc_codec codec; | ||
38 | u16 reg_cache[WM8731_CACHEREGNUM]; | ||
38 | unsigned int sysclk; | 39 | unsigned int sysclk; |
39 | }; | 40 | }; |
40 | 41 | ||
42 | #ifdef CONFIG_SPI_MASTER | ||
43 | static int wm8731_spi_write(struct spi_device *spi, const char *data, int len); | ||
44 | #endif | ||
45 | |||
41 | /* | 46 | /* |
42 | * wm8731 register cache | 47 | * wm8731 register cache |
43 | * We can't read the WM8731 register space when we are | 48 | * We can't read the WM8731 register space when we are |
@@ -129,22 +134,6 @@ SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0), | |||
129 | SOC_ENUM("Playback De-emphasis", wm8731_enum[1]), | 134 | SOC_ENUM("Playback De-emphasis", wm8731_enum[1]), |
130 | }; | 135 | }; |
131 | 136 | ||
132 | /* add non dapm controls */ | ||
133 | static int wm8731_add_controls(struct snd_soc_codec *codec) | ||
134 | { | ||
135 | int err, i; | ||
136 | |||
137 | for (i = 0; i < ARRAY_SIZE(wm8731_snd_controls); i++) { | ||
138 | err = snd_ctl_add(codec->card, | ||
139 | snd_soc_cnew(&wm8731_snd_controls[i], | ||
140 | codec, NULL)); | ||
141 | if (err < 0) | ||
142 | return err; | ||
143 | } | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | /* Output Mixer */ | 137 | /* Output Mixer */ |
149 | static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = { | 138 | static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = { |
150 | SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0), | 139 | SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0), |
@@ -269,7 +258,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, | |||
269 | { | 258 | { |
270 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 259 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
271 | struct snd_soc_device *socdev = rtd->socdev; | 260 | struct snd_soc_device *socdev = rtd->socdev; |
272 | struct snd_soc_codec *codec = socdev->codec; | 261 | struct snd_soc_codec *codec = socdev->card->codec; |
273 | struct wm8731_priv *wm8731 = codec->private_data; | 262 | struct wm8731_priv *wm8731 = codec->private_data; |
274 | u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3; | 263 | u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3; |
275 | int i = get_coeff(wm8731->sysclk, params_rate(params)); | 264 | int i = get_coeff(wm8731->sysclk, params_rate(params)); |
@@ -299,7 +288,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, | |||
299 | { | 288 | { |
300 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 289 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
301 | struct snd_soc_device *socdev = rtd->socdev; | 290 | struct snd_soc_device *socdev = rtd->socdev; |
302 | struct snd_soc_codec *codec = socdev->codec; | 291 | struct snd_soc_codec *codec = socdev->card->codec; |
303 | 292 | ||
304 | /* set active */ | 293 | /* set active */ |
305 | wm8731_write(codec, WM8731_ACTIVE, 0x0001); | 294 | wm8731_write(codec, WM8731_ACTIVE, 0x0001); |
@@ -312,7 +301,7 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream, | |||
312 | { | 301 | { |
313 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 302 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
314 | struct snd_soc_device *socdev = rtd->socdev; | 303 | struct snd_soc_device *socdev = rtd->socdev; |
315 | struct snd_soc_codec *codec = socdev->codec; | 304 | struct snd_soc_codec *codec = socdev->card->codec; |
316 | 305 | ||
317 | /* deactivate */ | 306 | /* deactivate */ |
318 | if (!codec->active) { | 307 | if (!codec->active) { |
@@ -414,21 +403,19 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
414 | static int wm8731_set_bias_level(struct snd_soc_codec *codec, | 403 | static int wm8731_set_bias_level(struct snd_soc_codec *codec, |
415 | enum snd_soc_bias_level level) | 404 | enum snd_soc_bias_level level) |
416 | { | 405 | { |
417 | u16 reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f; | 406 | u16 reg; |
418 | 407 | ||
419 | switch (level) { | 408 | switch (level) { |
420 | case SND_SOC_BIAS_ON: | 409 | case SND_SOC_BIAS_ON: |
421 | /* vref/mid, osc on, dac unmute */ | ||
422 | wm8731_write(codec, WM8731_PWR, reg); | ||
423 | break; | 410 | break; |
424 | case SND_SOC_BIAS_PREPARE: | 411 | case SND_SOC_BIAS_PREPARE: |
425 | break; | 412 | break; |
426 | case SND_SOC_BIAS_STANDBY: | 413 | case SND_SOC_BIAS_STANDBY: |
427 | /* everything off except vref/vmid, */ | 414 | /* Clear PWROFF, gate CLKOUT, everything else as-is */ |
415 | reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f; | ||
428 | wm8731_write(codec, WM8731_PWR, reg | 0x0040); | 416 | wm8731_write(codec, WM8731_PWR, reg | 0x0040); |
429 | break; | 417 | break; |
430 | case SND_SOC_BIAS_OFF: | 418 | case SND_SOC_BIAS_OFF: |
431 | /* everything off, dac mute, inactive */ | ||
432 | wm8731_write(codec, WM8731_ACTIVE, 0x0); | 419 | wm8731_write(codec, WM8731_ACTIVE, 0x0); |
433 | wm8731_write(codec, WM8731_PWR, 0xffff); | 420 | wm8731_write(codec, WM8731_PWR, 0xffff); |
434 | break; | 421 | break; |
@@ -446,6 +433,15 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, | |||
446 | #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 433 | #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
447 | SNDRV_PCM_FMTBIT_S24_LE) | 434 | SNDRV_PCM_FMTBIT_S24_LE) |
448 | 435 | ||
436 | static struct snd_soc_dai_ops wm8731_dai_ops = { | ||
437 | .prepare = wm8731_pcm_prepare, | ||
438 | .hw_params = wm8731_hw_params, | ||
439 | .shutdown = wm8731_shutdown, | ||
440 | .digital_mute = wm8731_mute, | ||
441 | .set_sysclk = wm8731_set_dai_sysclk, | ||
442 | .set_fmt = wm8731_set_dai_fmt, | ||
443 | }; | ||
444 | |||
449 | struct snd_soc_dai wm8731_dai = { | 445 | struct snd_soc_dai wm8731_dai = { |
450 | .name = "WM8731", | 446 | .name = "WM8731", |
451 | .playback = { | 447 | .playback = { |
@@ -460,21 +456,14 @@ struct snd_soc_dai wm8731_dai = { | |||
460 | .channels_max = 2, | 456 | .channels_max = 2, |
461 | .rates = WM8731_RATES, | 457 | .rates = WM8731_RATES, |
462 | .formats = WM8731_FORMATS,}, | 458 | .formats = WM8731_FORMATS,}, |
463 | .ops = { | 459 | .ops = &wm8731_dai_ops, |
464 | .prepare = wm8731_pcm_prepare, | ||
465 | .hw_params = wm8731_hw_params, | ||
466 | .shutdown = wm8731_shutdown, | ||
467 | .digital_mute = wm8731_mute, | ||
468 | .set_sysclk = wm8731_set_dai_sysclk, | ||
469 | .set_fmt = wm8731_set_dai_fmt, | ||
470 | } | ||
471 | }; | 460 | }; |
472 | EXPORT_SYMBOL_GPL(wm8731_dai); | 461 | EXPORT_SYMBOL_GPL(wm8731_dai); |
473 | 462 | ||
474 | static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) | 463 | static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) |
475 | { | 464 | { |
476 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 465 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
477 | struct snd_soc_codec *codec = socdev->codec; | 466 | struct snd_soc_codec *codec = socdev->card->codec; |
478 | 467 | ||
479 | wm8731_write(codec, WM8731_ACTIVE, 0x0); | 468 | wm8731_write(codec, WM8731_ACTIVE, 0x0); |
480 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); | 469 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); |
@@ -484,7 +473,7 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) | |||
484 | static int wm8731_resume(struct platform_device *pdev) | 473 | static int wm8731_resume(struct platform_device *pdev) |
485 | { | 474 | { |
486 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 475 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
487 | struct snd_soc_codec *codec = socdev->codec; | 476 | struct snd_soc_codec *codec = socdev->card->codec; |
488 | int i; | 477 | int i; |
489 | u8 data[2]; | 478 | u8 data[2]; |
490 | u16 *cache = codec->reg_cache; | 479 | u16 *cache = codec->reg_cache; |
@@ -500,54 +489,33 @@ static int wm8731_resume(struct platform_device *pdev) | |||
500 | return 0; | 489 | return 0; |
501 | } | 490 | } |
502 | 491 | ||
503 | /* | 492 | static int wm8731_probe(struct platform_device *pdev) |
504 | * initialise the WM8731 driver | ||
505 | * register the mixer and dsp interfaces with the kernel | ||
506 | */ | ||
507 | static int wm8731_init(struct snd_soc_device *socdev) | ||
508 | { | 493 | { |
509 | struct snd_soc_codec *codec = socdev->codec; | 494 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
510 | int reg, ret = 0; | 495 | struct snd_soc_codec *codec; |
496 | int ret = 0; | ||
511 | 497 | ||
512 | codec->name = "WM8731"; | 498 | if (wm8731_codec == NULL) { |
513 | codec->owner = THIS_MODULE; | 499 | dev_err(&pdev->dev, "Codec device not registered\n"); |
514 | codec->read = wm8731_read_reg_cache; | 500 | return -ENODEV; |
515 | codec->write = wm8731_write; | 501 | } |
516 | codec->set_bias_level = wm8731_set_bias_level; | ||
517 | codec->dai = &wm8731_dai; | ||
518 | codec->num_dai = 1; | ||
519 | codec->reg_cache_size = ARRAY_SIZE(wm8731_reg); | ||
520 | codec->reg_cache = kmemdup(wm8731_reg, sizeof(wm8731_reg), GFP_KERNEL); | ||
521 | if (codec->reg_cache == NULL) | ||
522 | return -ENOMEM; | ||
523 | 502 | ||
524 | wm8731_reset(codec); | 503 | socdev->card->codec = wm8731_codec; |
504 | codec = wm8731_codec; | ||
525 | 505 | ||
526 | /* register pcms */ | 506 | /* register pcms */ |
527 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 507 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
528 | if (ret < 0) { | 508 | if (ret < 0) { |
529 | printk(KERN_ERR "wm8731: failed to create pcms\n"); | 509 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); |
530 | goto pcm_err; | 510 | goto pcm_err; |
531 | } | 511 | } |
532 | 512 | ||
533 | /* power on device */ | 513 | snd_soc_add_controls(codec, wm8731_snd_controls, |
534 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 514 | ARRAY_SIZE(wm8731_snd_controls)); |
535 | |||
536 | /* set the update bits */ | ||
537 | reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V); | ||
538 | wm8731_write(codec, WM8731_LOUT1V, reg & ~0x0100); | ||
539 | reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V); | ||
540 | wm8731_write(codec, WM8731_ROUT1V, reg & ~0x0100); | ||
541 | reg = wm8731_read_reg_cache(codec, WM8731_LINVOL); | ||
542 | wm8731_write(codec, WM8731_LINVOL, reg & ~0x0100); | ||
543 | reg = wm8731_read_reg_cache(codec, WM8731_RINVOL); | ||
544 | wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100); | ||
545 | |||
546 | wm8731_add_controls(codec); | ||
547 | wm8731_add_widgets(codec); | 515 | wm8731_add_widgets(codec); |
548 | ret = snd_soc_init_card(socdev); | 516 | ret = snd_soc_init_card(socdev); |
549 | if (ret < 0) { | 517 | if (ret < 0) { |
550 | printk(KERN_ERR "wm8731: failed to register card\n"); | 518 | dev_err(codec->dev, "failed to register card: %d\n", ret); |
551 | goto card_err; | 519 | goto card_err; |
552 | } | 520 | } |
553 | 521 | ||
@@ -557,133 +525,109 @@ card_err: | |||
557 | snd_soc_free_pcms(socdev); | 525 | snd_soc_free_pcms(socdev); |
558 | snd_soc_dapm_free(socdev); | 526 | snd_soc_dapm_free(socdev); |
559 | pcm_err: | 527 | pcm_err: |
560 | kfree(codec->reg_cache); | ||
561 | return ret; | 528 | return ret; |
562 | } | 529 | } |
563 | 530 | ||
564 | static struct snd_soc_device *wm8731_socdev; | 531 | /* power down chip */ |
565 | 532 | static int wm8731_remove(struct platform_device *pdev) | |
566 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
567 | |||
568 | /* | ||
569 | * WM8731 2 wire address is determined by GPIO5 | ||
570 | * state during powerup. | ||
571 | * low = 0x1a | ||
572 | * high = 0x1b | ||
573 | */ | ||
574 | |||
575 | static int wm8731_i2c_probe(struct i2c_client *i2c, | ||
576 | const struct i2c_device_id *id) | ||
577 | { | 533 | { |
578 | struct snd_soc_device *socdev = wm8731_socdev; | 534 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
579 | struct snd_soc_codec *codec = socdev->codec; | ||
580 | int ret; | ||
581 | |||
582 | i2c_set_clientdata(i2c, codec); | ||
583 | codec->control_data = i2c; | ||
584 | |||
585 | ret = wm8731_init(socdev); | ||
586 | if (ret < 0) | ||
587 | pr_err("failed to initialise WM8731\n"); | ||
588 | 535 | ||
589 | return ret; | 536 | snd_soc_free_pcms(socdev); |
590 | } | 537 | snd_soc_dapm_free(socdev); |
591 | 538 | ||
592 | static int wm8731_i2c_remove(struct i2c_client *client) | ||
593 | { | ||
594 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | ||
595 | kfree(codec->reg_cache); | ||
596 | return 0; | 539 | return 0; |
597 | } | 540 | } |
598 | 541 | ||
599 | static const struct i2c_device_id wm8731_i2c_id[] = { | 542 | struct snd_soc_codec_device soc_codec_dev_wm8731 = { |
600 | { "wm8731", 0 }, | 543 | .probe = wm8731_probe, |
601 | { } | 544 | .remove = wm8731_remove, |
602 | }; | 545 | .suspend = wm8731_suspend, |
603 | MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); | 546 | .resume = wm8731_resume, |
604 | |||
605 | static struct i2c_driver wm8731_i2c_driver = { | ||
606 | .driver = { | ||
607 | .name = "WM8731 I2C Codec", | ||
608 | .owner = THIS_MODULE, | ||
609 | }, | ||
610 | .probe = wm8731_i2c_probe, | ||
611 | .remove = wm8731_i2c_remove, | ||
612 | .id_table = wm8731_i2c_id, | ||
613 | }; | 547 | }; |
548 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); | ||
614 | 549 | ||
615 | static int wm8731_add_i2c_device(struct platform_device *pdev, | 550 | static int wm8731_register(struct wm8731_priv *wm8731) |
616 | const struct wm8731_setup_data *setup) | ||
617 | { | 551 | { |
618 | struct i2c_board_info info; | ||
619 | struct i2c_adapter *adapter; | ||
620 | struct i2c_client *client; | ||
621 | int ret; | 552 | int ret; |
553 | struct snd_soc_codec *codec = &wm8731->codec; | ||
554 | u16 reg; | ||
622 | 555 | ||
623 | ret = i2c_add_driver(&wm8731_i2c_driver); | 556 | if (wm8731_codec) { |
624 | if (ret != 0) { | 557 | dev_err(codec->dev, "Another WM8731 is registered\n"); |
625 | dev_err(&pdev->dev, "can't add i2c driver\n"); | 558 | return -EINVAL; |
626 | return ret; | ||
627 | } | 559 | } |
628 | 560 | ||
629 | memset(&info, 0, sizeof(struct i2c_board_info)); | 561 | mutex_init(&codec->mutex); |
630 | info.addr = setup->i2c_address; | 562 | INIT_LIST_HEAD(&codec->dapm_widgets); |
631 | strlcpy(info.type, "wm8731", I2C_NAME_SIZE); | 563 | INIT_LIST_HEAD(&codec->dapm_paths); |
632 | 564 | ||
633 | adapter = i2c_get_adapter(setup->i2c_bus); | 565 | codec->private_data = wm8731; |
634 | if (!adapter) { | 566 | codec->name = "WM8731"; |
635 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | 567 | codec->owner = THIS_MODULE; |
636 | setup->i2c_bus); | 568 | codec->read = wm8731_read_reg_cache; |
637 | goto err_driver; | 569 | codec->write = wm8731_write; |
638 | } | 570 | codec->bias_level = SND_SOC_BIAS_OFF; |
571 | codec->set_bias_level = wm8731_set_bias_level; | ||
572 | codec->dai = &wm8731_dai; | ||
573 | codec->num_dai = 1; | ||
574 | codec->reg_cache_size = WM8731_CACHEREGNUM; | ||
575 | codec->reg_cache = &wm8731->reg_cache; | ||
639 | 576 | ||
640 | client = i2c_new_device(adapter, &info); | 577 | memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg)); |
641 | i2c_put_adapter(adapter); | 578 | |
642 | if (!client) { | 579 | ret = wm8731_reset(codec); |
643 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | 580 | if (ret < 0) { |
644 | (unsigned int)info.addr); | 581 | dev_err(codec->dev, "Failed to issue reset\n"); |
645 | goto err_driver; | 582 | return ret; |
646 | } | 583 | } |
647 | 584 | ||
648 | return 0; | 585 | wm8731_dai.dev = codec->dev; |
649 | 586 | ||
650 | err_driver: | 587 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
651 | i2c_del_driver(&wm8731_i2c_driver); | ||
652 | return -ENODEV; | ||
653 | } | ||
654 | #endif | ||
655 | 588 | ||
656 | #if defined(CONFIG_SPI_MASTER) | 589 | /* Latch the update bits */ |
657 | static int __devinit wm8731_spi_probe(struct spi_device *spi) | 590 | reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V); |
658 | { | 591 | wm8731_write(codec, WM8731_LOUT1V, reg & ~0x0100); |
659 | struct snd_soc_device *socdev = wm8731_socdev; | 592 | reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V); |
660 | struct snd_soc_codec *codec = socdev->codec; | 593 | wm8731_write(codec, WM8731_ROUT1V, reg & ~0x0100); |
661 | int ret; | 594 | reg = wm8731_read_reg_cache(codec, WM8731_LINVOL); |
595 | wm8731_write(codec, WM8731_LINVOL, reg & ~0x0100); | ||
596 | reg = wm8731_read_reg_cache(codec, WM8731_RINVOL); | ||
597 | wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100); | ||
662 | 598 | ||
663 | codec->control_data = spi; | 599 | /* Disable bypass path by default */ |
600 | reg = wm8731_read_reg_cache(codec, WM8731_APANA); | ||
601 | wm8731_write(codec, WM8731_APANA, reg & ~0x4); | ||
664 | 602 | ||
665 | ret = wm8731_init(socdev); | 603 | wm8731_codec = codec; |
666 | if (ret < 0) | ||
667 | dev_err(&spi->dev, "failed to initialise WM8731\n"); | ||
668 | 604 | ||
669 | return ret; | 605 | ret = snd_soc_register_codec(codec); |
670 | } | 606 | if (ret != 0) { |
607 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
608 | return ret; | ||
609 | } | ||
610 | |||
611 | ret = snd_soc_register_dai(&wm8731_dai); | ||
612 | if (ret != 0) { | ||
613 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
614 | snd_soc_unregister_codec(codec); | ||
615 | return ret; | ||
616 | } | ||
671 | 617 | ||
672 | static int __devexit wm8731_spi_remove(struct spi_device *spi) | ||
673 | { | ||
674 | return 0; | 618 | return 0; |
675 | } | 619 | } |
676 | 620 | ||
677 | static struct spi_driver wm8731_spi_driver = { | 621 | static void wm8731_unregister(struct wm8731_priv *wm8731) |
678 | .driver = { | 622 | { |
679 | .name = "wm8731", | 623 | wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); |
680 | .bus = &spi_bus_type, | 624 | snd_soc_unregister_dai(&wm8731_dai); |
681 | .owner = THIS_MODULE, | 625 | snd_soc_unregister_codec(&wm8731->codec); |
682 | }, | 626 | kfree(wm8731); |
683 | .probe = wm8731_spi_probe, | 627 | wm8731_codec = NULL; |
684 | .remove = __devexit_p(wm8731_spi_remove), | 628 | } |
685 | }; | ||
686 | 629 | ||
630 | #if defined(CONFIG_SPI_MASTER) | ||
687 | static int wm8731_spi_write(struct spi_device *spi, const char *data, int len) | 631 | static int wm8731_spi_write(struct spi_device *spi, const char *data, int len) |
688 | { | 632 | { |
689 | struct spi_transfer t; | 633 | struct spi_transfer t; |
@@ -707,101 +651,121 @@ static int wm8731_spi_write(struct spi_device *spi, const char *data, int len) | |||
707 | 651 | ||
708 | return len; | 652 | return len; |
709 | } | 653 | } |
710 | #endif /* CONFIG_SPI_MASTER */ | ||
711 | 654 | ||
712 | static int wm8731_probe(struct platform_device *pdev) | 655 | static int __devinit wm8731_spi_probe(struct spi_device *spi) |
713 | { | 656 | { |
714 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
715 | struct wm8731_setup_data *setup; | ||
716 | struct snd_soc_codec *codec; | 657 | struct snd_soc_codec *codec; |
717 | struct wm8731_priv *wm8731; | 658 | struct wm8731_priv *wm8731; |
718 | int ret = 0; | ||
719 | |||
720 | pr_info("WM8731 Audio Codec %s", WM8731_VERSION); | ||
721 | |||
722 | setup = socdev->codec_data; | ||
723 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
724 | if (codec == NULL) | ||
725 | return -ENOMEM; | ||
726 | 659 | ||
727 | wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); | 660 | wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); |
728 | if (wm8731 == NULL) { | 661 | if (wm8731 == NULL) |
729 | kfree(codec); | ||
730 | return -ENOMEM; | 662 | return -ENOMEM; |
731 | } | ||
732 | 663 | ||
733 | codec->private_data = wm8731; | 664 | codec = &wm8731->codec; |
734 | socdev->codec = codec; | 665 | codec->control_data = spi; |
735 | mutex_init(&codec->mutex); | 666 | codec->hw_write = (hw_write_t)wm8731_spi_write; |
736 | INIT_LIST_HEAD(&codec->dapm_widgets); | 667 | codec->dev = &spi->dev; |
737 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
738 | 668 | ||
739 | wm8731_socdev = socdev; | 669 | spi->dev.driver_data = wm8731; |
740 | ret = -ENODEV; | ||
741 | 670 | ||
742 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 671 | return wm8731_register(wm8731); |
743 | if (setup->i2c_address) { | ||
744 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
745 | ret = wm8731_add_i2c_device(pdev, setup); | ||
746 | } | ||
747 | #endif | ||
748 | #if defined(CONFIG_SPI_MASTER) | ||
749 | if (setup->spi) { | ||
750 | codec->hw_write = (hw_write_t)wm8731_spi_write; | ||
751 | ret = spi_register_driver(&wm8731_spi_driver); | ||
752 | if (ret != 0) | ||
753 | printk(KERN_ERR "can't add spi driver"); | ||
754 | } | ||
755 | #endif | ||
756 | |||
757 | if (ret != 0) { | ||
758 | kfree(codec->private_data); | ||
759 | kfree(codec); | ||
760 | } | ||
761 | return ret; | ||
762 | } | 672 | } |
763 | 673 | ||
764 | /* power down chip */ | 674 | static int __devexit wm8731_spi_remove(struct spi_device *spi) |
765 | static int wm8731_remove(struct platform_device *pdev) | ||
766 | { | 675 | { |
767 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 676 | struct wm8731_priv *wm8731 = spi->dev.driver_data; |
768 | struct snd_soc_codec *codec = socdev->codec; | ||
769 | 677 | ||
770 | if (codec->control_data) | 678 | wm8731_unregister(wm8731); |
771 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); | 679 | |
680 | return 0; | ||
681 | } | ||
682 | |||
683 | static struct spi_driver wm8731_spi_driver = { | ||
684 | .driver = { | ||
685 | .name = "wm8731", | ||
686 | .bus = &spi_bus_type, | ||
687 | .owner = THIS_MODULE, | ||
688 | }, | ||
689 | .probe = wm8731_spi_probe, | ||
690 | .remove = __devexit_p(wm8731_spi_remove), | ||
691 | }; | ||
692 | #endif /* CONFIG_SPI_MASTER */ | ||
772 | 693 | ||
773 | snd_soc_free_pcms(socdev); | ||
774 | snd_soc_dapm_free(socdev); | ||
775 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 694 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
776 | i2c_unregister_device(codec->control_data); | 695 | static __devinit int wm8731_i2c_probe(struct i2c_client *i2c, |
777 | i2c_del_driver(&wm8731_i2c_driver); | 696 | const struct i2c_device_id *id) |
778 | #endif | 697 | { |
779 | #if defined(CONFIG_SPI_MASTER) | 698 | struct wm8731_priv *wm8731; |
780 | spi_unregister_driver(&wm8731_spi_driver); | 699 | struct snd_soc_codec *codec; |
781 | #endif | 700 | |
782 | kfree(codec->private_data); | 701 | wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); |
783 | kfree(codec); | 702 | if (wm8731 == NULL) |
703 | return -ENOMEM; | ||
704 | |||
705 | codec = &wm8731->codec; | ||
706 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
784 | 707 | ||
708 | i2c_set_clientdata(i2c, wm8731); | ||
709 | codec->control_data = i2c; | ||
710 | |||
711 | codec->dev = &i2c->dev; | ||
712 | |||
713 | return wm8731_register(wm8731); | ||
714 | } | ||
715 | |||
716 | static __devexit int wm8731_i2c_remove(struct i2c_client *client) | ||
717 | { | ||
718 | struct wm8731_priv *wm8731 = i2c_get_clientdata(client); | ||
719 | wm8731_unregister(wm8731); | ||
785 | return 0; | 720 | return 0; |
786 | } | 721 | } |
787 | 722 | ||
788 | struct snd_soc_codec_device soc_codec_dev_wm8731 = { | 723 | static const struct i2c_device_id wm8731_i2c_id[] = { |
789 | .probe = wm8731_probe, | 724 | { "wm8731", 0 }, |
790 | .remove = wm8731_remove, | 725 | { } |
791 | .suspend = wm8731_suspend, | ||
792 | .resume = wm8731_resume, | ||
793 | }; | 726 | }; |
794 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); | 727 | MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); |
728 | |||
729 | static struct i2c_driver wm8731_i2c_driver = { | ||
730 | .driver = { | ||
731 | .name = "WM8731 I2C Codec", | ||
732 | .owner = THIS_MODULE, | ||
733 | }, | ||
734 | .probe = wm8731_i2c_probe, | ||
735 | .remove = __devexit_p(wm8731_i2c_remove), | ||
736 | .id_table = wm8731_i2c_id, | ||
737 | }; | ||
738 | #endif | ||
795 | 739 | ||
796 | static int __init wm8731_modinit(void) | 740 | static int __init wm8731_modinit(void) |
797 | { | 741 | { |
798 | return snd_soc_register_dai(&wm8731_dai); | 742 | int ret; |
743 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
744 | ret = i2c_add_driver(&wm8731_i2c_driver); | ||
745 | if (ret != 0) { | ||
746 | printk(KERN_ERR "Failed to register WM8731 I2C driver: %d\n", | ||
747 | ret); | ||
748 | } | ||
749 | #endif | ||
750 | #if defined(CONFIG_SPI_MASTER) | ||
751 | ret = spi_register_driver(&wm8731_spi_driver); | ||
752 | if (ret != 0) { | ||
753 | printk(KERN_ERR "Failed to register WM8731 SPI driver: %d\n", | ||
754 | ret); | ||
755 | } | ||
756 | #endif | ||
757 | return 0; | ||
799 | } | 758 | } |
800 | module_init(wm8731_modinit); | 759 | module_init(wm8731_modinit); |
801 | 760 | ||
802 | static void __exit wm8731_exit(void) | 761 | static void __exit wm8731_exit(void) |
803 | { | 762 | { |
804 | snd_soc_unregister_dai(&wm8731_dai); | 763 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
764 | i2c_del_driver(&wm8731_i2c_driver); | ||
765 | #endif | ||
766 | #if defined(CONFIG_SPI_MASTER) | ||
767 | spi_unregister_driver(&wm8731_spi_driver); | ||
768 | #endif | ||
805 | } | 769 | } |
806 | module_exit(wm8731_exit); | 770 | module_exit(wm8731_exit); |
807 | 771 | ||