aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2015-05-01 12:02:44 -0400
committerMark Brown <broonie@kernel.org>2015-05-06 12:33:12 -0400
commit0eb93ef04b2641d4140e11d6b1f2f3841edd9a7a (patch)
treeb3138775b42a075612ff2793c1b5c314ce1e5945
parentd714f97c5b8c4c5da56b89a7289acb3f12ef7abb (diff)
ASoC: lm4857: Use DAPM demux
Use a DAPM auto-disable demux to model the Mode control which affects the routing of the input pin to the output pins. This allows us to remove the custom code for handling the Mode control. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/lm4857.c100
1 files changed, 26 insertions, 74 deletions
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 79ad4cbdcdd4..dac9165ea9ab 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -23,11 +23,6 @@
23#include <sound/soc.h> 23#include <sound/soc.h>
24#include <sound/tlv.h> 24#include <sound/tlv.h>
25 25
26struct lm4857 {
27 struct regmap *regmap;
28 uint8_t mode;
29};
30
31static const struct reg_default lm4857_default_regs[] = { 26static const struct reg_default lm4857_default_regs[] = {
32 { 0x0, 0x00 }, 27 { 0x0, 0x00 },
33 { 0x1, 0x00 }, 28 { 0x1, 0x00 },
@@ -46,64 +41,33 @@ static const struct reg_default lm4857_default_regs[] = {
46#define LM4857_WAKEUP 5 41#define LM4857_WAKEUP 5
47#define LM4857_EPGAIN 4 42#define LM4857_EPGAIN 4
48 43
49static int lm4857_get_mode(struct snd_kcontrol *kcontrol, 44static const unsigned int lm4857_mode_values[] = {
50 struct snd_ctl_elem_value *ucontrol) 45 0,
51{ 46 6,
52 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 47 7,
53 struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec); 48 8,
54 49 9,
55 ucontrol->value.integer.value[0] = lm4857->mode; 50};
56
57 return 0;
58}
59
60static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
61 struct snd_ctl_elem_value *ucontrol)
62{
63 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
64 struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
65 uint8_t value = ucontrol->value.integer.value[0];
66
67 lm4857->mode = value;
68
69 if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
70 regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, value + 6);
71
72 return 1;
73}
74
75static int lm4857_set_bias_level(struct snd_soc_codec *codec,
76 enum snd_soc_bias_level level)
77{
78 struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
79
80 switch (level) {
81 case SND_SOC_BIAS_ON:
82 regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F,
83 lm4857->mode + 6);
84 break;
85 case SND_SOC_BIAS_STANDBY:
86 regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, 0);
87 break;
88 default:
89 break;
90 }
91
92 return 0;
93}
94 51
95static const char *lm4857_mode[] = { 52static const char * const lm4857_mode_texts[] = {
53 "Off",
96 "Earpiece", 54 "Earpiece",
97 "Loudspeaker", 55 "Loudspeaker",
98 "Loudspeaker + Headphone", 56 "Loudspeaker + Headphone",
99 "Headphone", 57 "Headphone",
100}; 58};
101 59
102static SOC_ENUM_SINGLE_EXT_DECL(lm4857_mode_enum, lm4857_mode); 60static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(lm4857_mode_enum,
61 LM4857_CTRL, 0, 0xf, lm4857_mode_texts, lm4857_mode_values);
62
63static const struct snd_kcontrol_new lm4857_mode_ctrl =
64 SOC_DAPM_ENUM("Mode", lm4857_mode_enum);
103 65
104static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = { 66static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = {
105 SND_SOC_DAPM_INPUT("IN"), 67 SND_SOC_DAPM_INPUT("IN"),
106 68
69 SND_SOC_DAPM_DEMUX("Mode", SND_SOC_NOPM, 0, 0, &lm4857_mode_ctrl),
70
107 SND_SOC_DAPM_OUTPUT("LS"), 71 SND_SOC_DAPM_OUTPUT("LS"),
108 SND_SOC_DAPM_OUTPUT("HP"), 72 SND_SOC_DAPM_OUTPUT("HP"),
109 SND_SOC_DAPM_OUTPUT("EP"), 73 SND_SOC_DAPM_OUTPUT("EP"),
@@ -125,24 +89,18 @@ static const struct snd_kcontrol_new lm4857_controls[] = {
125 LM4857_WAKEUP, 1, 0), 89 LM4857_WAKEUP, 1, 0),
126 SOC_SINGLE("Earpiece 6dB Playback Switch", LM4857_CTRL, 90 SOC_SINGLE("Earpiece 6dB Playback Switch", LM4857_CTRL,
127 LM4857_EPGAIN, 1, 0), 91 LM4857_EPGAIN, 1, 0),
128
129 SOC_ENUM_EXT("Mode", lm4857_mode_enum,
130 lm4857_get_mode, lm4857_set_mode),
131}; 92};
132 93
133/* There is a demux between the input signal and the output signals.
134 * Currently there is no easy way to model it in ASoC and since it does not make
135 * much of a difference in practice simply connect the input direclty to the
136 * outputs. */
137static const struct snd_soc_dapm_route lm4857_routes[] = { 94static const struct snd_soc_dapm_route lm4857_routes[] = {
138 {"LS", NULL, "IN"}, 95 { "Mode", NULL, "IN" },
139 {"HP", NULL, "IN"}, 96 { "LS", "Loudspeaker", "Mode" },
140 {"EP", NULL, "IN"}, 97 { "LS", "Loudspeaker + Headphone", "Mode" },
98 { "HP", "Headphone", "Mode" },
99 { "HP", "Loudspeaker + Headphone", "Mode" },
100 { "EP", "Earpiece", "Mode" },
141}; 101};
142 102
143static struct snd_soc_codec_driver soc_codec_dev_lm4857 = { 103static struct snd_soc_codec_driver soc_codec_dev_lm4857 = {
144 .set_bias_level = lm4857_set_bias_level,
145
146 .controls = lm4857_controls, 104 .controls = lm4857_controls,
147 .num_controls = ARRAY_SIZE(lm4857_controls), 105 .num_controls = ARRAY_SIZE(lm4857_controls),
148 .dapm_widgets = lm4857_dapm_widgets, 106 .dapm_widgets = lm4857_dapm_widgets,
@@ -165,17 +123,11 @@ static const struct regmap_config lm4857_regmap_config = {
165static int lm4857_i2c_probe(struct i2c_client *i2c, 123static int lm4857_i2c_probe(struct i2c_client *i2c,
166 const struct i2c_device_id *id) 124 const struct i2c_device_id *id)
167{ 125{
168 struct lm4857 *lm4857; 126 struct regmap *regmap;
169
170 lm4857 = devm_kzalloc(&i2c->dev, sizeof(*lm4857), GFP_KERNEL);
171 if (!lm4857)
172 return -ENOMEM;
173
174 i2c_set_clientdata(i2c, lm4857);
175 127
176 lm4857->regmap = devm_regmap_init_i2c(i2c, &lm4857_regmap_config); 128 regmap = devm_regmap_init_i2c(i2c, &lm4857_regmap_config);
177 if (IS_ERR(lm4857->regmap)) 129 if (IS_ERR(regmap))
178 return PTR_ERR(lm4857->regmap); 130 return PTR_ERR(regmap);
179 131
180 return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0); 132 return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0);
181} 133}