aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/cs4270.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/cs4270.c')
-rw-r--r--sound/soc/codecs/cs4270.c91
1 files changed, 75 insertions, 16 deletions
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index ffe122d1cd76..dfbeb2db61b3 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
110static const char *supply_names[] = {
111 "va", "vd", "vlc"
112};
113
109/* Private data for the CS4270 */ 114/* Private data for the CS4270 */
110struct cs4270_private { 115struct 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/**
@@ -192,6 +200,11 @@ static struct cs4270_mode_ratios cs4270_mode_ratios[] = {
192 * This function must be called by the machine driver's 'startup' function, 200 * This function must be called by the machine driver's 'startup' function,
193 * otherwise the list of supported sample rates will not be available in 201 * otherwise the list of supported sample rates will not be available in
194 * time for ALSA. 202 * time for ALSA.
203 *
204 * For setups with variable MCLKs, pass 0 as 'freq' argument. This will cause
205 * theoretically possible sample rates to be enabled. Call it again with a
206 * proper value set one the external clock is set (most probably you would do
207 * that from a machine's driver 'hw_param' hook.
195 */ 208 */
196static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, 209static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai,
197 int clk_id, unsigned int freq, int dir) 210 int clk_id, unsigned int freq, int dir)
@@ -205,20 +218,27 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai,
205 218
206 cs4270->mclk = freq; 219 cs4270->mclk = freq;
207 220
208 for (i = 0; i < NUM_MCLK_RATIOS; i++) { 221 if (cs4270->mclk) {
209 unsigned int rate = freq / cs4270_mode_ratios[i].ratio; 222 for (i = 0; i < NUM_MCLK_RATIOS; i++) {
210 rates |= snd_pcm_rate_to_rate_bit(rate); 223 unsigned int rate = freq / cs4270_mode_ratios[i].ratio;
211 if (rate < rate_min) 224 rates |= snd_pcm_rate_to_rate_bit(rate);
212 rate_min = rate; 225 if (rate < rate_min)
213 if (rate > rate_max) 226 rate_min = rate;
214 rate_max = rate; 227 if (rate > rate_max)
215 } 228 rate_max = rate;
216 /* FIXME: soc should support a rate list */ 229 }
217 rates &= ~SNDRV_PCM_RATE_KNOT; 230 /* FIXME: soc should support a rate list */
231 rates &= ~SNDRV_PCM_RATE_KNOT;
218 232
219 if (!rates) { 233 if (!rates) {
220 dev_err(codec->dev, "could not find a valid sample rate\n"); 234 dev_err(codec->dev, "could not find a valid sample rate\n");
221 return -EINVAL; 235 return -EINVAL;
236 }
237 } else {
238 /* enable all possible rates */
239 rates = SNDRV_PCM_RATE_8000_192000;
240 rate_min = 8000;
241 rate_max = 192000;
222 } 242 }
223 243
224 codec_dai->playback.rates = rates; 244 codec_dai->playback.rates = rates;
@@ -579,7 +599,8 @@ static int cs4270_probe(struct platform_device *pdev)
579{ 599{
580 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 600 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
581 struct snd_soc_codec *codec = cs4270_codec; 601 struct snd_soc_codec *codec = cs4270_codec;
582 int ret; 602 struct cs4270_private *cs4270 = codec->private_data;
603 int i, ret;
583 604
584 /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ 605 /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */
585 socdev->card->codec = codec; 606 socdev->card->codec = codec;
@@ -599,8 +620,26 @@ static int cs4270_probe(struct platform_device *pdev)
599 goto error_free_pcms; 620 goto error_free_pcms;
600 } 621 }
601 622
623 /* get the power supply regulators */
624 for (i = 0; i < ARRAY_SIZE(supply_names); i++)
625 cs4270->supplies[i].supply = supply_names[i];
626
627 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies),
628 cs4270->supplies);
629 if (ret < 0)
630 goto error_free_pcms;
631
632 ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
633 cs4270->supplies);
634 if (ret < 0)
635 goto error_free_regulators;
636
602 return 0; 637 return 0;
603 638
639error_free_regulators:
640 regulator_bulk_free(ARRAY_SIZE(cs4270->supplies),
641 cs4270->supplies);
642
604error_free_pcms: 643error_free_pcms:
605 snd_soc_free_pcms(socdev); 644 snd_soc_free_pcms(socdev);
606 645
@@ -616,8 +655,12 @@ error_free_pcms:
616static int cs4270_remove(struct platform_device *pdev) 655static int cs4270_remove(struct platform_device *pdev)
617{ 656{
618 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 657 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
658 struct snd_soc_codec *codec = cs4270_codec;
659 struct cs4270_private *cs4270 = codec->private_data;
619 660
620 snd_soc_free_pcms(socdev); 661 snd_soc_free_pcms(socdev);
662 regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
663 regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
621 664
622 return 0; 665 return 0;
623}; 666};
@@ -799,17 +842,33 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
799static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) 842static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
800{ 843{
801 struct snd_soc_codec *codec = cs4270_codec; 844 struct snd_soc_codec *codec = cs4270_codec;
802 int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; 845 struct cs4270_private *cs4270 = codec->private_data;
846 int reg, ret;
803 847
804 return snd_soc_write(codec, CS4270_PWRCTL, reg); 848 reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL;
849 if (reg < 0)
850 return reg;
851
852 ret = snd_soc_write(codec, CS4270_PWRCTL, reg);
853 if (ret < 0)
854 return ret;
855
856 regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies),
857 cs4270->supplies);
858
859 return 0;
805} 860}
806 861
807static int cs4270_soc_resume(struct platform_device *pdev) 862static int cs4270_soc_resume(struct platform_device *pdev)
808{ 863{
809 struct snd_soc_codec *codec = cs4270_codec; 864 struct snd_soc_codec *codec = cs4270_codec;
865 struct cs4270_private *cs4270 = codec->private_data;
810 struct i2c_client *i2c_client = codec->control_data; 866 struct i2c_client *i2c_client = codec->control_data;
811 int reg; 867 int reg;
812 868
869 regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
870 cs4270->supplies);
871
813 /* In case the device was put to hard reset during sleep, we need to 872 /* In case the device was put to hard reset during sleep, we need to
814 * wait 500ns here before any I2C communication. */ 873 * wait 500ns here before any I2C communication. */
815 ndelay(500); 874 ndelay(500);