diff options
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r-- | sound/soc/codecs/tlv320aic3x.c | 83 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320aic3x.h | 4 |
2 files changed, 81 insertions, 6 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 5708a973a776..ba82ba2a7133 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -85,6 +85,9 @@ struct aic3x_priv { | |||
85 | #define AIC3X_MODEL_33 1 | 85 | #define AIC3X_MODEL_33 1 |
86 | #define AIC3X_MODEL_3007 2 | 86 | #define AIC3X_MODEL_3007 2 |
87 | u16 model; | 87 | u16 model; |
88 | |||
89 | /* Selects the micbias voltage */ | ||
90 | enum aic3x_micbias_voltage micbias_vg; | ||
88 | }; | 91 | }; |
89 | 92 | ||
90 | /* | 93 | /* |
@@ -195,6 +198,37 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, | |||
195 | return ret; | 198 | return ret; |
196 | } | 199 | } |
197 | 200 | ||
201 | /* | ||
202 | * mic bias power on/off share the same register bits with | ||
203 | * output voltage of mic bias. when power on mic bias, we | ||
204 | * need reclaim it to voltage value. | ||
205 | * 0x0 = Powered off | ||
206 | * 0x1 = MICBIAS output is powered to 2.0V, | ||
207 | * 0x2 = MICBIAS output is powered to 2.5V | ||
208 | * 0x3 = MICBIAS output is connected to AVDD | ||
209 | */ | ||
210 | static int mic_bias_event(struct snd_soc_dapm_widget *w, | ||
211 | struct snd_kcontrol *kcontrol, int event) | ||
212 | { | ||
213 | struct snd_soc_codec *codec = w->codec; | ||
214 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | ||
215 | |||
216 | switch (event) { | ||
217 | case SND_SOC_DAPM_POST_PMU: | ||
218 | /* change mic bias voltage to user defined */ | ||
219 | snd_soc_update_bits(codec, MICBIAS_CTRL, | ||
220 | MICBIAS_LEVEL_MASK, | ||
221 | aic3x->micbias_vg << MICBIAS_LEVEL_SHIFT); | ||
222 | break; | ||
223 | |||
224 | case SND_SOC_DAPM_PRE_PMD: | ||
225 | snd_soc_update_bits(codec, MICBIAS_CTRL, | ||
226 | MICBIAS_LEVEL_MASK, 0); | ||
227 | break; | ||
228 | } | ||
229 | return 0; | ||
230 | } | ||
231 | |||
198 | static const char *aic3x_left_dac_mux[] = { "DAC_L1", "DAC_L3", "DAC_L2" }; | 232 | static const char *aic3x_left_dac_mux[] = { "DAC_L1", "DAC_L3", "DAC_L2" }; |
199 | static const char *aic3x_right_dac_mux[] = { "DAC_R1", "DAC_R3", "DAC_R2" }; | 233 | static const char *aic3x_right_dac_mux[] = { "DAC_R1", "DAC_R3", "DAC_R2" }; |
200 | static const char *aic3x_left_hpcom_mux[] = | 234 | static const char *aic3x_left_hpcom_mux[] = |
@@ -596,12 +630,9 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | |||
596 | AIC3X_ASD_INTF_CTRLA, 0, 3, 3, 0), | 630 | AIC3X_ASD_INTF_CTRLA, 0, 3, 3, 0), |
597 | 631 | ||
598 | /* Mic Bias */ | 632 | /* Mic Bias */ |
599 | SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias 2V", | 633 | SND_SOC_DAPM_SUPPLY("Mic Bias", MICBIAS_CTRL, 6, 0, |
600 | MICBIAS_CTRL, 6, 3, 1, 0), | 634 | mic_bias_event, |
601 | SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias 2.5V", | 635 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
602 | MICBIAS_CTRL, 6, 3, 2, 0), | ||
603 | SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias AVDD", | ||
604 | MICBIAS_CTRL, 6, 3, 3, 0), | ||
605 | 636 | ||
606 | /* Output mixers */ | 637 | /* Output mixers */ |
607 | SND_SOC_DAPM_MIXER("Left Line Mixer", SND_SOC_NOPM, 0, 0, | 638 | SND_SOC_DAPM_MIXER("Left Line Mixer", SND_SOC_NOPM, 0, 0, |
@@ -1386,6 +1417,24 @@ static int aic3x_probe(struct snd_soc_codec *codec) | |||
1386 | if (aic3x->model == AIC3X_MODEL_3007) | 1417 | if (aic3x->model == AIC3X_MODEL_3007) |
1387 | snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1); | 1418 | snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1); |
1388 | 1419 | ||
1420 | /* set mic bias voltage */ | ||
1421 | switch (aic3x->micbias_vg) { | ||
1422 | case AIC3X_MICBIAS_2_0V: | ||
1423 | case AIC3X_MICBIAS_2_5V: | ||
1424 | case AIC3X_MICBIAS_AVDDV: | ||
1425 | snd_soc_update_bits(codec, MICBIAS_CTRL, | ||
1426 | MICBIAS_LEVEL_MASK, | ||
1427 | (aic3x->micbias_vg) << MICBIAS_LEVEL_SHIFT); | ||
1428 | break; | ||
1429 | case AIC3X_MICBIAS_OFF: | ||
1430 | /* | ||
1431 | * noting to do. target won't enter here. This is just to avoid | ||
1432 | * compile time warning "warning: enumeration value | ||
1433 | * 'AIC3X_MICBIAS_OFF' not handled in switch" | ||
1434 | */ | ||
1435 | break; | ||
1436 | } | ||
1437 | |||
1389 | aic3x_add_widgets(codec); | 1438 | aic3x_add_widgets(codec); |
1390 | list_add(&aic3x->list, &reset_list); | 1439 | list_add(&aic3x->list, &reset_list); |
1391 | 1440 | ||
@@ -1461,6 +1510,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1461 | struct aic3x_setup_data *ai3x_setup; | 1510 | struct aic3x_setup_data *ai3x_setup; |
1462 | struct device_node *np = i2c->dev.of_node; | 1511 | struct device_node *np = i2c->dev.of_node; |
1463 | int ret; | 1512 | int ret; |
1513 | u32 value; | ||
1464 | 1514 | ||
1465 | aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); | 1515 | aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); |
1466 | if (aic3x == NULL) { | 1516 | if (aic3x == NULL) { |
@@ -1474,6 +1524,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1474 | if (pdata) { | 1524 | if (pdata) { |
1475 | aic3x->gpio_reset = pdata->gpio_reset; | 1525 | aic3x->gpio_reset = pdata->gpio_reset; |
1476 | aic3x->setup = pdata->setup; | 1526 | aic3x->setup = pdata->setup; |
1527 | aic3x->micbias_vg = pdata->micbias_vg; | ||
1477 | } else if (np) { | 1528 | } else if (np) { |
1478 | ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup), | 1529 | ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup), |
1479 | GFP_KERNEL); | 1530 | GFP_KERNEL); |
@@ -1493,6 +1544,26 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1493 | aic3x->setup = ai3x_setup; | 1544 | aic3x->setup = ai3x_setup; |
1494 | } | 1545 | } |
1495 | 1546 | ||
1547 | if (!of_property_read_u32(np, "ai3x-micbias-vg", &value)) { | ||
1548 | switch (value) { | ||
1549 | case 1 : | ||
1550 | aic3x->micbias_vg = AIC3X_MICBIAS_2_0V; | ||
1551 | break; | ||
1552 | case 2 : | ||
1553 | aic3x->micbias_vg = AIC3X_MICBIAS_2_5V; | ||
1554 | break; | ||
1555 | case 3 : | ||
1556 | aic3x->micbias_vg = AIC3X_MICBIAS_AVDDV; | ||
1557 | break; | ||
1558 | default : | ||
1559 | aic3x->micbias_vg = AIC3X_MICBIAS_OFF; | ||
1560 | dev_err(&i2c->dev, "Unsuitable MicBias voltage " | ||
1561 | "found in DT\n"); | ||
1562 | } | ||
1563 | } else { | ||
1564 | aic3x->micbias_vg = AIC3X_MICBIAS_OFF; | ||
1565 | } | ||
1566 | |||
1496 | } else { | 1567 | } else { |
1497 | aic3x->gpio_reset = -1; | 1568 | aic3x->gpio_reset = -1; |
1498 | } | 1569 | } |
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index 6db3c41b0163..e521ac3ddde8 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h | |||
@@ -238,6 +238,10 @@ | |||
238 | /* Default input volume */ | 238 | /* Default input volume */ |
239 | #define DEFAULT_GAIN 0x20 | 239 | #define DEFAULT_GAIN 0x20 |
240 | 240 | ||
241 | /* MICBIAS Control Register */ | ||
242 | #define MICBIAS_LEVEL_SHIFT (6) | ||
243 | #define MICBIAS_LEVEL_MASK (3 << 6) | ||
244 | |||
241 | /* headset detection / button API */ | 245 | /* headset detection / button API */ |
242 | 246 | ||
243 | /* The AIC3x supports detection of stereo headsets (GND + left + right signal) | 247 | /* The AIC3x supports detection of stereo headsets (GND + left + right signal) |