Commit 315472d5 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'asoc/topic/tlv320aic3x' into asoc-next

parents 56b3f31f e2e8bfdf
...@@ -11,6 +11,12 @@ Optional properties: ...@@ -11,6 +11,12 @@ Optional properties:
- gpio-reset - gpio pin number used for codec reset - gpio-reset - gpio pin number used for codec reset
- ai3x-gpio-func - <array of 2 int> - AIC3X_GPIO1 & AIC3X_GPIO2 Functionality - ai3x-gpio-func - <array of 2 int> - AIC3X_GPIO1 & AIC3X_GPIO2 Functionality
- ai3x-micbias-vg - MicBias Voltage required.
1 - MICBIAS output is powered to 2.0V,
2 - MICBIAS output is powered to 2.5V,
3 - MICBIAS output is connected to AVDD,
If this node is not mentioned or if the value is incorrect, then MicBias
is powered down.
Example: Example:
......
...@@ -46,6 +46,13 @@ enum { ...@@ -46,6 +46,13 @@ enum {
AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ = 15 AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ = 15
}; };
enum aic3x_micbias_voltage {
AIC3X_MICBIAS_OFF = 0,
AIC3X_MICBIAS_2_0V = 1,
AIC3X_MICBIAS_2_5V = 2,
AIC3X_MICBIAS_AVDDV = 3,
};
struct aic3x_setup_data { struct aic3x_setup_data {
unsigned int gpio_func[2]; unsigned int gpio_func[2];
}; };
...@@ -53,6 +60,9 @@ struct aic3x_setup_data { ...@@ -53,6 +60,9 @@ struct aic3x_setup_data {
struct aic3x_pdata { struct aic3x_pdata {
int gpio_reset; /* < 0 if not used */ int gpio_reset; /* < 0 if not used */
struct aic3x_setup_data *setup; struct aic3x_setup_data *setup;
/* Selects the micbias voltage */
enum aic3x_micbias_voltage micbias_vg;
}; };
#endif #endif
...@@ -85,6 +85,9 @@ struct aic3x_priv { ...@@ -85,6 +85,9 @@ struct aic3x_priv {
#define AIC3X_MODEL_33 1 #define AIC3X_MODEL_33 1
#define AIC3X_MODEL_3007 2 #define AIC3X_MODEL_3007 2
u16 model; u16 model;
/* Selects the micbias voltage */
enum aic3x_micbias_voltage micbias_vg;
}; };
/* /*
...@@ -195,6 +198,37 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, ...@@ -195,6 +198,37 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
return ret; return ret;
} }
/*
* mic bias power on/off share the same register bits with
* output voltage of mic bias. when power on mic bias, we
* need reclaim it to voltage value.
* 0x0 = Powered off
* 0x1 = MICBIAS output is powered to 2.0V,
* 0x2 = MICBIAS output is powered to 2.5V
* 0x3 = MICBIAS output is connected to AVDD
*/
static int mic_bias_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
/* change mic bias voltage to user defined */
snd_soc_update_bits(codec, MICBIAS_CTRL,
MICBIAS_LEVEL_MASK,
aic3x->micbias_vg << MICBIAS_LEVEL_SHIFT);
break;
case SND_SOC_DAPM_PRE_PMD:
snd_soc_update_bits(codec, MICBIAS_CTRL,
MICBIAS_LEVEL_MASK, 0);
break;
}
return 0;
}
static const char *aic3x_left_dac_mux[] = { "DAC_L1", "DAC_L3", "DAC_L2" }; static const char *aic3x_left_dac_mux[] = { "DAC_L1", "DAC_L3", "DAC_L2" };
static const char *aic3x_right_dac_mux[] = { "DAC_R1", "DAC_R3", "DAC_R2" }; static const char *aic3x_right_dac_mux[] = { "DAC_R1", "DAC_R3", "DAC_R2" };
static const char *aic3x_left_hpcom_mux[] = static const char *aic3x_left_hpcom_mux[] =
...@@ -596,12 +630,9 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { ...@@ -596,12 +630,9 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
AIC3X_ASD_INTF_CTRLA, 0, 3, 3, 0), AIC3X_ASD_INTF_CTRLA, 0, 3, 3, 0),
/* Mic Bias */ /* Mic Bias */
SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias 2V", SND_SOC_DAPM_SUPPLY("Mic Bias", MICBIAS_CTRL, 6, 0,
MICBIAS_CTRL, 6, 3, 1, 0), mic_bias_event,
SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias 2.5V", SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
MICBIAS_CTRL, 6, 3, 2, 0),
SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias AVDD",
MICBIAS_CTRL, 6, 3, 3, 0),
/* Output mixers */ /* Output mixers */
SND_SOC_DAPM_MIXER("Left Line Mixer", SND_SOC_NOPM, 0, 0, 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,6 +1417,24 @@ static int aic3x_probe(struct snd_soc_codec *codec)
if (aic3x->model == AIC3X_MODEL_3007) if (aic3x->model == AIC3X_MODEL_3007)
snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1); snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
/* set mic bias voltage */
switch (aic3x->micbias_vg) {
case AIC3X_MICBIAS_2_0V:
case AIC3X_MICBIAS_2_5V:
case AIC3X_MICBIAS_AVDDV:
snd_soc_update_bits(codec, MICBIAS_CTRL,
MICBIAS_LEVEL_MASK,
(aic3x->micbias_vg) << MICBIAS_LEVEL_SHIFT);
break;
case AIC3X_MICBIAS_OFF:
/*
* noting to do. target won't enter here. This is just to avoid
* compile time warning "warning: enumeration value
* 'AIC3X_MICBIAS_OFF' not handled in switch"
*/
break;
}
aic3x_add_widgets(codec); aic3x_add_widgets(codec);
list_add(&aic3x->list, &reset_list); list_add(&aic3x->list, &reset_list);
...@@ -1461,6 +1510,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, ...@@ -1461,6 +1510,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
struct aic3x_setup_data *ai3x_setup; struct aic3x_setup_data *ai3x_setup;
struct device_node *np = i2c->dev.of_node; struct device_node *np = i2c->dev.of_node;
int ret; int ret;
u32 value;
aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL);
if (aic3x == NULL) { if (aic3x == NULL) {
...@@ -1474,6 +1524,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, ...@@ -1474,6 +1524,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
if (pdata) { if (pdata) {
aic3x->gpio_reset = pdata->gpio_reset; aic3x->gpio_reset = pdata->gpio_reset;
aic3x->setup = pdata->setup; aic3x->setup = pdata->setup;
aic3x->micbias_vg = pdata->micbias_vg;
} else if (np) { } else if (np) {
ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup), ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup),
GFP_KERNEL); GFP_KERNEL);
...@@ -1493,6 +1544,26 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, ...@@ -1493,6 +1544,26 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
aic3x->setup = ai3x_setup; aic3x->setup = ai3x_setup;
} }
if (!of_property_read_u32(np, "ai3x-micbias-vg", &value)) {
switch (value) {
case 1 :
aic3x->micbias_vg = AIC3X_MICBIAS_2_0V;
break;
case 2 :
aic3x->micbias_vg = AIC3X_MICBIAS_2_5V;
break;
case 3 :
aic3x->micbias_vg = AIC3X_MICBIAS_AVDDV;
break;
default :
aic3x->micbias_vg = AIC3X_MICBIAS_OFF;
dev_err(&i2c->dev, "Unsuitable MicBias voltage "
"found in DT\n");
}
} else {
aic3x->micbias_vg = AIC3X_MICBIAS_OFF;
}
} else { } else {
aic3x->gpio_reset = -1; aic3x->gpio_reset = -1;
} }
......
...@@ -238,6 +238,10 @@ ...@@ -238,6 +238,10 @@
/* Default input volume */ /* Default input volume */
#define DEFAULT_GAIN 0x20 #define DEFAULT_GAIN 0x20
/* MICBIAS Control Register */
#define MICBIAS_LEVEL_SHIFT (6)
#define MICBIAS_LEVEL_MASK (3 << 6)
/* headset detection / button API */ /* headset detection / button API */
/* The AIC3x supports detection of stereo headsets (GND + left + right signal) /* The AIC3x supports detection of stereo headsets (GND + left + right signal)
......
...@@ -116,9 +116,9 @@ static const struct snd_soc_dapm_route audio_map[] = { ...@@ -116,9 +116,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Line Out", NULL, "RLOUT"}, {"Line Out", NULL, "RLOUT"},
/* Mic connected to (MIC3L | MIC3R) */ /* Mic connected to (MIC3L | MIC3R) */
{"MIC3L", NULL, "Mic Bias 2V"}, {"MIC3L", NULL, "Mic Bias"},
{"MIC3R", NULL, "Mic Bias 2V"}, {"MIC3R", NULL, "Mic Bias"},
{"Mic Bias 2V", NULL, "Mic Jack"}, {"Mic Bias", NULL, "Mic Jack"},
/* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */ /* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */
{"LINE1L", NULL, "Line In"}, {"LINE1L", NULL, "Line In"},
......
...@@ -230,8 +230,8 @@ static const struct snd_soc_dapm_route audio_map[] = { ...@@ -230,8 +230,8 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Ext Spk", NULL, "LLOUT"}, {"Ext Spk", NULL, "LLOUT"},
{"Ext Spk", NULL, "RLOUT"}, {"Ext Spk", NULL, "RLOUT"},
{"DMic Rate 64", NULL, "Mic Bias 2V"}, {"DMic Rate 64", NULL, "Mic Bias"},
{"Mic Bias 2V", NULL, "DMic"}, {"Mic Bias", NULL, "DMic"},
}; };
static const char *spk_function[] = {"Off", "On"}; static const char *spk_function[] = {"Off", "On"};
......
...@@ -248,16 +248,16 @@ static const struct snd_soc_dapm_route audio_map[] = { ...@@ -248,16 +248,16 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"FM Transmitter", NULL, "LLOUT"}, {"FM Transmitter", NULL, "LLOUT"},
{"FM Transmitter", NULL, "RLOUT"}, {"FM Transmitter", NULL, "RLOUT"},
{"DMic Rate 64", NULL, "Mic Bias 2V"}, {"DMic Rate 64", NULL, "Mic Bias"},
{"Mic Bias 2V", NULL, "DMic"}, {"Mic Bias", NULL, "DMic"},
}; };
static const struct snd_soc_dapm_route audio_mapb[] = { static const struct snd_soc_dapm_route audio_mapb[] = {
{"b LINE2R", NULL, "MONO_LOUT"}, {"b LINE2R", NULL, "MONO_LOUT"},
{"Earphone", NULL, "b HPLOUT"}, {"Earphone", NULL, "b HPLOUT"},
{"LINE1L", NULL, "b Mic Bias 2.5V"}, {"LINE1L", NULL, "b Mic Bias"},
{"b Mic Bias 2.5V", NULL, "HS Mic"} {"b Mic Bias", NULL, "HS Mic"}
}; };
static const char *spk_function[] = {"Off", "On"}; static const char *spk_function[] = {"Off", "On"};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment