aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/twl6040.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-25 11:32:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-25 11:32:05 -0400
commit33081adf8b89d5a716d7e1c60171768d39795b39 (patch)
tree275de58bbbb5f7ddffcdc087844cfc7fbe4315be /sound/soc/codecs/twl6040.c
parentc55960499f810357a29659b32d6ea594abee9237 (diff)
parent506ecbca71d07fa327dd986be1682e90885678ee (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (365 commits) ALSA: hda - Disable sticky PCM stream assignment for AD codecs ALSA: usb - Creative USB X-Fi volume knob support ALSA: ca0106: Use card specific dac id for mute controls. ALSA: ca0106: Allow different sound cards to use different SPI channel mappings. ALSA: ca0106: Create a nice spot for mapping channels to dacs. ALSA: ca0106: Move enabling of front dac out of hardcoded setup sequence. ALSA: ca0106: Pull out dac powering routine into separate function. ALSA: ca0106 - add Sound Blaster 5.1vx info. ASoC: tlv320dac33: Use usleep_range for delays ALSA: usb-audio: add Novation Launchpad support ALSA: hda - Add workarounds for CT-IBG controllers ALSA: hda - Fix wrong TLV mute bit for STAC/IDT codecs ASoC: tpa6130a2: Error handling for broken chip ASoC: max98088: Staticise m98088_eq_band ASoC: soc-core: Fix codec->name memory leak ALSA: hda - Apply ideapad quirk to Acer laptops with Cxt5066 ALSA: hda - Add some workarounds for Creative IBG ALSA: hda - Fix wrong SPDIF NID assignment for CA0110 ALSA: hda - Fix codec rename rules for ALC662-compatible codecs ALSA: hda - Add alc_init_jacks() call to other codecs ...
Diffstat (limited to 'sound/soc/codecs/twl6040.c')
-rw-r--r--sound/soc/codecs/twl6040.c170
1 files changed, 44 insertions, 126 deletions
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 64a807f1a8a1..10f6e5214511 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -45,7 +45,6 @@
45 45
46/* codec private data */ 46/* codec private data */
47struct twl6040_data { 47struct twl6040_data {
48 struct snd_soc_codec codec;
49 int audpwron; 48 int audpwron;
50 int naudint; 49 int naudint;
51 int codec_powered; 50 int codec_powered;
@@ -770,8 +769,7 @@ static int twl6040_startup(struct snd_pcm_substream *substream,
770 struct snd_soc_dai *dai) 769 struct snd_soc_dai *dai)
771{ 770{
772 struct snd_soc_pcm_runtime *rtd = substream->private_data; 771 struct snd_soc_pcm_runtime *rtd = substream->private_data;
773 struct snd_soc_device *socdev = rtd->socdev; 772 struct snd_soc_codec *codec = rtd->codec;
774 struct snd_soc_codec *codec = socdev->card->codec;
775 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 773 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
776 774
777 if (!priv->sysclk) { 775 if (!priv->sysclk) {
@@ -803,8 +801,7 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
803 struct snd_soc_dai *dai) 801 struct snd_soc_dai *dai)
804{ 802{
805 struct snd_soc_pcm_runtime *rtd = substream->private_data; 803 struct snd_soc_pcm_runtime *rtd = substream->private_data;
806 struct snd_soc_device *socdev = rtd->socdev; 804 struct snd_soc_codec *codec = rtd->codec;
807 struct snd_soc_codec *codec = socdev->card->codec;
808 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 805 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
809 u8 lppllctl; 806 u8 lppllctl;
810 int rate; 807 int rate;
@@ -839,8 +836,7 @@ static int twl6040_trigger(struct snd_pcm_substream *substream,
839 int cmd, struct snd_soc_dai *dai) 836 int cmd, struct snd_soc_dai *dai)
840{ 837{
841 struct snd_soc_pcm_runtime *rtd = substream->private_data; 838 struct snd_soc_pcm_runtime *rtd = substream->private_data;
842 struct snd_soc_device *socdev = rtd->socdev; 839 struct snd_soc_codec *codec = rtd->codec;
843 struct snd_soc_codec *codec = socdev->card->codec;
844 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 840 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
845 841
846 switch (cmd) { 842 switch (cmd) {
@@ -978,8 +974,8 @@ static struct snd_soc_dai_ops twl6040_dai_ops = {
978 .set_sysclk = twl6040_set_dai_sysclk, 974 .set_sysclk = twl6040_set_dai_sysclk,
979}; 975};
980 976
981struct snd_soc_dai twl6040_dai = { 977static struct snd_soc_dai_driver twl6040_dai = {
982 .name = "twl6040", 978 .name = "twl6040-hifi",
983 .playback = { 979 .playback = {
984 .stream_name = "Playback", 980 .stream_name = "Playback",
985 .channels_min = 1, 981 .channels_min = 1,
@@ -996,24 +992,17 @@ struct snd_soc_dai twl6040_dai = {
996 }, 992 },
997 .ops = &twl6040_dai_ops, 993 .ops = &twl6040_dai_ops,
998}; 994};
999EXPORT_SYMBOL_GPL(twl6040_dai);
1000 995
1001#ifdef CONFIG_PM 996#ifdef CONFIG_PM
1002static int twl6040_suspend(struct platform_device *pdev, pm_message_t state) 997static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state)
1003{ 998{
1004 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1005 struct snd_soc_codec *codec = socdev->card->codec;
1006
1007 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); 999 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1008 1000
1009 return 0; 1001 return 0;
1010} 1002}
1011 1003
1012static int twl6040_resume(struct platform_device *pdev) 1004static int twl6040_resume(struct snd_soc_codec *codec)
1013{ 1005{
1014 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1015 struct snd_soc_codec *codec = socdev->card->codec;
1016
1017 twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1006 twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1018 1007
1019 return 0; 1008 return 0;
@@ -1023,68 +1012,9 @@ static int twl6040_resume(struct platform_device *pdev)
1023#define twl6040_resume NULL 1012#define twl6040_resume NULL
1024#endif 1013#endif
1025 1014
1026static struct snd_soc_codec *twl6040_codec; 1015static int twl6040_probe(struct snd_soc_codec *codec)
1027
1028static int twl6040_probe(struct platform_device *pdev)
1029{
1030 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1031 struct snd_soc_codec *codec;
1032 int ret = 0;
1033
1034 BUG_ON(!twl6040_codec);
1035
1036 codec = twl6040_codec;
1037 socdev->card->codec = codec;
1038
1039 /* register pcms */
1040 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1041 if (ret < 0) {
1042 dev_err(&pdev->dev, "failed to create pcms\n");
1043 return ret;
1044 }
1045
1046 snd_soc_add_controls(codec, twl6040_snd_controls,
1047 ARRAY_SIZE(twl6040_snd_controls));
1048 twl6040_add_widgets(codec);
1049
1050 if (ret < 0) {
1051 dev_err(&pdev->dev, "failed to register card\n");
1052 goto card_err;
1053 }
1054
1055 return ret;
1056
1057card_err:
1058 snd_soc_free_pcms(socdev);
1059 snd_soc_dapm_free(socdev);
1060 return ret;
1061}
1062
1063static int twl6040_remove(struct platform_device *pdev)
1064{
1065 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1066 struct snd_soc_codec *codec = socdev->card->codec;
1067
1068 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1069 snd_soc_free_pcms(socdev);
1070 snd_soc_dapm_free(socdev);
1071 kfree(codec);
1072
1073 return 0;
1074}
1075
1076struct snd_soc_codec_device soc_codec_dev_twl6040 = {
1077 .probe = twl6040_probe,
1078 .remove = twl6040_remove,
1079 .suspend = twl6040_suspend,
1080 .resume = twl6040_resume,
1081};
1082EXPORT_SYMBOL_GPL(soc_codec_dev_twl6040);
1083
1084static int __devinit twl6040_codec_probe(struct platform_device *pdev)
1085{ 1016{
1086 struct twl4030_codec_data *twl_codec = pdev->dev.platform_data; 1017 struct twl4030_codec_data *twl_codec = codec->dev->platform_data;
1087 struct snd_soc_codec *codec;
1088 struct twl6040_data *priv; 1018 struct twl6040_data *priv;
1089 int audpwron, naudint; 1019 int audpwron, naudint;
1090 int ret = 0; 1020 int ret = 0;
@@ -1092,6 +1022,7 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)
1092 priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); 1022 priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
1093 if (priv == NULL) 1023 if (priv == NULL)
1094 return -ENOMEM; 1024 return -ENOMEM;
1025 snd_soc_codec_set_drvdata(codec, priv);
1095 1026
1096 if (twl_codec) { 1027 if (twl_codec) {
1097 audpwron = twl_codec->audpwron_gpio; 1028 audpwron = twl_codec->audpwron_gpio;
@@ -1104,29 +1035,6 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)
1104 priv->audpwron = audpwron; 1035 priv->audpwron = audpwron;
1105 priv->naudint = naudint; 1036 priv->naudint = naudint;
1106 1037
1107 codec = &priv->codec;
1108 codec->dev = &pdev->dev;
1109 twl6040_dai.dev = &pdev->dev;
1110
1111 codec->name = "twl6040";
1112 codec->owner = THIS_MODULE;
1113 codec->read = twl6040_read_reg_cache;
1114 codec->write = twl6040_write;
1115 codec->set_bias_level = twl6040_set_bias_level;
1116 snd_soc_codec_set_drvdata(codec, priv);
1117 codec->dai = &twl6040_dai;
1118 codec->num_dai = 1;
1119 codec->reg_cache_size = ARRAY_SIZE(twl6040_reg);
1120 codec->reg_cache = kmemdup(twl6040_reg, sizeof(twl6040_reg),
1121 GFP_KERNEL);
1122 if (codec->reg_cache == NULL) {
1123 ret = -ENOMEM;
1124 goto cache_err;
1125 }
1126
1127 mutex_init(&codec->mutex);
1128 INIT_LIST_HEAD(&codec->dapm_widgets);
1129 INIT_LIST_HEAD(&codec->dapm_paths);
1130 init_completion(&priv->ready); 1038 init_completion(&priv->ready);
1131 1039
1132 if (gpio_is_valid(audpwron)) { 1040 if (gpio_is_valid(audpwron)) {
@@ -1169,23 +1077,12 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)
1169 if (ret) 1077 if (ret)
1170 goto irq_err; 1078 goto irq_err;
1171 1079
1172 ret = snd_soc_register_codec(codec); 1080 snd_soc_add_controls(codec, twl6040_snd_controls,
1173 if (ret) 1081 ARRAY_SIZE(twl6040_snd_controls));
1174 goto reg_err; 1082 twl6040_add_widgets(codec);
1175
1176 twl6040_codec = codec;
1177
1178 ret = snd_soc_register_dai(&twl6040_dai);
1179 if (ret)
1180 goto dai_err;
1181 1083
1182 return 0; 1084 return 0;
1183 1085
1184dai_err:
1185 snd_soc_unregister_codec(codec);
1186 twl6040_codec = NULL;
1187reg_err:
1188 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1189irq_err: 1086irq_err:
1190 if (naudint) 1087 if (naudint)
1191 free_irq(naudint, codec); 1088 free_irq(naudint, codec);
@@ -1193,36 +1090,57 @@ gpio2_err:
1193 if (gpio_is_valid(audpwron)) 1090 if (gpio_is_valid(audpwron))
1194 gpio_free(audpwron); 1091 gpio_free(audpwron);
1195gpio1_err: 1092gpio1_err:
1196 kfree(codec->reg_cache);
1197cache_err:
1198 kfree(priv); 1093 kfree(priv);
1199 return ret; 1094 return ret;
1200} 1095}
1201 1096
1202static int __devexit twl6040_codec_remove(struct platform_device *pdev) 1097static int twl6040_remove(struct snd_soc_codec *codec)
1203{ 1098{
1204 struct twl6040_data *priv = snd_soc_codec_get_drvdata(twl6040_codec); 1099 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1205 int audpwron = priv->audpwron; 1100 int audpwron = priv->audpwron;
1206 int naudint = priv->naudint; 1101 int naudint = priv->naudint;
1207 1102
1103 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1104
1208 if (gpio_is_valid(audpwron)) 1105 if (gpio_is_valid(audpwron))
1209 gpio_free(audpwron); 1106 gpio_free(audpwron);
1210 1107
1211 if (naudint) 1108 if (naudint)
1212 free_irq(naudint, twl6040_codec); 1109 free_irq(naudint, codec);
1213 1110
1214 snd_soc_unregister_dai(&twl6040_dai); 1111 kfree(priv);
1215 snd_soc_unregister_codec(twl6040_codec);
1216 1112
1217 kfree(twl6040_codec); 1113 return 0;
1218 twl6040_codec = NULL; 1114}
1219 1115
1116static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
1117 .probe = twl6040_probe,
1118 .remove = twl6040_remove,
1119 .suspend = twl6040_suspend,
1120 .resume = twl6040_resume,
1121 .read = twl6040_read_reg_cache,
1122 .write = twl6040_write,
1123 .set_bias_level = twl6040_set_bias_level,
1124 .reg_cache_size = ARRAY_SIZE(twl6040_reg),
1125 .reg_word_size = sizeof(u8),
1126 .reg_cache_default = twl6040_reg,
1127};
1128
1129static int __devinit twl6040_codec_probe(struct platform_device *pdev)
1130{
1131 return snd_soc_register_codec(&pdev->dev,
1132 &soc_codec_dev_twl6040, &twl6040_dai, 1);
1133}
1134
1135static int __devexit twl6040_codec_remove(struct platform_device *pdev)
1136{
1137 snd_soc_unregister_codec(&pdev->dev);
1220 return 0; 1138 return 0;
1221} 1139}
1222 1140
1223static struct platform_driver twl6040_codec_driver = { 1141static struct platform_driver twl6040_codec_driver = {
1224 .driver = { 1142 .driver = {
1225 .name = "twl6040_codec", 1143 .name = "twl6040-codec",
1226 .owner = THIS_MODULE, 1144 .owner = THIS_MODULE,
1227 }, 1145 },
1228 .probe = twl6040_codec_probe, 1146 .probe = twl6040_codec_probe,