diff options
Diffstat (limited to 'sound/soc/codecs/tlv320aic3x.c')
-rw-r--r-- | sound/soc/codecs/tlv320aic3x.c | 56 |
1 files changed, 21 insertions, 35 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index e5b926883131..6e3f269243e0 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -138,8 +138,7 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = { | |||
138 | static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, | 138 | static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, |
139 | struct snd_ctl_elem_value *ucontrol) | 139 | struct snd_ctl_elem_value *ucontrol) |
140 | { | 140 | { |
141 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 141 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
142 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
143 | struct soc_mixer_control *mc = | 142 | struct soc_mixer_control *mc = |
144 | (struct soc_mixer_control *)kcontrol->private_value; | 143 | (struct soc_mixer_control *)kcontrol->private_value; |
145 | unsigned int reg = mc->reg; | 144 | unsigned int reg = mc->reg; |
@@ -147,10 +146,9 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, | |||
147 | int max = mc->max; | 146 | int max = mc->max; |
148 | unsigned int mask = (1 << fls(max)) - 1; | 147 | unsigned int mask = (1 << fls(max)) - 1; |
149 | unsigned int invert = mc->invert; | 148 | unsigned int invert = mc->invert; |
150 | unsigned short val, val_mask; | 149 | unsigned short val; |
151 | int ret; | 150 | struct snd_soc_dapm_update update; |
152 | struct snd_soc_dapm_path *path; | 151 | int connect, change; |
153 | int found = 0; | ||
154 | 152 | ||
155 | val = (ucontrol->value.integer.value[0] & mask); | 153 | val = (ucontrol->value.integer.value[0] & mask); |
156 | 154 | ||
@@ -158,42 +156,26 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, | |||
158 | if (val) | 156 | if (val) |
159 | val = mask; | 157 | val = mask; |
160 | 158 | ||
159 | connect = !!val; | ||
160 | |||
161 | if (invert) | 161 | if (invert) |
162 | val = mask - val; | 162 | val = mask - val; |
163 | val_mask = mask << shift; | ||
164 | val = val << shift; | ||
165 | |||
166 | mutex_lock(&widget->codec->mutex); | ||
167 | 163 | ||
168 | if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) { | 164 | mask <<= shift; |
169 | /* find dapm widget path assoc with kcontrol */ | 165 | val <<= shift; |
170 | list_for_each_entry(path, &widget->dapm->card->paths, list) { | ||
171 | if (path->kcontrol != kcontrol) | ||
172 | continue; | ||
173 | 166 | ||
174 | /* found, now check type */ | 167 | change = snd_soc_test_bits(codec, val, mask, reg); |
175 | found = 1; | 168 | if (change) { |
176 | if (val) | 169 | update.kcontrol = kcontrol; |
177 | /* new connection */ | 170 | update.reg = reg; |
178 | path->connect = invert ? 0 : 1; | 171 | update.mask = mask; |
179 | else | 172 | update.val = val; |
180 | /* old connection must be powered down */ | ||
181 | path->connect = invert ? 1 : 0; | ||
182 | 173 | ||
183 | dapm_mark_dirty(path->source, "tlv320aic3x source"); | 174 | snd_soc_dapm_mixer_update_power(&codec->dapm, kcontrol, connect, |
184 | dapm_mark_dirty(path->sink, "tlv320aic3x sink"); | 175 | &update); |
185 | |||
186 | break; | ||
187 | } | ||
188 | } | 176 | } |
189 | 177 | ||
190 | mutex_unlock(&widget->codec->mutex); | 178 | return change; |
191 | |||
192 | if (found) | ||
193 | snd_soc_dapm_sync(widget->dapm); | ||
194 | |||
195 | ret = snd_soc_update_bits_locked(widget->codec, reg, val_mask, val); | ||
196 | return ret; | ||
197 | } | 179 | } |
198 | 180 | ||
199 | /* | 181 | /* |
@@ -1492,6 +1474,7 @@ static const struct i2c_device_id aic3x_i2c_id[] = { | |||
1492 | { "tlv320aic3x", AIC3X_MODEL_3X }, | 1474 | { "tlv320aic3x", AIC3X_MODEL_3X }, |
1493 | { "tlv320aic33", AIC3X_MODEL_33 }, | 1475 | { "tlv320aic33", AIC3X_MODEL_33 }, |
1494 | { "tlv320aic3007", AIC3X_MODEL_3007 }, | 1476 | { "tlv320aic3007", AIC3X_MODEL_3007 }, |
1477 | { "tlv320aic3106", AIC3X_MODEL_3X }, | ||
1495 | { } | 1478 | { } |
1496 | }; | 1479 | }; |
1497 | MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); | 1480 | MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); |
@@ -1582,6 +1565,9 @@ static int aic3x_i2c_remove(struct i2c_client *client) | |||
1582 | #if defined(CONFIG_OF) | 1565 | #if defined(CONFIG_OF) |
1583 | static const struct of_device_id tlv320aic3x_of_match[] = { | 1566 | static const struct of_device_id tlv320aic3x_of_match[] = { |
1584 | { .compatible = "ti,tlv320aic3x", }, | 1567 | { .compatible = "ti,tlv320aic3x", }, |
1568 | { .compatible = "ti,tlv320aic33" }, | ||
1569 | { .compatible = "ti,tlv320aic3007" }, | ||
1570 | { .compatible = "ti,tlv320aic3106" }, | ||
1585 | {}, | 1571 | {}, |
1586 | }; | 1572 | }; |
1587 | MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match); | 1573 | MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match); |