diff options
Diffstat (limited to 'sound/soc/codecs/wm8510.c')
-rw-r--r-- | sound/soc/codecs/wm8510.c | 111 |
1 files changed, 96 insertions, 15 deletions
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 9a37c8d95ed2..d8ca2da8d634 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright 2006 Wolfson Microelectronics PLC. | 4 | * Copyright 2006 Wolfson Microelectronics PLC. |
5 | * | 5 | * |
6 | * Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com> | 6 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 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 | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/spi/spi.h> | ||
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
23 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
@@ -27,7 +28,6 @@ | |||
27 | 28 | ||
28 | #include "wm8510.h" | 29 | #include "wm8510.h" |
29 | 30 | ||
30 | #define AUDIO_NAME "wm8510" | ||
31 | #define WM8510_VERSION "0.6" | 31 | #define WM8510_VERSION "0.6" |
32 | 32 | ||
33 | struct snd_soc_codec_device soc_codec_dev_wm8510; | 33 | struct snd_soc_codec_device soc_codec_dev_wm8510; |
@@ -55,6 +55,9 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { | |||
55 | 0x0001, | 55 | 0x0001, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | #define WM8510_POWER1_BIASEN 0x08 | ||
59 | #define WM8510_POWER1_BUFIOEN 0x10 | ||
60 | |||
58 | /* | 61 | /* |
59 | * read wm8510 register cache | 62 | * read wm8510 register cache |
60 | */ | 63 | */ |
@@ -224,9 +227,9 @@ SND_SOC_DAPM_PGA("SpkN Out", WM8510_POWER3, 5, 0, NULL, 0), | |||
224 | SND_SOC_DAPM_PGA("SpkP Out", WM8510_POWER3, 6, 0, NULL, 0), | 227 | SND_SOC_DAPM_PGA("SpkP Out", WM8510_POWER3, 6, 0, NULL, 0), |
225 | SND_SOC_DAPM_PGA("Mono Out", WM8510_POWER3, 7, 0, NULL, 0), | 228 | SND_SOC_DAPM_PGA("Mono Out", WM8510_POWER3, 7, 0, NULL, 0), |
226 | 229 | ||
227 | SND_SOC_DAPM_PGA("Mic PGA", WM8510_POWER2, 2, 0, | 230 | SND_SOC_DAPM_MIXER("Mic PGA", WM8510_POWER2, 2, 0, |
228 | &wm8510_micpga_controls[0], | 231 | &wm8510_micpga_controls[0], |
229 | ARRAY_SIZE(wm8510_micpga_controls)), | 232 | ARRAY_SIZE(wm8510_micpga_controls)), |
230 | SND_SOC_DAPM_MIXER("Boost Mixer", WM8510_POWER2, 4, 0, | 233 | SND_SOC_DAPM_MIXER("Boost Mixer", WM8510_POWER2, 4, 0, |
231 | &wm8510_boost_controls[0], | 234 | &wm8510_boost_controls[0], |
232 | ARRAY_SIZE(wm8510_boost_controls)), | 235 | ARRAY_SIZE(wm8510_boost_controls)), |
@@ -526,23 +529,35 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute) | |||
526 | static int wm8510_set_bias_level(struct snd_soc_codec *codec, | 529 | static int wm8510_set_bias_level(struct snd_soc_codec *codec, |
527 | enum snd_soc_bias_level level) | 530 | enum snd_soc_bias_level level) |
528 | { | 531 | { |
532 | u16 power1 = wm8510_read_reg_cache(codec, WM8510_POWER1) & ~0x3; | ||
529 | 533 | ||
530 | switch (level) { | 534 | switch (level) { |
531 | case SND_SOC_BIAS_ON: | 535 | case SND_SOC_BIAS_ON: |
532 | wm8510_write(codec, WM8510_POWER1, 0x1ff); | ||
533 | wm8510_write(codec, WM8510_POWER2, 0x1ff); | ||
534 | wm8510_write(codec, WM8510_POWER3, 0x1ff); | ||
535 | break; | ||
536 | case SND_SOC_BIAS_PREPARE: | 536 | case SND_SOC_BIAS_PREPARE: |
537 | power1 |= 0x1; /* VMID 50k */ | ||
538 | wm8510_write(codec, WM8510_POWER1, power1); | ||
539 | break; | ||
540 | |||
537 | case SND_SOC_BIAS_STANDBY: | 541 | case SND_SOC_BIAS_STANDBY: |
542 | power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN; | ||
543 | |||
544 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | ||
545 | /* Initial cap charge at VMID 5k */ | ||
546 | wm8510_write(codec, WM8510_POWER1, power1 | 0x3); | ||
547 | mdelay(100); | ||
548 | } | ||
549 | |||
550 | power1 |= 0x2; /* VMID 500k */ | ||
551 | wm8510_write(codec, WM8510_POWER1, power1); | ||
538 | break; | 552 | break; |
553 | |||
539 | case SND_SOC_BIAS_OFF: | 554 | case SND_SOC_BIAS_OFF: |
540 | /* everything off, dac mute, inactive */ | 555 | wm8510_write(codec, WM8510_POWER1, 0); |
541 | wm8510_write(codec, WM8510_POWER1, 0x0); | 556 | wm8510_write(codec, WM8510_POWER2, 0); |
542 | wm8510_write(codec, WM8510_POWER2, 0x0); | 557 | wm8510_write(codec, WM8510_POWER3, 0); |
543 | wm8510_write(codec, WM8510_POWER3, 0x0); | ||
544 | break; | 558 | break; |
545 | } | 559 | } |
560 | |||
546 | codec->bias_level = level; | 561 | codec->bias_level = level; |
547 | return 0; | 562 | return 0; |
548 | } | 563 | } |
@@ -640,6 +655,7 @@ static int wm8510_init(struct snd_soc_device *socdev) | |||
640 | } | 655 | } |
641 | 656 | ||
642 | /* power on device */ | 657 | /* power on device */ |
658 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
643 | wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 659 | wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
644 | wm8510_add_controls(codec); | 660 | wm8510_add_controls(codec); |
645 | wm8510_add_widgets(codec); | 661 | wm8510_add_widgets(codec); |
@@ -747,6 +763,62 @@ err_driver: | |||
747 | } | 763 | } |
748 | #endif | 764 | #endif |
749 | 765 | ||
766 | #if defined(CONFIG_SPI_MASTER) | ||
767 | static int __devinit wm8510_spi_probe(struct spi_device *spi) | ||
768 | { | ||
769 | struct snd_soc_device *socdev = wm8510_socdev; | ||
770 | struct snd_soc_codec *codec = socdev->codec; | ||
771 | int ret; | ||
772 | |||
773 | codec->control_data = spi; | ||
774 | |||
775 | ret = wm8510_init(socdev); | ||
776 | if (ret < 0) | ||
777 | dev_err(&spi->dev, "failed to initialise WM8510\n"); | ||
778 | |||
779 | return ret; | ||
780 | } | ||
781 | |||
782 | static int __devexit wm8510_spi_remove(struct spi_device *spi) | ||
783 | { | ||
784 | return 0; | ||
785 | } | ||
786 | |||
787 | static struct spi_driver wm8510_spi_driver = { | ||
788 | .driver = { | ||
789 | .name = "wm8510", | ||
790 | .bus = &spi_bus_type, | ||
791 | .owner = THIS_MODULE, | ||
792 | }, | ||
793 | .probe = wm8510_spi_probe, | ||
794 | .remove = __devexit_p(wm8510_spi_remove), | ||
795 | }; | ||
796 | |||
797 | static int wm8510_spi_write(struct spi_device *spi, const char *data, int len) | ||
798 | { | ||
799 | struct spi_transfer t; | ||
800 | struct spi_message m; | ||
801 | u8 msg[2]; | ||
802 | |||
803 | if (len <= 0) | ||
804 | return 0; | ||
805 | |||
806 | msg[0] = data[0]; | ||
807 | msg[1] = data[1]; | ||
808 | |||
809 | spi_message_init(&m); | ||
810 | memset(&t, 0, (sizeof t)); | ||
811 | |||
812 | t.tx_buf = &msg[0]; | ||
813 | t.len = len; | ||
814 | |||
815 | spi_message_add_tail(&t, &m); | ||
816 | spi_sync(spi, &m); | ||
817 | |||
818 | return len; | ||
819 | } | ||
820 | #endif /* CONFIG_SPI_MASTER */ | ||
821 | |||
750 | static int wm8510_probe(struct platform_device *pdev) | 822 | static int wm8510_probe(struct platform_device *pdev) |
751 | { | 823 | { |
752 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 824 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
@@ -772,8 +844,14 @@ static int wm8510_probe(struct platform_device *pdev) | |||
772 | codec->hw_write = (hw_write_t)i2c_master_send; | 844 | codec->hw_write = (hw_write_t)i2c_master_send; |
773 | ret = wm8510_add_i2c_device(pdev, setup); | 845 | ret = wm8510_add_i2c_device(pdev, setup); |
774 | } | 846 | } |
775 | #else | 847 | #endif |
776 | /* Add other interfaces here */ | 848 | #if defined(CONFIG_SPI_MASTER) |
849 | if (setup->spi) { | ||
850 | codec->hw_write = (hw_write_t)wm8510_spi_write; | ||
851 | ret = spi_register_driver(&wm8510_spi_driver); | ||
852 | if (ret != 0) | ||
853 | printk(KERN_ERR "can't add spi driver"); | ||
854 | } | ||
777 | #endif | 855 | #endif |
778 | 856 | ||
779 | if (ret != 0) | 857 | if (ret != 0) |
@@ -796,6 +874,9 @@ static int wm8510_remove(struct platform_device *pdev) | |||
796 | i2c_unregister_device(codec->control_data); | 874 | i2c_unregister_device(codec->control_data); |
797 | i2c_del_driver(&wm8510_i2c_driver); | 875 | i2c_del_driver(&wm8510_i2c_driver); |
798 | #endif | 876 | #endif |
877 | #if defined(CONFIG_SPI_MASTER) | ||
878 | spi_unregister_driver(&wm8510_spi_driver); | ||
879 | #endif | ||
799 | kfree(codec); | 880 | kfree(codec); |
800 | 881 | ||
801 | return 0; | 882 | return 0; |