diff options
author | Daniel Mack <daniel@caiaq.de> | 2009-11-30 11:56:11 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-12-07 08:11:56 -0500 |
commit | ffbfd336f9eac361e1630cfcb17a70607551daf2 (patch) | |
tree | 23304b522d850dcf1e52940324c32f70ff7aa071 /sound/soc/codecs/cs4270.c | |
parent | a91eb199e4dc8a2ab3fb7a53f1a23ce82b29fc04 (diff) |
ASoC: Add regulator support to CS4270 codec driver
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Acked-by: Timur Tabi <timur@freescale.com>
Cc: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/cs4270.c')
-rw-r--r-- | sound/soc/codecs/cs4270.c | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index ffe122d1cd76..8b5457542a0e 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <sound/initval.h> | 28 | #include <sound/initval.h> |
29 | #include <linux/i2c.h> | 29 | #include <linux/i2c.h> |
30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
31 | #include <linux/regulator/consumer.h> | ||
31 | 32 | ||
32 | #include "cs4270.h" | 33 | #include "cs4270.h" |
33 | 34 | ||
@@ -106,6 +107,10 @@ | |||
106 | #define CS4270_MUTE_DAC_A 0x01 | 107 | #define CS4270_MUTE_DAC_A 0x01 |
107 | #define CS4270_MUTE_DAC_B 0x02 | 108 | #define CS4270_MUTE_DAC_B 0x02 |
108 | 109 | ||
110 | static const char *supply_names[] = { | ||
111 | "va", "vd", "vlc" | ||
112 | }; | ||
113 | |||
109 | /* Private data for the CS4270 */ | 114 | /* Private data for the CS4270 */ |
110 | struct cs4270_private { | 115 | struct cs4270_private { |
111 | struct snd_soc_codec codec; | 116 | struct snd_soc_codec codec; |
@@ -114,6 +119,9 @@ struct cs4270_private { | |||
114 | unsigned int mode; /* The mode (I2S or left-justified) */ | 119 | unsigned int mode; /* The mode (I2S or left-justified) */ |
115 | unsigned int slave_mode; | 120 | unsigned int slave_mode; |
116 | unsigned int manual_mute; | 121 | unsigned int manual_mute; |
122 | |||
123 | /* power domain regulators */ | ||
124 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | ||
117 | }; | 125 | }; |
118 | 126 | ||
119 | /** | 127 | /** |
@@ -579,7 +587,8 @@ static int cs4270_probe(struct platform_device *pdev) | |||
579 | { | 587 | { |
580 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 588 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
581 | struct snd_soc_codec *codec = cs4270_codec; | 589 | struct snd_soc_codec *codec = cs4270_codec; |
582 | int ret; | 590 | struct cs4270_private *cs4270 = codec->private_data; |
591 | int i, ret; | ||
583 | 592 | ||
584 | /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ | 593 | /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ |
585 | socdev->card->codec = codec; | 594 | socdev->card->codec = codec; |
@@ -599,6 +608,15 @@ static int cs4270_probe(struct platform_device *pdev) | |||
599 | goto error_free_pcms; | 608 | goto error_free_pcms; |
600 | } | 609 | } |
601 | 610 | ||
611 | /* get the power supply regulators */ | ||
612 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
613 | cs4270->supplies[i].supply = supply_names[i]; | ||
614 | |||
615 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), | ||
616 | cs4270->supplies); | ||
617 | if (ret < 0) | ||
618 | goto error_free_pcms; | ||
619 | |||
602 | return 0; | 620 | return 0; |
603 | 621 | ||
604 | error_free_pcms: | 622 | error_free_pcms: |
@@ -616,8 +634,11 @@ error_free_pcms: | |||
616 | static int cs4270_remove(struct platform_device *pdev) | 634 | static int cs4270_remove(struct platform_device *pdev) |
617 | { | 635 | { |
618 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 636 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
637 | struct snd_soc_codec *codec = cs4270_codec; | ||
638 | struct cs4270_private *cs4270 = codec->private_data; | ||
619 | 639 | ||
620 | snd_soc_free_pcms(socdev); | 640 | snd_soc_free_pcms(socdev); |
641 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); | ||
621 | 642 | ||
622 | return 0; | 643 | return 0; |
623 | }; | 644 | }; |
@@ -799,17 +820,33 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id); | |||
799 | static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) | 820 | static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) |
800 | { | 821 | { |
801 | struct snd_soc_codec *codec = cs4270_codec; | 822 | struct snd_soc_codec *codec = cs4270_codec; |
802 | int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; | 823 | struct cs4270_private *cs4270 = codec->private_data; |
824 | int reg, ret; | ||
803 | 825 | ||
804 | return snd_soc_write(codec, CS4270_PWRCTL, reg); | 826 | reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; |
827 | if (reg < 0) | ||
828 | return reg; | ||
829 | |||
830 | ret = snd_soc_write(codec, CS4270_PWRCTL, reg); | ||
831 | if (ret < 0) | ||
832 | return ret; | ||
833 | |||
834 | regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), | ||
835 | cs4270->supplies); | ||
836 | |||
837 | return 0; | ||
805 | } | 838 | } |
806 | 839 | ||
807 | static int cs4270_soc_resume(struct platform_device *pdev) | 840 | static int cs4270_soc_resume(struct platform_device *pdev) |
808 | { | 841 | { |
809 | struct snd_soc_codec *codec = cs4270_codec; | 842 | struct snd_soc_codec *codec = cs4270_codec; |
843 | struct cs4270_private *cs4270 = codec->private_data; | ||
810 | struct i2c_client *i2c_client = codec->control_data; | 844 | struct i2c_client *i2c_client = codec->control_data; |
811 | int reg; | 845 | int reg; |
812 | 846 | ||
847 | regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), | ||
848 | cs4270->supplies); | ||
849 | |||
813 | /* In case the device was put to hard reset during sleep, we need to | 850 | /* In case the device was put to hard reset during sleep, we need to |
814 | * wait 500ns here before any I2C communication. */ | 851 | * wait 500ns here before any I2C communication. */ |
815 | ndelay(500); | 852 | ndelay(500); |