aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2011-06-27 10:03:14 -0400
committerPeter Ujfalusi <peter.ujfalusi@ti.com>2011-07-07 07:23:44 -0400
commitaf958c72af88405501fe61a43f8011614cff29f5 (patch)
tree5ea6d28e39befdd4246d477e83641c5814ec5329
parent7cca606794ceb597e95fd0a0f3a8dcdd51af55e0 (diff)
ASoC: twl6040: Move PLL selection to codec driver
It is better if the selection between the Low power, and High performance PLL is handled within the codec driver, not in machine driver(s) to avoid duplicated code, and also to have consistent tracking of the selected PLL, and the resulting differences in supported sample rates. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-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: