aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8510.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8510.c')
-rw-r--r--sound/soc/codecs/wm8510.c290
1 files changed, 98 insertions, 192 deletions
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 0f7bcb61071a..dbfa05d2cb92 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -31,8 +31,6 @@
31 31
32#define WM8510_VERSION "0.6" 32#define WM8510_VERSION "0.6"
33 33
34struct snd_soc_codec_device soc_codec_dev_wm8510;
35
36/* 34/*
37 * wm8510 register cache 35 * wm8510 register cache
38 * We can't read the WM8510 register space when we are 36 * We can't read the WM8510 register space when we are
@@ -61,6 +59,12 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
61 59
62#define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0) 60#define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0)
63 61
62/* codec private data */
63struct wm8510_priv {
64 enum snd_soc_control_type control_type;
65 void *control_data;
66};
67
64static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; 68static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" };
65static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; 69static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
66static const char *wm8510_alc[] = { "ALC", "Limiter" }; 70static const char *wm8510_alc[] = { "ALC", "Limiter" };
@@ -403,8 +407,7 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
403 struct snd_soc_dai *dai) 407 struct snd_soc_dai *dai)
404{ 408{
405 struct snd_soc_pcm_runtime *rtd = substream->private_data; 409 struct snd_soc_pcm_runtime *rtd = substream->private_data;
406 struct snd_soc_device *socdev = rtd->socdev; 410 struct snd_soc_codec *codec = rtd->codec;
407 struct snd_soc_codec *codec = socdev->card->codec;
408 u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f; 411 u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f;
409 u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1; 412 u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1;
410 413
@@ -514,8 +517,8 @@ static struct snd_soc_dai_ops wm8510_dai_ops = {
514 .set_pll = wm8510_set_dai_pll, 517 .set_pll = wm8510_set_dai_pll,
515}; 518};
516 519
517struct snd_soc_dai wm8510_dai = { 520static struct snd_soc_dai_driver wm8510_dai = {
518 .name = "WM8510 HiFi", 521 .name = "wm8510-hifi",
519 .playback = { 522 .playback = {
520 .stream_name = "Playback", 523 .stream_name = "Playback",
521 .channels_min = 2, 524 .channels_min = 2,
@@ -531,21 +534,15 @@ struct snd_soc_dai wm8510_dai = {
531 .ops = &wm8510_dai_ops, 534 .ops = &wm8510_dai_ops,
532 .symmetric_rates = 1, 535 .symmetric_rates = 1,
533}; 536};
534EXPORT_SYMBOL_GPL(wm8510_dai);
535 537
536static int wm8510_suspend(struct platform_device *pdev, pm_message_t state) 538static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state)
537{ 539{
538 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
539 struct snd_soc_codec *codec = socdev->card->codec;
540
541 wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); 540 wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
542 return 0; 541 return 0;
543} 542}
544 543
545static int wm8510_resume(struct platform_device *pdev) 544static int wm8510_resume(struct snd_soc_codec *codec)
546{ 545{
547 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
548 struct snd_soc_codec *codec = socdev->card->codec;
549 int i; 546 int i;
550 u8 data[2]; 547 u8 data[2];
551 u16 *cache = codec->reg_cache; 548 u16 *cache = codec->reg_cache;
@@ -561,43 +558,22 @@ static int wm8510_resume(struct platform_device *pdev)
561 return 0; 558 return 0;
562} 559}
563 560
564/* 561static int wm8510_probe(struct snd_soc_codec *codec)
565 * initialise the WM8510 driver
566 * register the mixer and dsp interfaces with the kernel
567 */
568static int wm8510_init(struct snd_soc_device *socdev,
569 enum snd_soc_control_type control)
570{ 562{
571 struct snd_soc_codec *codec = socdev->card->codec; 563 struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec);
572 int ret = 0; 564 int ret;
573
574 codec->name = "WM8510";
575 codec->owner = THIS_MODULE;
576 codec->set_bias_level = wm8510_set_bias_level;
577 codec->dai = &wm8510_dai;
578 codec->num_dai = 1;
579 codec->reg_cache_size = ARRAY_SIZE(wm8510_reg);
580 codec->reg_cache = kmemdup(wm8510_reg, sizeof(wm8510_reg), GFP_KERNEL);
581 565
582 if (codec->reg_cache == NULL) 566 pr_info("WM8510 Audio Codec %s", WM8510_VERSION);
583 return -ENOMEM;
584 567
585 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); 568 codec->control_data = wm8510->control_data;
569 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8510->control_type);
586 if (ret < 0) { 570 if (ret < 0) {
587 printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", 571 printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret);
588 ret); 572 return ret;
589 goto err;
590 } 573 }
591 574
592 wm8510_reset(codec); 575 wm8510_reset(codec);
593 576
594 /* register pcms */
595 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
596 if (ret < 0) {
597 printk(KERN_ERR "wm8510: failed to create pcms\n");
598 goto err;
599 }
600
601 /* power on device */ 577 /* power on device */
602 codec->bias_level = SND_SOC_BIAS_OFF; 578 codec->bias_level = SND_SOC_BIAS_OFF;
603 wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 579 wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -606,119 +582,53 @@ static int wm8510_init(struct snd_soc_device *socdev,
606 wm8510_add_widgets(codec); 582 wm8510_add_widgets(codec);
607 583
608 return ret; 584 return ret;
609
610err:
611 kfree(codec->reg_cache);
612 return ret;
613} 585}
614 586
615static struct snd_soc_device *wm8510_socdev; 587/* power down chip */
616 588static int wm8510_remove(struct snd_soc_codec *codec)
617#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
618
619/*
620 * WM8510 2 wire address is 0x1a
621 */
622
623static int wm8510_i2c_probe(struct i2c_client *i2c,
624 const struct i2c_device_id *id)
625{ 589{
626 struct snd_soc_device *socdev = wm8510_socdev; 590 struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec);
627 struct snd_soc_codec *codec = socdev->card->codec;
628 int ret;
629
630 i2c_set_clientdata(i2c, codec);
631 codec->control_data = i2c;
632
633 ret = wm8510_init(socdev, SND_SOC_I2C);
634 if (ret < 0)
635 pr_err("failed to initialise WM8510\n");
636
637 return ret;
638}
639 591
640static int wm8510_i2c_remove(struct i2c_client *client) 592 wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
641{ 593 kfree(wm8510);
642 struct snd_soc_codec *codec = i2c_get_clientdata(client);
643 kfree(codec->reg_cache);
644 return 0; 594 return 0;
645} 595}
646 596
647static const struct i2c_device_id wm8510_i2c_id[] = { 597static struct snd_soc_codec_driver soc_codec_dev_wm8510 = {
648 { "wm8510", 0 }, 598 .probe = wm8510_probe,
649 { } 599 .remove = wm8510_remove,
650}; 600 .suspend = wm8510_suspend,
651MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id); 601 .resume = wm8510_resume,
652 602 .set_bias_level = wm8510_set_bias_level,
653static struct i2c_driver wm8510_i2c_driver = { 603 .reg_cache_size = ARRAY_SIZE(wm8510_reg),
654 .driver = { 604 .reg_word_size = sizeof(u16),
655 .name = "WM8510 I2C Codec", 605 .reg_cache_default =wm8510_reg,
656 .owner = THIS_MODULE,
657 },
658 .probe = wm8510_i2c_probe,
659 .remove = wm8510_i2c_remove,
660 .id_table = wm8510_i2c_id,
661}; 606};
662 607
663static int wm8510_add_i2c_device(struct platform_device *pdev,
664 const struct wm8510_setup_data *setup)
665{
666 struct i2c_board_info info;
667 struct i2c_adapter *adapter;
668 struct i2c_client *client;
669 int ret;
670
671 ret = i2c_add_driver(&wm8510_i2c_driver);
672 if (ret != 0) {
673 dev_err(&pdev->dev, "can't add i2c driver\n");
674 return ret;
675 }
676
677 memset(&info, 0, sizeof(struct i2c_board_info));
678 info.addr = setup->i2c_address;
679 strlcpy(info.type, "wm8510", I2C_NAME_SIZE);
680
681 adapter = i2c_get_adapter(setup->i2c_bus);
682 if (!adapter) {
683 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
684 setup->i2c_bus);
685 goto err_driver;
686 }
687
688 client = i2c_new_device(adapter, &info);
689 i2c_put_adapter(adapter);
690 if (!client) {
691 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
692 (unsigned int)info.addr);
693 goto err_driver;
694 }
695
696 return 0;
697
698err_driver:
699 i2c_del_driver(&wm8510_i2c_driver);
700 return -ENODEV;
701}
702#endif
703
704#if defined(CONFIG_SPI_MASTER) 608#if defined(CONFIG_SPI_MASTER)
705static int __devinit wm8510_spi_probe(struct spi_device *spi) 609static int __devinit wm8510_spi_probe(struct spi_device *spi)
706{ 610{
707 struct snd_soc_device *socdev = wm8510_socdev; 611 struct wm8510_priv *wm8510;
708 struct snd_soc_codec *codec = socdev->card->codec;
709 int ret; 612 int ret;
710 613
711 codec->control_data = spi; 614 wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL);
615 if (wm8510 == NULL)
616 return -ENOMEM;
617
618 wm8510->control_data = spi;
619 wm8510->control_type = SND_SOC_SPI;
620 spi_set_drvdata(spi, wm8510);
712 621
713 ret = wm8510_init(socdev, SND_SOC_SPI); 622 ret = snd_soc_register_codec(&spi->dev,
623 &soc_codec_dev_wm8510, &wm8510_dai, 1);
714 if (ret < 0) 624 if (ret < 0)
715 dev_err(&spi->dev, "failed to initialise WM8510\n"); 625 kfree(wm8510);
716
717 return ret; 626 return ret;
718} 627}
719 628
720static int __devexit wm8510_spi_remove(struct spi_device *spi) 629static int __devexit wm8510_spi_remove(struct spi_device *spi)
721{ 630{
631 snd_soc_unregister_codec(&spi->dev);
722 return 0; 632 return 0;
723} 633}
724 634
@@ -733,84 +643,80 @@ static struct spi_driver wm8510_spi_driver = {
733}; 643};
734#endif /* CONFIG_SPI_MASTER */ 644#endif /* CONFIG_SPI_MASTER */
735 645
736static int wm8510_probe(struct platform_device *pdev) 646#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
647static __devinit int wm8510_i2c_probe(struct i2c_client *i2c,
648 const struct i2c_device_id *id)
737{ 649{
738 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 650 struct wm8510_priv *wm8510;
739 struct wm8510_setup_data *setup; 651 int ret;
740 struct snd_soc_codec *codec;
741 int ret = 0;
742
743 pr_info("WM8510 Audio Codec %s", WM8510_VERSION);
744 652
745 setup = socdev->codec_data; 653 wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL);
746 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 654 if (wm8510 == NULL)
747 if (codec == NULL)
748 return -ENOMEM; 655 return -ENOMEM;
749 656
750 socdev->card->codec = codec; 657 i2c_set_clientdata(i2c, wm8510);
751 mutex_init(&codec->mutex); 658 wm8510->control_data = i2c;
752 INIT_LIST_HEAD(&codec->dapm_widgets); 659 wm8510->control_type = SND_SOC_I2C;
753 INIT_LIST_HEAD(&codec->dapm_paths);
754 660
755 wm8510_socdev = socdev; 661 ret = snd_soc_register_codec(&i2c->dev,
756#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 662 &soc_codec_dev_wm8510, &wm8510_dai, 1);
757 if (setup->i2c_address) { 663 if (ret < 0)
758 ret = wm8510_add_i2c_device(pdev, setup); 664 kfree(wm8510);
759 }
760#endif
761#if defined(CONFIG_SPI_MASTER)
762 if (setup->spi) {
763 ret = spi_register_driver(&wm8510_spi_driver);
764 if (ret != 0)
765 printk(KERN_ERR "can't add spi driver");
766 }
767#endif
768
769 if (ret != 0)
770 kfree(codec);
771 return ret; 665 return ret;
772} 666}
773 667
774/* power down chip */ 668static __devexit int wm8510_i2c_remove(struct i2c_client *client)
775static int wm8510_remove(struct platform_device *pdev)
776{ 669{
777 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 670 snd_soc_unregister_codec(&client->dev);
778 struct snd_soc_codec *codec = socdev->card->codec;
779
780 if (codec->control_data)
781 wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
782
783 snd_soc_free_pcms(socdev);
784 snd_soc_dapm_free(socdev);
785#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
786 i2c_unregister_device(codec->control_data);
787 i2c_del_driver(&wm8510_i2c_driver);
788#endif
789#if defined(CONFIG_SPI_MASTER)
790 spi_unregister_driver(&wm8510_spi_driver);
791#endif
792 kfree(codec);
793
794 return 0; 671 return 0;
795} 672}
796 673
797struct snd_soc_codec_device soc_codec_dev_wm8510 = { 674static const struct i2c_device_id wm8510_i2c_id[] = {
798 .probe = wm8510_probe, 675 { "wm8510", 0 },
799 .remove = wm8510_remove, 676 { }
800 .suspend = wm8510_suspend, 677};
801 .resume = wm8510_resume, 678MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id);
679
680static struct i2c_driver wm8510_i2c_driver = {
681 .driver = {
682 .name = "wm8510-codec",
683 .owner = THIS_MODULE,
684 },
685 .probe = wm8510_i2c_probe,
686 .remove = __devexit_p(wm8510_i2c_remove),
687 .id_table = wm8510_i2c_id,
802}; 688};
803EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510); 689#endif
804 690
805static int __init wm8510_modinit(void) 691static int __init wm8510_modinit(void)
806{ 692{
807 return snd_soc_register_dai(&wm8510_dai); 693 int ret = 0;
694#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
695 ret = i2c_add_driver(&wm8510_i2c_driver);
696 if (ret != 0) {
697 printk(KERN_ERR "Failed to register WM8510 I2C driver: %d\n",
698 ret);
699 }
700#endif
701#if defined(CONFIG_SPI_MASTER)
702 ret = spi_register_driver(&wm8510_spi_driver);
703 if (ret != 0) {
704 printk(KERN_ERR "Failed to register WM8510 SPI driver: %d\n",
705 ret);
706 }
707#endif
708 return ret;
808} 709}
809module_init(wm8510_modinit); 710module_init(wm8510_modinit);
810 711
811static void __exit wm8510_exit(void) 712static void __exit wm8510_exit(void)
812{ 713{
813 snd_soc_unregister_dai(&wm8510_dai); 714#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
715 i2c_del_driver(&wm8510_i2c_driver);
716#endif
717#if defined(CONFIG_SPI_MASTER)
718 spi_unregister_driver(&wm8510_spi_driver);
719#endif
814} 720}
815module_exit(wm8510_exit); 721module_exit(wm8510_exit);
816 722