diff options
-rw-r--r-- | sound/soc/codecs/twl6040.c | 110 | ||||
-rw-r--r-- | sound/soc/codecs/twl6040.h | 1 | ||||
-rw-r--r-- | sound/soc/omap/sdp4430.c | 50 |
3 files changed, 79 insertions, 82 deletions
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 8f923e5c9e48..94108ce63c6b 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -80,6 +80,7 @@ struct twl6040_data { | |||
80 | int codec_powered; | 80 | int codec_powered; |
81 | int pll; | 81 | int pll; |
82 | int non_lp; | 82 | int non_lp; |
83 | int pll_power_mode; | ||
83 | int hs_power_mode; | 84 | int hs_power_mode; |
84 | int hs_power_mode_locked; | 85 | int hs_power_mode_locked; |
85 | unsigned int clk_in; | 86 | unsigned int clk_in; |
@@ -210,6 +211,37 @@ static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = { | |||
210 | TWL6040_REG_DLB, | 211 | TWL6040_REG_DLB, |
211 | }; | 212 | }; |
212 | 213 | ||
214 | /* set of rates for each pll: low-power and high-performance */ | ||
215 | static unsigned int lp_rates[] = { | ||
216 | 8000, | ||
217 | 11250, | ||
218 | 16000, | ||
219 | 22500, | ||
220 | 32000, | ||
221 | 44100, | ||
222 | 48000, | ||
223 | 88200, | ||
224 | 96000, | ||
225 | }; | ||
226 | |||
227 | static struct snd_pcm_hw_constraint_list lp_constraints = { | ||
228 | .count = ARRAY_SIZE(lp_rates), | ||
229 | .list = lp_rates, | ||
230 | }; | ||
231 | |||
232 | static unsigned int hp_rates[] = { | ||
233 | 8000, | ||
234 | 16000, | ||
235 | 32000, | ||
236 | 48000, | ||
237 | 96000, | ||
238 | }; | ||
239 | |||
240 | static struct snd_pcm_hw_constraint_list hp_constraints = { | ||
241 | .count = ARRAY_SIZE(hp_rates), | ||
242 | .list = hp_rates, | ||
243 | }; | ||
244 | |||
213 | /* | 245 | /* |
214 | * read twl6040 register cache | 246 | * read twl6040 register cache |
215 | */ | 247 | */ |
@@ -1049,6 +1081,43 @@ static int twl6040_headset_power_put_enum(struct snd_kcontrol *kcontrol, | |||
1049 | return ret; | 1081 | return ret; |
1050 | } | 1082 | } |
1051 | 1083 | ||
1084 | static int twl6040_pll_get_enum(struct snd_kcontrol *kcontrol, | ||
1085 | struct snd_ctl_elem_value *ucontrol) | ||
1086 | { | ||
1087 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1088 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | ||
1089 | |||
1090 | ucontrol->value.enumerated.item[0] = priv->pll_power_mode; | ||
1091 | |||
1092 | return 0; | ||
1093 | } | ||
1094 | |||
1095 | static int twl6040_pll_put_enum(struct snd_kcontrol *kcontrol, | ||
1096 | struct snd_ctl_elem_value *ucontrol) | ||
1097 | { | ||
1098 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1099 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | ||
1100 | |||
1101 | priv->pll_power_mode = ucontrol->value.enumerated.item[0]; | ||
1102 | if (priv->pll_power_mode) | ||
1103 | priv->sysclk_constraints = &hp_constraints; | ||
1104 | else | ||
1105 | priv->sysclk_constraints = &lp_constraints; | ||
1106 | |||
1107 | return 0; | ||
1108 | } | ||
1109 | |||
1110 | int twl6040_get_clk_id(struct snd_soc_codec *codec) | ||
1111 | { | ||
1112 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | ||
1113 | |||
1114 | if (priv->pll_power_mode) | ||
1115 | return TWL6040_SYSCLK_SEL_HPPLL; | ||
1116 | else | ||
1117 | return TWL6040_SYSCLK_SEL_LPPLL; | ||
1118 | } | ||
1119 | EXPORT_SYMBOL_GPL(twl6040_get_clk_id); | ||
1120 | |||
1052 | static const struct snd_kcontrol_new twl6040_snd_controls[] = { | 1121 | static const struct snd_kcontrol_new twl6040_snd_controls[] = { |
1053 | /* Capture gains */ | 1122 | /* Capture gains */ |
1054 | SOC_DOUBLE_TLV("Capture Preamplifier Volume", | 1123 | SOC_DOUBLE_TLV("Capture Preamplifier Volume", |
@@ -1071,6 +1140,9 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = { | |||
1071 | SOC_ENUM_EXT("Headset Power Mode", twl6040_power_mode_enum, | 1140 | SOC_ENUM_EXT("Headset Power Mode", twl6040_power_mode_enum, |
1072 | twl6040_headset_power_get_enum, | 1141 | twl6040_headset_power_get_enum, |
1073 | twl6040_headset_power_put_enum), | 1142 | twl6040_headset_power_put_enum), |
1143 | |||
1144 | SOC_ENUM_EXT("PLL Selection", twl6040_power_mode_enum, | ||
1145 | twl6040_pll_get_enum, twl6040_pll_put_enum), | ||
1074 | }; | 1146 | }; |
1075 | 1147 | ||
1076 | static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { | 1148 | static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { |
@@ -1289,38 +1361,6 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec, | |||
1289 | return 0; | 1361 | return 0; |
1290 | } | 1362 | } |
1291 | 1363 | ||
1292 | /* set of rates for each pll: low-power and high-performance */ | ||
1293 | |||
1294 | static unsigned int lp_rates[] = { | ||
1295 | 8000, | ||
1296 | 11250, | ||
1297 | 16000, | ||
1298 | 22500, | ||
1299 | 32000, | ||
1300 | 44100, | ||
1301 | 48000, | ||
1302 | 88200, | ||
1303 | 96000, | ||
1304 | }; | ||
1305 | |||
1306 | static struct snd_pcm_hw_constraint_list lp_constraints = { | ||
1307 | .count = ARRAY_SIZE(lp_rates), | ||
1308 | .list = lp_rates, | ||
1309 | }; | ||
1310 | |||
1311 | static unsigned int hp_rates[] = { | ||
1312 | 8000, | ||
1313 | 16000, | ||
1314 | 32000, | ||
1315 | 48000, | ||
1316 | 96000, | ||
1317 | }; | ||
1318 | |||
1319 | static struct snd_pcm_hw_constraint_list hp_constraints = { | ||
1320 | .count = ARRAY_SIZE(hp_rates), | ||
1321 | .list = hp_rates, | ||
1322 | }; | ||
1323 | |||
1324 | static int twl6040_startup(struct snd_pcm_substream *substream, | 1364 | static int twl6040_startup(struct snd_pcm_substream *substream, |
1325 | struct snd_soc_dai *dai) | 1365 | struct snd_soc_dai *dai) |
1326 | { | 1366 | { |
@@ -1427,16 +1467,12 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
1427 | freq, priv->sysclk); | 1467 | freq, priv->sysclk); |
1428 | if (ret) | 1468 | if (ret) |
1429 | return ret; | 1469 | return ret; |
1430 | |||
1431 | priv->sysclk_constraints = &lp_constraints; | ||
1432 | break; | 1470 | break; |
1433 | case TWL6040_SYSCLK_SEL_HPPLL: | 1471 | case TWL6040_SYSCLK_SEL_HPPLL: |
1434 | ret = twl6040_set_pll(twl6040, TWL6040_HPPLL_ID, | 1472 | ret = twl6040_set_pll(twl6040, TWL6040_HPPLL_ID, |
1435 | freq, priv->sysclk); | 1473 | freq, priv->sysclk); |
1436 | if (ret) | 1474 | if (ret) |
1437 | return ret; | 1475 | return ret; |
1438 | |||
1439 | priv->sysclk_constraints = &hp_constraints; | ||
1440 | break; | 1476 | break; |
1441 | default: | 1477 | default: |
1442 | dev_err(codec->dev, "unknown clk_id %d\n", clk_id); | 1478 | dev_err(codec->dev, "unknown clk_id %d\n", clk_id); |
@@ -1563,7 +1599,7 @@ static int twl6040_probe(struct snd_soc_codec *codec) | |||
1563 | goto work_err; | 1599 | goto work_err; |
1564 | } | 1600 | } |
1565 | 1601 | ||
1566 | priv->sysclk_constraints = &hp_constraints; | 1602 | priv->sysclk_constraints = &lp_constraints; |
1567 | priv->workqueue = create_singlethread_workqueue("twl6040-codec"); | 1603 | priv->workqueue = create_singlethread_workqueue("twl6040-codec"); |
1568 | if (!priv->workqueue) { | 1604 | if (!priv->workqueue) { |
1569 | ret = -ENOMEM; | 1605 | ret = -ENOMEM; |
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h index 234bfad24e6f..d8de67869dd9 100644 --- a/sound/soc/codecs/twl6040.h +++ b/sound/soc/codecs/twl6040.h | |||
@@ -24,5 +24,6 @@ | |||
24 | 24 | ||
25 | void twl6040_hs_jack_detect(struct snd_soc_codec *codec, | 25 | void twl6040_hs_jack_detect(struct snd_soc_codec *codec, |
26 | struct snd_soc_jack *jack, int report); | 26 | struct snd_soc_jack *jack, int report); |
27 | int twl6040_get_clk_id(struct snd_soc_codec *codec); | ||
27 | 28 | ||
28 | #endif /* End of __TWL6040_H__ */ | 29 | #endif /* End of __TWL6040_H__ */ |
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c index 5d67c25bca5e..b80efb02bfca 100644 --- a/sound/soc/omap/sdp4430.c +++ b/sound/soc/omap/sdp4430.c | |||
@@ -36,8 +36,6 @@ | |||
36 | #include "omap-pcm.h" | 36 | #include "omap-pcm.h" |
37 | #include "../codecs/twl6040.h" | 37 | #include "../codecs/twl6040.h" |
38 | 38 | ||
39 | static int twl6040_power_mode; | ||
40 | |||
41 | static int sdp4430_hw_params(struct snd_pcm_substream *substream, | 39 | static int sdp4430_hw_params(struct snd_pcm_substream *substream, |
42 | struct snd_pcm_hw_params *params) | 40 | struct snd_pcm_hw_params *params) |
43 | { | 41 | { |
@@ -46,13 +44,13 @@ static int sdp4430_hw_params(struct snd_pcm_substream *substream, | |||
46 | int clk_id, freq; | 44 | int clk_id, freq; |
47 | int ret; | 45 | int ret; |
48 | 46 | ||
49 | if (twl6040_power_mode) { | 47 | clk_id = twl6040_get_clk_id(rtd->codec); |
50 | clk_id = TWL6040_SYSCLK_SEL_HPPLL; | 48 | if (clk_id == TWL6040_SYSCLK_SEL_HPPLL) |
51 | freq = 38400000; | 49 | freq = 38400000; |
52 | } else { | 50 | else if (clk_id == TWL6040_SYSCLK_SEL_LPPLL) |
53 | clk_id = TWL6040_SYSCLK_SEL_LPPLL; | ||
54 | freq = 32768; | 51 | freq = 32768; |
55 | } | 52 | else |
53 | return -EINVAL; | ||
56 | 54 | ||
57 | /* set the codec mclk */ | 55 | /* set the codec mclk */ |
58 | ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq, | 56 | ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq, |
@@ -83,35 +81,6 @@ static struct snd_soc_jack_pin hs_jack_pins[] = { | |||
83 | }, | 81 | }, |
84 | }; | 82 | }; |
85 | 83 | ||
86 | static int sdp4430_get_power_mode(struct snd_kcontrol *kcontrol, | ||
87 | struct snd_ctl_elem_value *ucontrol) | ||
88 | { | ||
89 | ucontrol->value.integer.value[0] = twl6040_power_mode; | ||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static int sdp4430_set_power_mode(struct snd_kcontrol *kcontrol, | ||
94 | struct snd_ctl_elem_value *ucontrol) | ||
95 | { | ||
96 | if (twl6040_power_mode == ucontrol->value.integer.value[0]) | ||
97 | return 0; | ||
98 | |||
99 | twl6040_power_mode = ucontrol->value.integer.value[0]; | ||
100 | |||
101 | return 1; | ||
102 | } | ||
103 | |||
104 | static const char *power_texts[] = {"Low-Power", "High-Performance"}; | ||
105 | |||
106 | static const struct soc_enum sdp4430_enum[] = { | ||
107 | SOC_ENUM_SINGLE_EXT(2, power_texts), | ||
108 | }; | ||
109 | |||
110 | static const struct snd_kcontrol_new sdp4430_controls[] = { | ||
111 | SOC_ENUM_EXT("TWL6040 Power Mode", sdp4430_enum[0], | ||
112 | sdp4430_get_power_mode, sdp4430_set_power_mode), | ||
113 | }; | ||
114 | |||
115 | /* SDP4430 machine DAPM */ | 84 | /* SDP4430 machine DAPM */ |
116 | static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = { | 85 | static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = { |
117 | SND_SOC_DAPM_MIC("Ext Mic", NULL), | 86 | SND_SOC_DAPM_MIC("Ext Mic", NULL), |
@@ -154,12 +123,6 @@ static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd) | |||
154 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 123 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
155 | int ret; | 124 | int ret; |
156 | 125 | ||
157 | /* Add SDP4430 specific controls */ | ||
158 | ret = snd_soc_add_controls(codec, sdp4430_controls, | ||
159 | ARRAY_SIZE(sdp4430_controls)); | ||
160 | if (ret) | ||
161 | return ret; | ||
162 | |||
163 | /* Add SDP4430 specific widgets */ | 126 | /* Add SDP4430 specific widgets */ |
164 | ret = snd_soc_dapm_new_controls(dapm, sdp4430_twl6040_dapm_widgets, | 127 | ret = snd_soc_dapm_new_controls(dapm, sdp4430_twl6040_dapm_widgets, |
165 | ARRAY_SIZE(sdp4430_twl6040_dapm_widgets)); | 128 | ARRAY_SIZE(sdp4430_twl6040_dapm_widgets)); |
@@ -239,9 +202,6 @@ static int __init sdp4430_soc_init(void) | |||
239 | if (ret) | 202 | if (ret) |
240 | goto err; | 203 | goto err; |
241 | 204 | ||
242 | /* Codec starts in HP mode */ | ||
243 | twl6040_power_mode = 1; | ||
244 | |||
245 | return 0; | 205 | return 0; |
246 | 206 | ||
247 | err: | 207 | err: |