aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/twl6040.c110
-rw-r--r--sound/soc/codecs/twl6040.h1
-rw-r--r--sound/soc/omap/sdp4430.c50
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 */
215static unsigned int lp_rates[] = {
216 8000,
217 11250,
218 16000,
219 22500,
220 32000,
221 44100,
222 48000,
223 88200,
224 96000,
225};
226
227static struct snd_pcm_hw_constraint_list lp_constraints = {
228 .count = ARRAY_SIZE(lp_rates),
229 .list = lp_rates,
230};
231
232static unsigned int hp_rates[] = {
233 8000,
234 16000,
235 32000,
236 48000,
237 96000,
238};
239
240static 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
1084static 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
1095static 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
1110int 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}
1119EXPORT_SYMBOL_GPL(twl6040_get_clk_id);
1120
1052static const struct snd_kcontrol_new twl6040_snd_controls[] = { 1121static 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
1076static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { 1148static 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
1294static unsigned int lp_rates[] = {
1295 8000,
1296 11250,
1297 16000,
1298 22500,
1299 32000,
1300 44100,
1301 48000,
1302 88200,
1303 96000,
1304};
1305
1306static struct snd_pcm_hw_constraint_list lp_constraints = {
1307 .count = ARRAY_SIZE(lp_rates),
1308 .list = lp_rates,
1309};
1310
1311static unsigned int hp_rates[] = {
1312 8000,
1313 16000,
1314 32000,
1315 48000,
1316 96000,
1317};
1318
1319static struct snd_pcm_hw_constraint_list hp_constraints = {
1320 .count = ARRAY_SIZE(hp_rates),
1321 .list = hp_rates,
1322};
1323
1324static int twl6040_startup(struct snd_pcm_substream *substream, 1364static 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
25void twl6040_hs_jack_detect(struct snd_soc_codec *codec, 25void 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);
27int 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
39static int twl6040_power_mode;
40
41static int sdp4430_hw_params(struct snd_pcm_substream *substream, 39static 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
86static 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
93static 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
104static const char *power_texts[] = {"Low-Power", "High-Performance"};
105
106static const struct soc_enum sdp4430_enum[] = {
107 SOC_ENUM_SINGLE_EXT(2, power_texts),
108};
109
110static 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 */
116static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = { 85static 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
247err: 207err: