diff options
author | Cliff Cai <cliff.cai@analog.com> | 2008-09-01 13:47:03 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-09-04 04:34:27 -0400 |
commit | d2a403553ba7659d85dae2a05b1f3767d2fefcfe (patch) | |
tree | e902a5a87e8aa5359d2c7e7331ca22babf1694d6 /sound/soc/codecs/wm8731.c | |
parent | e5d3fd38f93755c5ab1e04b8e40196135f576355 (diff) |
ALSA: ASoC: Add SPI support for WM8731
[Modified to allow runtime selection between I2C and SPI and to select
SPI_MASTER for all codecs build so this is included. -- broonie]
Signed-off-by: Cliff Cai <cliff.cai@analog.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/soc/codecs/wm8731.c')
-rw-r--r-- | sound/soc/codecs/wm8731.c | 71 |
1 files changed, 69 insertions, 2 deletions
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 5814f9bdf0c0..975befdfd885 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> |
@@ -652,6 +653,61 @@ err_driver: | |||
652 | } | 653 | } |
653 | #endif | 654 | #endif |
654 | 655 | ||
656 | #if defined(CONFIG_SPI_MASTER) | ||
657 | static int __devinit wm8731_spi_probe(struct spi_device *spi) | ||
658 | { | ||
659 | struct snd_soc_device *socdev = wm8731_socdev; | ||
660 | struct snd_soc_codec *codec = socdev->codec; | ||
661 | int ret; | ||
662 | |||
663 | codec->control_data = spi; | ||
664 | |||
665 | ret = wm8731_init(socdev); | ||
666 | if (ret < 0) | ||
667 | dev_err(&spi->dev, "failed to initialise WM8731\n"); | ||
668 | |||
669 | return ret; | ||
670 | } | ||
671 | |||
672 | static int __devexit wm8731_spi_remove(struct spi_device *spi) | ||
673 | { | ||
674 | return 0; | ||
675 | } | ||
676 | |||
677 | static struct spi_driver wm8731_spi_driver = { | ||
678 | .driver = { | ||
679 | .name = "wm8731", | ||
680 | .bus = &spi_bus_type, | ||
681 | .owner = THIS_MODULE, | ||
682 | }, | ||
683 | .probe = wm8731_spi_probe, | ||
684 | .remove = __devexit_p(wm8731_spi_remove), | ||
685 | }; | ||
686 | |||
687 | static int wm8731_spi_write(struct spi_device *spi, const char *data, int len) | ||
688 | { | ||
689 | struct spi_transfer t; | ||
690 | struct spi_message m; | ||
691 | u16 msg[2]; | ||
692 | |||
693 | if (len <= 0) | ||
694 | return 0; | ||
695 | |||
696 | msg[0] = (data[0] << 8) + 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,13 +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 | codec->hw_write = (hw_write_t)i2c_master_send; | 743 | codec->hw_write = (hw_write_t)i2c_master_send; |
686 | ret = wm8731_add_i2c_device(pdev, setup); | 744 | ret = wm8731_add_i2c_device(pdev, setup); |
687 | } | 745 | } |
688 | #else | 746 | #endif |
689 | /* Add other interfaces here */ | 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); | ||
751 | if (ret != 0) | ||
752 | printk(KERN_ERR "can't add spi driver"); | ||
753 | } | ||
690 | #endif | 754 | #endif |
691 | 755 | ||
692 | if (ret != 0) { | 756 | if (ret != 0) { |
@@ -711,6 +775,9 @@ static int wm8731_remove(struct platform_device *pdev) | |||
711 | i2c_unregister_device(codec->control_data); | 775 | i2c_unregister_device(codec->control_data); |
712 | i2c_del_driver(&wm8731_i2c_driver); | 776 | i2c_del_driver(&wm8731_i2c_driver); |
713 | #endif | 777 | #endif |
778 | #if defined(CONFIG_SPI_MASTER) | ||
779 | spi_unregister_driver(&wm8731_spi_driver); | ||
780 | #endif | ||
714 | kfree(codec->private_data); | 781 | kfree(codec->private_data); |
715 | kfree(codec); | 782 | kfree(codec); |
716 | 783 | ||