aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@nokia.com>2009-01-29 07:57:50 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-01-29 08:58:04 -0500
commit7393958f630ac91e591e62058f2bdb61523ec60c (patch)
tree50df70a912bfeb37901378dc78dd8baff5038fa3 /sound/soc
parent0bf5460de96aa66abf9350333ee6711e73b3b31e (diff)
ASoC: TWL4030: Add analog loopback support
This patch adds the analog loopback/bypass support for twl4030 codec. Details for the implementation: It seams that the analog loopback needs the DAC powered on on the channel, where the loopback is selected. The switch for the DACs has been moved from the DAPM_DAC to the "Analog XX Playback Mixer". In this way the DAC will be powered while the audio playback is used or/and the loopback is enabled for the channel. The twl4030 codec powering has been reworked. Now the codec will be powered as long as it does not receives the SND_SOC_BIAS_OFF event. The exceptions are when the given change in the registers needs the codec power down/up cycle in order to take effect. Otherwise the codec is on. When the codec enters to STANDBY state and none of the loopback paths are enabled, than the amplifiers, which are no in the DAPM path are forced to turn off and the PLL is disabled. When playback/capture starts the disabled gains are restored and the PLL is enabled. When one of the loopback enabled in STANDBY mode, the disabled gains are restored and the PLL is enabled also. In short: the codec always goes to the lowest power state based on the bias_level and the bypass_state. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/codecs/twl4030.c212
-rw-r--r--sound/soc/codecs/twl4030.h15
2 files changed, 214 insertions, 13 deletions
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index f985bef40a39..c26854b398d3 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -117,6 +117,13 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
117 0x00, /* REG_MISC_SET_2 (0x49) */ 117 0x00, /* REG_MISC_SET_2 (0x49) */
118}; 118};
119 119
120/* codec private data */
121struct twl4030_priv {
122 unsigned int bypass_state;
123 unsigned int codec_powered;
124 unsigned int codec_muted;
125};
126
120/* 127/*
121 * read twl4030 register cache 128 * read twl4030 register cache
122 */ 129 */
@@ -156,8 +163,12 @@ static int twl4030_write(struct snd_soc_codec *codec,
156 163
157static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) 164static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
158{ 165{
166 struct twl4030_priv *twl4030 = codec->private_data;
159 u8 mode; 167 u8 mode;
160 168
169 if (enable == twl4030->codec_powered)
170 return;
171
161 mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); 172 mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
162 if (enable) 173 if (enable)
163 mode |= TWL4030_CODECPDZ; 174 mode |= TWL4030_CODECPDZ;
@@ -165,6 +176,7 @@ static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
165 mode &= ~TWL4030_CODECPDZ; 176 mode &= ~TWL4030_CODECPDZ;
166 177
167 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); 178 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
179 twl4030->codec_powered = enable;
168 180
169 /* REVISIT: this delay is present in TI sample drivers */ 181 /* REVISIT: this delay is present in TI sample drivers */
170 /* but there seems to be no TRM requirement for it */ 182 /* but there seems to be no TRM requirement for it */
@@ -184,11 +196,82 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
184 196
185} 197}
186 198
199static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute)
200{
201 struct twl4030_priv *twl4030 = codec->private_data;
202 u8 reg_val;
203
204 if (mute == twl4030->codec_muted)
205 return;
206
207 if (mute) {
208 /* Bypass the reg_cache and mute the volumes
209 * Headset mute is done in it's own event handler
210 * Things to mute: Earpiece, PreDrivL/R, CarkitL/R
211 */
212 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL);
213 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
214 reg_val & (~TWL4030_EAR_GAIN),
215 TWL4030_REG_EAR_CTL);
216
217 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL);
218 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
219 reg_val & (~TWL4030_PREDL_GAIN),
220 TWL4030_REG_PREDL_CTL);
221 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL);
222 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
223 reg_val & (~TWL4030_PREDR_GAIN),
224 TWL4030_REG_PREDL_CTL);
225
226 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL);
227 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
228 reg_val & (~TWL4030_PRECKL_GAIN),
229 TWL4030_REG_PRECKL_CTL);
230 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL);
231 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
232 reg_val & (~TWL4030_PRECKL_GAIN),
233 TWL4030_REG_PRECKR_CTL);
234
235 /* Disable PLL */
236 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL);
237 reg_val &= ~TWL4030_APLL_EN;
238 twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val);
239 } else {
240 /* Restore the volumes
241 * Headset mute is done in it's own event handler
242 * Things to restore: Earpiece, PreDrivL/R, CarkitL/R
243 */
244 twl4030_write(codec, TWL4030_REG_EAR_CTL,
245 twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL));
246
247 twl4030_write(codec, TWL4030_REG_PREDL_CTL,
248 twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL));
249 twl4030_write(codec, TWL4030_REG_PREDR_CTL,
250 twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL));
251
252 twl4030_write(codec, TWL4030_REG_PRECKL_CTL,
253 twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL));
254 twl4030_write(codec, TWL4030_REG_PRECKR_CTL,
255 twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL));
256
257 /* Enable PLL */
258 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL);
259 reg_val |= TWL4030_APLL_EN;
260 twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val);
261 }
262
263 twl4030->codec_muted = mute;
264}
265
187static void twl4030_power_up(struct snd_soc_codec *codec) 266static void twl4030_power_up(struct snd_soc_codec *codec)
188{ 267{
268 struct twl4030_priv *twl4030 = codec->private_data;
189 u8 anamicl, regmisc1, byte; 269 u8 anamicl, regmisc1, byte;
190 int i = 0; 270 int i = 0;
191 271
272 if (twl4030->codec_powered)
273 return;
274
192 /* set CODECPDZ to turn on codec */ 275 /* set CODECPDZ to turn on codec */
193 twl4030_codec_enable(codec, 1); 276 twl4030_codec_enable(codec, 1);
194 277
@@ -220,6 +303,9 @@ static void twl4030_power_up(struct snd_soc_codec *codec)
220 twl4030_codec_enable(codec, 1); 303 twl4030_codec_enable(codec, 1);
221} 304}
222 305
306/*
307 * Unconditional power down
308 */
223static void twl4030_power_down(struct snd_soc_codec *codec) 309static void twl4030_power_down(struct snd_soc_codec *codec)
224{ 310{
225 /* power down */ 311 /* power down */
@@ -402,6 +488,22 @@ static const struct soc_enum twl4030_micpathtx2_enum =
402static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control = 488static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control =
403SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum); 489SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum);
404 490
491/* Analog bypass for AudioR1 */
492static const struct snd_kcontrol_new twl4030_dapm_abypassr1_control =
493 SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXR1_APGA_CTL, 2, 1, 0);
494
495/* Analog bypass for AudioL1 */
496static const struct snd_kcontrol_new twl4030_dapm_abypassl1_control =
497 SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL1_APGA_CTL, 2, 1, 0);
498
499/* Analog bypass for AudioR2 */
500static const struct snd_kcontrol_new twl4030_dapm_abypassr2_control =
501 SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXR2_APGA_CTL, 2, 1, 0);
502
503/* Analog bypass for AudioL2 */
504static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control =
505 SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL2_APGA_CTL, 2, 1, 0);
506
405static int micpath_event(struct snd_soc_dapm_widget *w, 507static int micpath_event(struct snd_soc_dapm_widget *w,
406 struct snd_kcontrol *kcontrol, int event) 508 struct snd_kcontrol *kcontrol, int event)
407{ 509{
@@ -497,6 +599,31 @@ static int headsetl_event(struct snd_soc_dapm_widget *w,
497 return 0; 599 return 0;
498} 600}
499 601
602static int bypass_event(struct snd_soc_dapm_widget *w,
603 struct snd_kcontrol *kcontrol, int event)
604{
605 struct soc_mixer_control *m =
606 (struct soc_mixer_control *)w->kcontrols->private_value;
607 struct twl4030_priv *twl4030 = w->codec->private_data;
608 unsigned char reg;
609
610 reg = twl4030_read_reg_cache(w->codec, m->reg);
611 if (reg & (1 << m->shift))
612 twl4030->bypass_state |=
613 (1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
614 else
615 twl4030->bypass_state &=
616 ~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
617
618 if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) {
619 if (twl4030->bypass_state)
620 twl4030_codec_mute(w->codec, 0);
621 else
622 twl4030_codec_mute(w->codec, 1);
623 }
624 return 0;
625}
626
500/* 627/*
501 * Some of the gain controls in TWL (mostly those which are associated with 628 * Some of the gain controls in TWL (mostly those which are associated with
502 * the outputs) are implemented in an interesting way: 629 * the outputs) are implemented in an interesting way:
@@ -775,13 +902,13 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
775 902
776 /* DACs */ 903 /* DACs */
777 SND_SOC_DAPM_DAC("DAC Right1", "Right Front Playback", 904 SND_SOC_DAPM_DAC("DAC Right1", "Right Front Playback",
778 TWL4030_REG_AVDAC_CTL, 0, 0), 905 SND_SOC_NOPM, 0, 0),
779 SND_SOC_DAPM_DAC("DAC Left1", "Left Front Playback", 906 SND_SOC_DAPM_DAC("DAC Left1", "Left Front Playback",
780 TWL4030_REG_AVDAC_CTL, 1, 0), 907 SND_SOC_NOPM, 0, 0),
781 SND_SOC_DAPM_DAC("DAC Right2", "Right Rear Playback", 908 SND_SOC_DAPM_DAC("DAC Right2", "Right Rear Playback",
782 TWL4030_REG_AVDAC_CTL, 2, 0), 909 SND_SOC_NOPM, 0, 0),
783 SND_SOC_DAPM_DAC("DAC Left2", "Left Rear Playback", 910 SND_SOC_DAPM_DAC("DAC Left2", "Left Rear Playback",
784 TWL4030_REG_AVDAC_CTL, 3, 0), 911 SND_SOC_NOPM, 0, 0),
785 912
786 /* Analog PGAs */ 913 /* Analog PGAs */
787 SND_SOC_DAPM_PGA("ARXR1_APGA", TWL4030_REG_ARXR1_APGA_CTL, 914 SND_SOC_DAPM_PGA("ARXR1_APGA", TWL4030_REG_ARXR1_APGA_CTL,
@@ -793,6 +920,29 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
793 SND_SOC_DAPM_PGA("ARXL2_APGA", TWL4030_REG_ARXL2_APGA_CTL, 920 SND_SOC_DAPM_PGA("ARXL2_APGA", TWL4030_REG_ARXL2_APGA_CTL,
794 0, 0, NULL, 0), 921 0, 0, NULL, 0),
795 922
923 /* Analog bypasses */
924 SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0,
925 &twl4030_dapm_abypassr1_control, bypass_event,
926 SND_SOC_DAPM_POST_REG),
927 SND_SOC_DAPM_SWITCH_E("Left1 Analog Loopback", SND_SOC_NOPM, 0, 0,
928 &twl4030_dapm_abypassl1_control,
929 bypass_event, SND_SOC_DAPM_POST_REG),
930 SND_SOC_DAPM_SWITCH_E("Right2 Analog Loopback", SND_SOC_NOPM, 0, 0,
931 &twl4030_dapm_abypassr2_control,
932 bypass_event, SND_SOC_DAPM_POST_REG),
933 SND_SOC_DAPM_SWITCH_E("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0,
934 &twl4030_dapm_abypassl2_control,
935 bypass_event, SND_SOC_DAPM_POST_REG),
936
937 SND_SOC_DAPM_MIXER("Analog R1 Playback Mixer", TWL4030_REG_AVDAC_CTL,
938 0, 0, NULL, 0),
939 SND_SOC_DAPM_MIXER("Analog L1 Playback Mixer", TWL4030_REG_AVDAC_CTL,
940 1, 0, NULL, 0),
941 SND_SOC_DAPM_MIXER("Analog R2 Playback Mixer", TWL4030_REG_AVDAC_CTL,
942 2, 0, NULL, 0),
943 SND_SOC_DAPM_MIXER("Analog L2 Playback Mixer", TWL4030_REG_AVDAC_CTL,
944 3, 0, NULL, 0),
945
796 /* Output MUX controls */ 946 /* Output MUX controls */
797 /* Earpiece */ 947 /* Earpiece */
798 SND_SOC_DAPM_VALUE_MUX("Earpiece Mux", SND_SOC_NOPM, 0, 0, 948 SND_SOC_DAPM_VALUE_MUX("Earpiece Mux", SND_SOC_NOPM, 0, 0,
@@ -863,13 +1013,19 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
863 SND_SOC_DAPM_MICBIAS("Mic Bias 1", TWL4030_REG_MICBIAS_CTL, 0, 0), 1013 SND_SOC_DAPM_MICBIAS("Mic Bias 1", TWL4030_REG_MICBIAS_CTL, 0, 0),
864 SND_SOC_DAPM_MICBIAS("Mic Bias 2", TWL4030_REG_MICBIAS_CTL, 1, 0), 1014 SND_SOC_DAPM_MICBIAS("Mic Bias 2", TWL4030_REG_MICBIAS_CTL, 1, 0),
865 SND_SOC_DAPM_MICBIAS("Headset Mic Bias", TWL4030_REG_MICBIAS_CTL, 2, 0), 1015 SND_SOC_DAPM_MICBIAS("Headset Mic Bias", TWL4030_REG_MICBIAS_CTL, 2, 0),
1016
866}; 1017};
867 1018
868static const struct snd_soc_dapm_route intercon[] = { 1019static const struct snd_soc_dapm_route intercon[] = {
869 {"ARXL1_APGA", NULL, "DAC Left1"}, 1020 {"Analog L1 Playback Mixer", NULL, "DAC Left1"},
870 {"ARXR1_APGA", NULL, "DAC Right1"}, 1021 {"Analog R1 Playback Mixer", NULL, "DAC Right1"},
871 {"ARXL2_APGA", NULL, "DAC Left2"}, 1022 {"Analog L2 Playback Mixer", NULL, "DAC Left2"},
872 {"ARXR2_APGA", NULL, "DAC Right2"}, 1023 {"Analog R2 Playback Mixer", NULL, "DAC Right2"},
1024
1025 {"ARXL1_APGA", NULL, "Analog L1 Playback Mixer"},
1026 {"ARXR1_APGA", NULL, "Analog R1 Playback Mixer"},
1027 {"ARXL2_APGA", NULL, "Analog L2 Playback Mixer"},
1028 {"ARXR2_APGA", NULL, "Analog R2 Playback Mixer"},
873 1029
874 /* Internal playback routings */ 1030 /* Internal playback routings */
875 /* Earpiece */ 1031 /* Earpiece */
@@ -951,6 +1107,17 @@ static const struct snd_soc_dapm_route intercon[] = {
951 {"ADC Virtual Left2", NULL, "TX2 Capture Route"}, 1107 {"ADC Virtual Left2", NULL, "TX2 Capture Route"},
952 {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, 1108 {"ADC Virtual Right2", NULL, "TX2 Capture Route"},
953 1109
1110 /* Analog bypass routes */
1111 {"Right1 Analog Loopback", "Switch", "Analog Right Capture Route"},
1112 {"Left1 Analog Loopback", "Switch", "Analog Left Capture Route"},
1113 {"Right2 Analog Loopback", "Switch", "Analog Right Capture Route"},
1114 {"Left2 Analog Loopback", "Switch", "Analog Left Capture Route"},
1115
1116 {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"},
1117 {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"},
1118 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"},
1119 {"Analog L2 Playback Mixer", NULL, "Left2 Analog Loopback"},
1120
954}; 1121};
955 1122
956static int twl4030_add_widgets(struct snd_soc_codec *codec) 1123static int twl4030_add_widgets(struct snd_soc_codec *codec)
@@ -967,16 +1134,25 @@ static int twl4030_add_widgets(struct snd_soc_codec *codec)
967static int twl4030_set_bias_level(struct snd_soc_codec *codec, 1134static int twl4030_set_bias_level(struct snd_soc_codec *codec,
968 enum snd_soc_bias_level level) 1135 enum snd_soc_bias_level level)
969{ 1136{
1137 struct twl4030_priv *twl4030 = codec->private_data;
1138
970 switch (level) { 1139 switch (level) {
971 case SND_SOC_BIAS_ON: 1140 case SND_SOC_BIAS_ON:
972 twl4030_power_up(codec); 1141 twl4030_codec_mute(codec, 0);
973 break; 1142 break;
974 case SND_SOC_BIAS_PREPARE: 1143 case SND_SOC_BIAS_PREPARE:
975 /* TODO: develop a twl4030_prepare function */ 1144 twl4030_power_up(codec);
1145 if (twl4030->bypass_state)
1146 twl4030_codec_mute(codec, 0);
1147 else
1148 twl4030_codec_mute(codec, 1);
976 break; 1149 break;
977 case SND_SOC_BIAS_STANDBY: 1150 case SND_SOC_BIAS_STANDBY:
978 /* TODO: develop a twl4030_standby function */ 1151 twl4030_power_up(codec);
979 twl4030_power_down(codec); 1152 if (twl4030->bypass_state)
1153 twl4030_codec_mute(codec, 0);
1154 else
1155 twl4030_codec_mute(codec, 1);
980 break; 1156 break;
981 case SND_SOC_BIAS_OFF: 1157 case SND_SOC_BIAS_OFF:
982 twl4030_power_down(codec); 1158 twl4030_power_down(codec);
@@ -996,7 +1172,6 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
996 struct snd_soc_codec *codec = socdev->card->codec; 1172 struct snd_soc_codec *codec = socdev->card->codec;
997 u8 mode, old_mode, format, old_format; 1173 u8 mode, old_mode, format, old_format;
998 1174
999
1000 /* bit rate */ 1175 /* bit rate */
1001 old_mode = twl4030_read_reg_cache(codec, 1176 old_mode = twl4030_read_reg_cache(codec,
1002 TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ; 1177 TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ;
@@ -1038,6 +1213,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1038 1213
1039 if (mode != old_mode) { 1214 if (mode != old_mode) {
1040 /* change rate and set CODECPDZ */ 1215 /* change rate and set CODECPDZ */
1216 twl4030_codec_enable(codec, 0);
1041 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); 1217 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
1042 twl4030_codec_enable(codec, 1); 1218 twl4030_codec_enable(codec, 1);
1043 } 1219 }
@@ -1258,11 +1434,19 @@ static int twl4030_probe(struct platform_device *pdev)
1258{ 1434{
1259 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1435 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1260 struct snd_soc_codec *codec; 1436 struct snd_soc_codec *codec;
1437 struct twl4030_priv *twl4030;
1261 1438
1262 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 1439 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
1263 if (codec == NULL) 1440 if (codec == NULL)
1264 return -ENOMEM; 1441 return -ENOMEM;
1265 1442
1443 twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
1444 if (twl4030 == NULL) {
1445 kfree(codec);
1446 return -ENOMEM;
1447 }
1448
1449 codec->private_data = twl4030;
1266 socdev->card->codec = codec; 1450 socdev->card->codec = codec;
1267 mutex_init(&codec->mutex); 1451 mutex_init(&codec->mutex);
1268 INIT_LIST_HEAD(&codec->dapm_widgets); 1452 INIT_LIST_HEAD(&codec->dapm_widgets);
@@ -1280,8 +1464,10 @@ static int twl4030_remove(struct platform_device *pdev)
1280 struct snd_soc_codec *codec = socdev->card->codec; 1464 struct snd_soc_codec *codec = socdev->card->codec;
1281 1465
1282 printk(KERN_INFO "TWL4030 Audio Codec remove\n"); 1466 printk(KERN_INFO "TWL4030 Audio Codec remove\n");
1467 twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
1283 snd_soc_free_pcms(socdev); 1468 snd_soc_free_pcms(socdev);
1284 snd_soc_dapm_free(socdev); 1469 snd_soc_dapm_free(socdev);
1470 kfree(codec->private_data);
1285 kfree(codec); 1471 kfree(codec);
1286 1472
1287 return 0; 1473 return 0;
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
index 442e5a828617..33dbb144dad1 100644
--- a/sound/soc/codecs/twl4030.h
+++ b/sound/soc/codecs/twl4030.h
@@ -170,6 +170,9 @@
170#define TWL4030_CLK256FS_EN 0x02 170#define TWL4030_CLK256FS_EN 0x02
171#define TWL4030_AIF_EN 0x01 171#define TWL4030_AIF_EN 0x01
172 172
173/* EAR_CTL (0x21) */
174#define TWL4030_EAR_GAIN 0x30
175
173/* HS_GAIN_SET (0x23) Fields */ 176/* HS_GAIN_SET (0x23) Fields */
174 177
175#define TWL4030_HSR_GAIN 0x0C 178#define TWL4030_HSR_GAIN 0x0C
@@ -198,6 +201,18 @@
198#define TWL4030_RAMP_DELAY_2581MS 0x1C 201#define TWL4030_RAMP_DELAY_2581MS 0x1C
199#define TWL4030_RAMP_EN 0x02 202#define TWL4030_RAMP_EN 0x02
200 203
204/* PREDL_CTL (0x25) */
205#define TWL4030_PREDL_GAIN 0x30
206
207/* PREDR_CTL (0x26) */
208#define TWL4030_PREDR_GAIN 0x30
209
210/* PRECKL_CTL (0x27) */
211#define TWL4030_PRECKL_GAIN 0x30
212
213/* PRECKR_CTL (0x28) */
214#define TWL4030_PRECKR_GAIN 0x30
215
201/* HFL_CTL (0x29, 0x2A) Fields */ 216/* HFL_CTL (0x29, 0x2A) Fields */
202#define TWL4030_HF_CTL_HB_EN 0x04 217#define TWL4030_HF_CTL_HB_EN 0x04
203#define TWL4030_HF_CTL_LOOP_EN 0x08 218#define TWL4030_HF_CTL_LOOP_EN 0x08