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.c114
1 files changed, 74 insertions, 40 deletions
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index ca1e24a8f12a..81a62d198b70 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -23,11 +23,13 @@
23 23
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/slab.h>
26#include <sound/core.h> 27#include <sound/core.h>
27#include <sound/soc.h> 28#include <sound/soc.h>
28#include <sound/initval.h> 29#include <sound/initval.h>
29#include <linux/i2c.h> 30#include <linux/i2c.h>
30#include <linux/delay.h> 31#include <linux/delay.h>
32#include <linux/regulator/consumer.h>
31 33
32#include "cs4270.h" 34#include "cs4270.h"
33 35
@@ -106,6 +108,10 @@
106#define CS4270_MUTE_DAC_A 0x01 108#define CS4270_MUTE_DAC_A 0x01
107#define CS4270_MUTE_DAC_B 0x02 109#define CS4270_MUTE_DAC_B 0x02
108 110
111static const char *supply_names[] = {
112 "va", "vd", "vlc"
113};
114
109/* Private data for the CS4270 */ 115/* Private data for the CS4270 */
110struct cs4270_private { 116struct cs4270_private {
111 struct snd_soc_codec codec; 117 struct snd_soc_codec codec;
@@ -114,6 +120,9 @@ struct cs4270_private {
114 unsigned int mode; /* The mode (I2S or left-justified) */ 120 unsigned int mode; /* The mode (I2S or left-justified) */
115 unsigned int slave_mode; 121 unsigned int slave_mode;
116 unsigned int manual_mute; 122 unsigned int manual_mute;
123
124 /* power domain regulators */
125 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
117}; 126};
118 127
119/** 128/**
@@ -192,6 +201,11 @@ static struct cs4270_mode_ratios cs4270_mode_ratios[] = {
192 * This function must be called by the machine driver's 'startup' function, 201 * 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 202 * otherwise the list of supported sample rates will not be available in
194 * time for ALSA. 203 * time for ALSA.
204 *
205 * For setups with variable MCLKs, pass 0 as 'freq' argument. This will cause
206 * theoretically possible sample rates to be enabled. Call it again with a
207 * proper value set one the external clock is set (most probably you would do
208 * that from a machine's driver 'hw_param' hook.
195 */ 209 */
196static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, 210static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai,
197 int clk_id, unsigned int freq, int dir) 211 int clk_id, unsigned int freq, int dir)
@@ -205,20 +219,27 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai,
205 219
206 cs4270->mclk = freq; 220 cs4270->mclk = freq;
207 221
208 for (i = 0; i < NUM_MCLK_RATIOS; i++) { 222 if (cs4270->mclk) {
209 unsigned int rate = freq / cs4270_mode_ratios[i].ratio; 223 for (i = 0; i < NUM_MCLK_RATIOS; i++) {
210 rates |= snd_pcm_rate_to_rate_bit(rate); 224 unsigned int rate = freq / cs4270_mode_ratios[i].ratio;
211 if (rate < rate_min) 225 rates |= snd_pcm_rate_to_rate_bit(rate);
212 rate_min = rate; 226 if (rate < rate_min)
213 if (rate > rate_max) 227 rate_min = rate;
214 rate_max = rate; 228 if (rate > rate_max)
215 } 229 rate_max = rate;
216 /* FIXME: soc should support a rate list */ 230 }
217 rates &= ~SNDRV_PCM_RATE_KNOT; 231 /* FIXME: soc should support a rate list */
232 rates &= ~SNDRV_PCM_RATE_KNOT;
218 233
219 if (!rates) { 234 if (!rates) {
220 dev_err(codec->dev, "could not find a valid sample rate\n"); 235 dev_err(codec->dev, "could not find a valid sample rate\n");
221 return -EINVAL; 236 return -EINVAL;
237 }
238 } else {
239 /* enable all possible rates */
240 rates = SNDRV_PCM_RATE_8000_192000;
241 rate_min = 8000;
242 rate_max = 192000;
222 } 243 }
223 244
224 codec_dai->playback.rates = rates; 245 codec_dai->playback.rates = rates;
@@ -520,6 +541,7 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
520 SOC_SINGLE("Digital Sidetone Switch", CS4270_FORMAT, 5, 1, 0), 541 SOC_SINGLE("Digital Sidetone Switch", CS4270_FORMAT, 5, 1, 0),
521 SOC_SINGLE("Soft Ramp Switch", CS4270_TRANS, 6, 1, 0), 542 SOC_SINGLE("Soft Ramp Switch", CS4270_TRANS, 6, 1, 0),
522 SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0), 543 SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0),
544 SOC_SINGLE("De-emphasis filter", CS4270_TRANS, 0, 1, 0),
523 SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1), 545 SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1),
524 SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0), 546 SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0),
525 SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 1), 547 SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 1),
@@ -578,7 +600,8 @@ static int cs4270_probe(struct platform_device *pdev)
578{ 600{
579 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 601 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
580 struct snd_soc_codec *codec = cs4270_codec; 602 struct snd_soc_codec *codec = cs4270_codec;
581 int ret; 603 struct cs4270_private *cs4270 = codec->private_data;
604 int i, ret;
582 605
583 /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ 606 /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */
584 socdev->card->codec = codec; 607 socdev->card->codec = codec;
@@ -598,15 +621,26 @@ static int cs4270_probe(struct platform_device *pdev)
598 goto error_free_pcms; 621 goto error_free_pcms;
599 } 622 }
600 623
601 /* And finally, register the socdev */ 624 /* get the power supply regulators */
602 ret = snd_soc_init_card(socdev); 625 for (i = 0; i < ARRAY_SIZE(supply_names); i++)
603 if (ret < 0) { 626 cs4270->supplies[i].supply = supply_names[i];
604 dev_err(codec->dev, "failed to register card\n"); 627
628 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies),
629 cs4270->supplies);
630 if (ret < 0)
605 goto error_free_pcms; 631 goto error_free_pcms;
606 } 632
633 ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
634 cs4270->supplies);
635 if (ret < 0)
636 goto error_free_regulators;
607 637
608 return 0; 638 return 0;
609 639
640error_free_regulators:
641 regulator_bulk_free(ARRAY_SIZE(cs4270->supplies),
642 cs4270->supplies);
643
610error_free_pcms: 644error_free_pcms:
611 snd_soc_free_pcms(socdev); 645 snd_soc_free_pcms(socdev);
612 646
@@ -622,8 +656,12 @@ error_free_pcms:
622static int cs4270_remove(struct platform_device *pdev) 656static int cs4270_remove(struct platform_device *pdev)
623{ 657{
624 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 658 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
659 struct snd_soc_codec *codec = cs4270_codec;
660 struct cs4270_private *cs4270 = codec->private_data;
625 661
626 snd_soc_free_pcms(socdev); 662 snd_soc_free_pcms(socdev);
663 regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
664 regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
627 665
628 return 0; 666 return 0;
629}; 667};
@@ -802,36 +840,36 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
802 * and all registers are written back to the hardware when resuming. 840 * and all registers are written back to the hardware when resuming.
803 */ 841 */
804 842
805static int cs4270_i2c_suspend(struct i2c_client *client, pm_message_t mesg) 843static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
806{ 844{
807 struct cs4270_private *cs4270 = i2c_get_clientdata(client); 845 struct snd_soc_codec *codec = cs4270_codec;
808 struct snd_soc_codec *codec = &cs4270->codec; 846 struct cs4270_private *cs4270 = codec->private_data;
809 847 int reg, ret;
810 return snd_soc_suspend_device(codec->dev);
811}
812 848
813static int cs4270_i2c_resume(struct i2c_client *client) 849 reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL;
814{ 850 if (reg < 0)
815 struct cs4270_private *cs4270 = i2c_get_clientdata(client); 851 return reg;
816 struct snd_soc_codec *codec = &cs4270->codec;
817 852
818 return snd_soc_resume_device(codec->dev); 853 ret = snd_soc_write(codec, CS4270_PWRCTL, reg);
819} 854 if (ret < 0)
855 return ret;
820 856
821static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) 857 regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies),
822{ 858 cs4270->supplies);
823 struct snd_soc_codec *codec = cs4270_codec;
824 int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL;
825 859
826 return snd_soc_write(codec, CS4270_PWRCTL, reg); 860 return 0;
827} 861}
828 862
829static int cs4270_soc_resume(struct platform_device *pdev) 863static int cs4270_soc_resume(struct platform_device *pdev)
830{ 864{
831 struct snd_soc_codec *codec = cs4270_codec; 865 struct snd_soc_codec *codec = cs4270_codec;
866 struct cs4270_private *cs4270 = codec->private_data;
832 struct i2c_client *i2c_client = codec->control_data; 867 struct i2c_client *i2c_client = codec->control_data;
833 int reg; 868 int reg;
834 869
870 regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
871 cs4270->supplies);
872
835 /* In case the device was put to hard reset during sleep, we need to 873 /* In case the device was put to hard reset during sleep, we need to
836 * wait 500ns here before any I2C communication. */ 874 * wait 500ns here before any I2C communication. */
837 ndelay(500); 875 ndelay(500);
@@ -853,8 +891,6 @@ static int cs4270_soc_resume(struct platform_device *pdev)
853 return snd_soc_write(codec, CS4270_PWRCTL, reg); 891 return snd_soc_write(codec, CS4270_PWRCTL, reg);
854} 892}
855#else 893#else
856#define cs4270_i2c_suspend NULL
857#define cs4270_i2c_resume NULL
858#define cs4270_soc_suspend NULL 894#define cs4270_soc_suspend NULL
859#define cs4270_soc_resume NULL 895#define cs4270_soc_resume NULL
860#endif /* CONFIG_PM */ 896#endif /* CONFIG_PM */
@@ -873,8 +909,6 @@ static struct i2c_driver cs4270_i2c_driver = {
873 .id_table = cs4270_id, 909 .id_table = cs4270_id,
874 .probe = cs4270_i2c_probe, 910 .probe = cs4270_i2c_probe,
875 .remove = cs4270_i2c_remove, 911 .remove = cs4270_i2c_remove,
876 .suspend = cs4270_i2c_suspend,
877 .resume = cs4270_i2c_resume,
878}; 912};
879 913
880/* 914/*