diff options
Diffstat (limited to 'sound/soc/codecs/wm8731.c')
-rw-r--r-- | sound/soc/codecs/wm8731.c | 179 |
1 files changed, 122 insertions, 57 deletions
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 9402fcaf04fa..7f8a7e36b33e 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/spi/spi.h> | ||
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
@@ -28,7 +29,6 @@ | |||
28 | 29 | ||
29 | #include "wm8731.h" | 30 | #include "wm8731.h" |
30 | 31 | ||
31 | #define AUDIO_NAME "wm8731" | ||
32 | #define WM8731_VERSION "0.13" | 32 | #define WM8731_VERSION "0.13" |
33 | 33 | ||
34 | struct snd_soc_codec_device soc_codec_dev_wm8731; | 34 | struct snd_soc_codec_device soc_codec_dev_wm8731; |
@@ -570,88 +570,144 @@ static struct snd_soc_device *wm8731_socdev; | |||
570 | * low = 0x1a | 570 | * low = 0x1a |
571 | * high = 0x1b | 571 | * high = 0x1b |
572 | */ | 572 | */ |
573 | static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END }; | ||
574 | 573 | ||
575 | /* Magic definition of all other variables and things */ | 574 | static int wm8731_i2c_probe(struct i2c_client *i2c, |
576 | I2C_CLIENT_INSMOD; | 575 | const struct i2c_device_id *id) |
577 | |||
578 | static struct i2c_driver wm8731_i2c_driver; | ||
579 | static struct i2c_client client_template; | ||
580 | |||
581 | /* If the i2c layer weren't so broken, we could pass this kind of data | ||
582 | around */ | ||
583 | |||
584 | static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind) | ||
585 | { | 576 | { |
586 | struct snd_soc_device *socdev = wm8731_socdev; | 577 | struct snd_soc_device *socdev = wm8731_socdev; |
587 | struct wm8731_setup_data *setup = socdev->codec_data; | ||
588 | struct snd_soc_codec *codec = socdev->codec; | 578 | struct snd_soc_codec *codec = socdev->codec; |
589 | struct i2c_client *i2c; | ||
590 | int ret; | 579 | int ret; |
591 | 580 | ||
592 | if (addr != setup->i2c_address) | ||
593 | return -ENODEV; | ||
594 | |||
595 | client_template.adapter = adap; | ||
596 | client_template.addr = addr; | ||
597 | |||
598 | i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); | ||
599 | if (i2c == NULL) | ||
600 | return -ENOMEM; | ||
601 | |||
602 | i2c_set_clientdata(i2c, codec); | 581 | i2c_set_clientdata(i2c, codec); |
603 | codec->control_data = i2c; | 582 | codec->control_data = i2c; |
604 | 583 | ||
605 | ret = i2c_attach_client(i2c); | ||
606 | if (ret < 0) { | ||
607 | pr_err("failed to attach codec at addr %x\n", addr); | ||
608 | goto err; | ||
609 | } | ||
610 | |||
611 | ret = wm8731_init(socdev); | 584 | ret = wm8731_init(socdev); |
612 | if (ret < 0) { | 585 | if (ret < 0) |
613 | pr_err("failed to initialise WM8731\n"); | 586 | pr_err("failed to initialise WM8731\n"); |
614 | goto err; | ||
615 | } | ||
616 | return ret; | ||
617 | 587 | ||
618 | err: | ||
619 | kfree(i2c); | ||
620 | return ret; | 588 | return ret; |
621 | } | 589 | } |
622 | 590 | ||
623 | static int wm8731_i2c_detach(struct i2c_client *client) | 591 | static int wm8731_i2c_remove(struct i2c_client *client) |
624 | { | 592 | { |
625 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 593 | struct snd_soc_codec *codec = i2c_get_clientdata(client); |
626 | i2c_detach_client(client); | ||
627 | kfree(codec->reg_cache); | 594 | kfree(codec->reg_cache); |
628 | kfree(client); | ||
629 | return 0; | 595 | return 0; |
630 | } | 596 | } |
631 | 597 | ||
632 | static int wm8731_i2c_attach(struct i2c_adapter *adap) | 598 | static const struct i2c_device_id wm8731_i2c_id[] = { |
633 | { | 599 | { "wm8731", 0 }, |
634 | return i2c_probe(adap, &addr_data, wm8731_codec_probe); | 600 | { } |
635 | } | 601 | }; |
602 | MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); | ||
636 | 603 | ||
637 | /* corgi i2c codec control layer */ | ||
638 | static struct i2c_driver wm8731_i2c_driver = { | 604 | static struct i2c_driver wm8731_i2c_driver = { |
639 | .driver = { | 605 | .driver = { |
640 | .name = "WM8731 I2C Codec", | 606 | .name = "WM8731 I2C Codec", |
641 | .owner = THIS_MODULE, | 607 | .owner = THIS_MODULE, |
642 | }, | 608 | }, |
643 | .id = I2C_DRIVERID_WM8731, | 609 | .probe = wm8731_i2c_probe, |
644 | .attach_adapter = wm8731_i2c_attach, | 610 | .remove = wm8731_i2c_remove, |
645 | .detach_client = wm8731_i2c_detach, | 611 | .id_table = wm8731_i2c_id, |
646 | .command = NULL, | ||
647 | }; | 612 | }; |
648 | 613 | ||
649 | static struct i2c_client client_template = { | 614 | static int wm8731_add_i2c_device(struct platform_device *pdev, |
650 | .name = "WM8731", | 615 | const struct wm8731_setup_data *setup) |
651 | .driver = &wm8731_i2c_driver, | 616 | { |
652 | }; | 617 | struct i2c_board_info info; |
618 | struct i2c_adapter *adapter; | ||
619 | struct i2c_client *client; | ||
620 | int ret; | ||
621 | |||
622 | ret = i2c_add_driver(&wm8731_i2c_driver); | ||
623 | if (ret != 0) { | ||
624 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
625 | return ret; | ||
626 | } | ||
627 | |||
628 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
629 | info.addr = setup->i2c_address; | ||
630 | strlcpy(info.type, "wm8731", I2C_NAME_SIZE); | ||
631 | |||
632 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
633 | if (!adapter) { | ||
634 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
635 | setup->i2c_bus); | ||
636 | goto err_driver; | ||
637 | } | ||
638 | |||
639 | client = i2c_new_device(adapter, &info); | ||
640 | i2c_put_adapter(adapter); | ||
641 | if (!client) { | ||
642 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
643 | (unsigned int)info.addr); | ||
644 | goto err_driver; | ||
645 | } | ||
646 | |||
647 | return 0; | ||
648 | |||
649 | err_driver: | ||
650 | i2c_del_driver(&wm8731_i2c_driver); | ||
651 | return -ENODEV; | ||
652 | } | ||
653 | #endif | 653 | #endif |
654 | 654 | ||
655 | #if defined(CONFIG_SPI_MASTER) | ||
656 | static int __devinit wm8731_spi_probe(struct spi_device *spi) | ||
657 | { | ||
658 | struct snd_soc_device *socdev = wm8731_socdev; | ||
659 | struct snd_soc_codec *codec = socdev->codec; | ||
660 | int ret; | ||
661 | |||
662 | codec->control_data = spi; | ||
663 | |||
664 | ret = wm8731_init(socdev); | ||
665 | if (ret < 0) | ||
666 | dev_err(&spi->dev, "failed to initialise WM8731\n"); | ||
667 | |||
668 | return ret; | ||
669 | } | ||
670 | |||
671 | static int __devexit wm8731_spi_remove(struct spi_device *spi) | ||
672 | { | ||
673 | return 0; | ||
674 | } | ||
675 | |||
676 | static struct spi_driver wm8731_spi_driver = { | ||
677 | .driver = { | ||
678 | .name = "wm8731", | ||
679 | .bus = &spi_bus_type, | ||
680 | .owner = THIS_MODULE, | ||
681 | }, | ||
682 | .probe = wm8731_spi_probe, | ||
683 | .remove = __devexit_p(wm8731_spi_remove), | ||
684 | }; | ||
685 | |||
686 | static int wm8731_spi_write(struct spi_device *spi, const char *data, int len) | ||
687 | { | ||
688 | struct spi_transfer t; | ||
689 | struct spi_message m; | ||
690 | u8 msg[2]; | ||
691 | |||
692 | if (len <= 0) | ||
693 | return 0; | ||
694 | |||
695 | msg[0] = data[0]; | ||
696 | msg[1] = data[1]; | ||
697 | |||
698 | spi_message_init(&m); | ||
699 | memset(&t, 0, (sizeof t)); | ||
700 | |||
701 | t.tx_buf = &msg[0]; | ||
702 | t.len = len; | ||
703 | |||
704 | spi_message_add_tail(&t, &m); | ||
705 | spi_sync(spi, &m); | ||
706 | |||
707 | return len; | ||
708 | } | ||
709 | #endif /* CONFIG_SPI_MASTER */ | ||
710 | |||
655 | static int wm8731_probe(struct platform_device *pdev) | 711 | static int wm8731_probe(struct platform_device *pdev) |
656 | { | 712 | { |
657 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 713 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
@@ -680,16 +736,21 @@ static int wm8731_probe(struct platform_device *pdev) | |||
680 | INIT_LIST_HEAD(&codec->dapm_paths); | 736 | INIT_LIST_HEAD(&codec->dapm_paths); |
681 | 737 | ||
682 | wm8731_socdev = socdev; | 738 | wm8731_socdev = socdev; |
739 | ret = -ENODEV; | ||
740 | |||
683 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 741 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
684 | if (setup->i2c_address) { | 742 | if (setup->i2c_address) { |
685 | normal_i2c[0] = setup->i2c_address; | ||
686 | codec->hw_write = (hw_write_t)i2c_master_send; | 743 | codec->hw_write = (hw_write_t)i2c_master_send; |
687 | ret = i2c_add_driver(&wm8731_i2c_driver); | 744 | ret = wm8731_add_i2c_device(pdev, setup); |
745 | } | ||
746 | #endif | ||
747 | #if defined(CONFIG_SPI_MASTER) | ||
748 | if (setup->spi) { | ||
749 | codec->hw_write = (hw_write_t)wm8731_spi_write; | ||
750 | ret = spi_register_driver(&wm8731_spi_driver); | ||
688 | if (ret != 0) | 751 | if (ret != 0) |
689 | printk(KERN_ERR "can't add i2c driver"); | 752 | printk(KERN_ERR "can't add spi driver"); |
690 | } | 753 | } |
691 | #else | ||
692 | /* Add other interfaces here */ | ||
693 | #endif | 754 | #endif |
694 | 755 | ||
695 | if (ret != 0) { | 756 | if (ret != 0) { |
@@ -711,8 +772,12 @@ static int wm8731_remove(struct platform_device *pdev) | |||
711 | snd_soc_free_pcms(socdev); | 772 | snd_soc_free_pcms(socdev); |
712 | snd_soc_dapm_free(socdev); | 773 | snd_soc_dapm_free(socdev); |
713 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 774 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
775 | i2c_unregister_device(codec->control_data); | ||
714 | i2c_del_driver(&wm8731_i2c_driver); | 776 | i2c_del_driver(&wm8731_i2c_driver); |
715 | #endif | 777 | #endif |
778 | #if defined(CONFIG_SPI_MASTER) | ||
779 | spi_unregister_driver(&wm8731_spi_driver); | ||
780 | #endif | ||
716 | kfree(codec->private_data); | 781 | kfree(codec->private_data); |
717 | kfree(codec); | 782 | kfree(codec); |
718 | 783 | ||