Merge remote-tracking branch 'asoc/topic/twl4030' into asoc-next
This commit is contained in:
commit
88cb5111e8
|
@ -286,6 +286,8 @@ struct device;
|
||||||
.info = snd_soc_info_volsw, \
|
.info = snd_soc_info_volsw, \
|
||||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
|
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
|
||||||
|
#define SOC_DAPM_SINGLE_VIRT(xname, max) \
|
||||||
|
SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0)
|
||||||
#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
|
#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||||
.info = snd_soc_info_volsw, \
|
.info = snd_soc_info_volsw, \
|
||||||
|
@ -300,6 +302,8 @@ struct device;
|
||||||
.tlv.p = (tlv_array), \
|
.tlv.p = (tlv_array), \
|
||||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
|
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
|
||||||
|
#define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \
|
||||||
|
SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array)
|
||||||
#define SOC_DAPM_ENUM(xname, xenum) \
|
#define SOC_DAPM_ENUM(xname, xenum) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||||
.info = snd_soc_info_enum_double, \
|
.info = snd_soc_info_enum_double, \
|
||||||
|
|
|
@ -1051,7 +1051,8 @@ struct snd_soc_pcm_runtime {
|
||||||
/* mixer control */
|
/* mixer control */
|
||||||
struct soc_mixer_control {
|
struct soc_mixer_control {
|
||||||
int min, max, platform_max;
|
int min, max, platform_max;
|
||||||
unsigned int reg, rreg, shift, rshift;
|
int reg, rreg;
|
||||||
|
unsigned int shift, rshift;
|
||||||
unsigned int invert:1;
|
unsigned int invert:1;
|
||||||
unsigned int autodisable:1;
|
unsigned int autodisable:1;
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,13 +46,7 @@
|
||||||
/* TWL4030 PMBR1 Register GPIO6 mux bits */
|
/* TWL4030 PMBR1 Register GPIO6 mux bits */
|
||||||
#define TWL4030_GPIO6_PWM0_MUTE(value) ((value & 0x03) << 2)
|
#define TWL4030_GPIO6_PWM0_MUTE(value) ((value & 0x03) << 2)
|
||||||
|
|
||||||
/* Shadow register used by the audio driver */
|
#define TWL4030_CACHEREGNUM (TWL4030_REG_MISC_SET_2 + 1)
|
||||||
#define TWL4030_REG_SW_SHADOW 0x4A
|
|
||||||
#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1)
|
|
||||||
|
|
||||||
/* TWL4030_REG_SW_SHADOW (0x4A) Fields */
|
|
||||||
#define TWL4030_HFL_EN 0x01
|
|
||||||
#define TWL4030_HFR_EN 0x02
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* twl4030 register cache & default register settings
|
* twl4030 register cache & default register settings
|
||||||
|
@ -132,7 +126,6 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
|
||||||
0x00, /* REG_VIBRA_PWM_SET (0x47) */
|
0x00, /* REG_VIBRA_PWM_SET (0x47) */
|
||||||
0x00, /* REG_ANAMIC_GAIN (0x48) */
|
0x00, /* REG_ANAMIC_GAIN (0x48) */
|
||||||
0x00, /* REG_MISC_SET_2 (0x49) */
|
0x00, /* REG_MISC_SET_2 (0x49) */
|
||||||
0x00, /* REG_SW_SHADOW (0x4A) - Shadow, non HW register */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* codec private data */
|
/* codec private data */
|
||||||
|
@ -198,42 +191,41 @@ static int twl4030_write(struct snd_soc_codec *codec,
|
||||||
int write_to_reg = 0;
|
int write_to_reg = 0;
|
||||||
|
|
||||||
twl4030_write_reg_cache(codec, reg, value);
|
twl4030_write_reg_cache(codec, reg, value);
|
||||||
if (likely(reg < TWL4030_REG_SW_SHADOW)) {
|
/* Decide if the given register can be written */
|
||||||
/* Decide if the given register can be written */
|
switch (reg) {
|
||||||
switch (reg) {
|
case TWL4030_REG_EAR_CTL:
|
||||||
case TWL4030_REG_EAR_CTL:
|
if (twl4030->earpiece_enabled)
|
||||||
if (twl4030->earpiece_enabled)
|
|
||||||
write_to_reg = 1;
|
|
||||||
break;
|
|
||||||
case TWL4030_REG_PREDL_CTL:
|
|
||||||
if (twl4030->predrivel_enabled)
|
|
||||||
write_to_reg = 1;
|
|
||||||
break;
|
|
||||||
case TWL4030_REG_PREDR_CTL:
|
|
||||||
if (twl4030->predriver_enabled)
|
|
||||||
write_to_reg = 1;
|
|
||||||
break;
|
|
||||||
case TWL4030_REG_PRECKL_CTL:
|
|
||||||
if (twl4030->carkitl_enabled)
|
|
||||||
write_to_reg = 1;
|
|
||||||
break;
|
|
||||||
case TWL4030_REG_PRECKR_CTL:
|
|
||||||
if (twl4030->carkitr_enabled)
|
|
||||||
write_to_reg = 1;
|
|
||||||
break;
|
|
||||||
case TWL4030_REG_HS_GAIN_SET:
|
|
||||||
if (twl4030->hsl_enabled || twl4030->hsr_enabled)
|
|
||||||
write_to_reg = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* All other register can be written */
|
|
||||||
write_to_reg = 1;
|
write_to_reg = 1;
|
||||||
break;
|
break;
|
||||||
}
|
case TWL4030_REG_PREDL_CTL:
|
||||||
if (write_to_reg)
|
if (twl4030->predrivel_enabled)
|
||||||
return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
|
write_to_reg = 1;
|
||||||
value, reg);
|
break;
|
||||||
|
case TWL4030_REG_PREDR_CTL:
|
||||||
|
if (twl4030->predriver_enabled)
|
||||||
|
write_to_reg = 1;
|
||||||
|
break;
|
||||||
|
case TWL4030_REG_PRECKL_CTL:
|
||||||
|
if (twl4030->carkitl_enabled)
|
||||||
|
write_to_reg = 1;
|
||||||
|
break;
|
||||||
|
case TWL4030_REG_PRECKR_CTL:
|
||||||
|
if (twl4030->carkitr_enabled)
|
||||||
|
write_to_reg = 1;
|
||||||
|
break;
|
||||||
|
case TWL4030_REG_HS_GAIN_SET:
|
||||||
|
if (twl4030->hsl_enabled || twl4030->hsr_enabled)
|
||||||
|
write_to_reg = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* All other register can be written */
|
||||||
|
write_to_reg = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if (write_to_reg)
|
||||||
|
return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
|
||||||
|
value, reg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,7 +524,7 @@ SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum);
|
||||||
|
|
||||||
/* Handsfree Left virtual mute */
|
/* Handsfree Left virtual mute */
|
||||||
static const struct snd_kcontrol_new twl4030_dapm_handsfreelmute_control =
|
static const struct snd_kcontrol_new twl4030_dapm_handsfreelmute_control =
|
||||||
SOC_DAPM_SINGLE("Switch", TWL4030_REG_SW_SHADOW, 0, 1, 0);
|
SOC_DAPM_SINGLE_VIRT("Switch", 1);
|
||||||
|
|
||||||
/* Handsfree Right */
|
/* Handsfree Right */
|
||||||
static const char *twl4030_handsfreer_texts[] =
|
static const char *twl4030_handsfreer_texts[] =
|
||||||
|
@ -548,7 +540,7 @@ SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum);
|
||||||
|
|
||||||
/* Handsfree Right virtual mute */
|
/* Handsfree Right virtual mute */
|
||||||
static const struct snd_kcontrol_new twl4030_dapm_handsfreermute_control =
|
static const struct snd_kcontrol_new twl4030_dapm_handsfreermute_control =
|
||||||
SOC_DAPM_SINGLE("Switch", TWL4030_REG_SW_SHADOW, 1, 1, 0);
|
SOC_DAPM_SINGLE_VIRT("Switch", 1);
|
||||||
|
|
||||||
/* Vibra */
|
/* Vibra */
|
||||||
/* Vibra audio path selection */
|
/* Vibra audio path selection */
|
||||||
|
|
|
@ -499,18 +499,22 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
|
||||||
int val;
|
int val;
|
||||||
struct soc_mixer_control *mc = (struct soc_mixer_control *)
|
struct soc_mixer_control *mc = (struct soc_mixer_control *)
|
||||||
w->kcontrol_news[i].private_value;
|
w->kcontrol_news[i].private_value;
|
||||||
unsigned int reg = mc->reg;
|
int reg = mc->reg;
|
||||||
unsigned int shift = mc->shift;
|
unsigned int shift = mc->shift;
|
||||||
int max = mc->max;
|
int max = mc->max;
|
||||||
unsigned int mask = (1 << fls(max)) - 1;
|
unsigned int mask = (1 << fls(max)) - 1;
|
||||||
unsigned int invert = mc->invert;
|
unsigned int invert = mc->invert;
|
||||||
|
|
||||||
val = soc_widget_read(w, reg);
|
if (reg != SND_SOC_NOPM) {
|
||||||
val = (val >> shift) & mask;
|
val = soc_widget_read(w, reg);
|
||||||
if (invert)
|
val = (val >> shift) & mask;
|
||||||
val = max - val;
|
if (invert)
|
||||||
|
val = max - val;
|
||||||
|
p->connect = !!val;
|
||||||
|
} else {
|
||||||
|
p->connect = 0;
|
||||||
|
}
|
||||||
|
|
||||||
p->connect = !!val;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case snd_soc_dapm_mux: {
|
case snd_soc_dapm_mux: {
|
||||||
|
@ -1840,6 +1844,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
|
||||||
*/
|
*/
|
||||||
switch (w->id) {
|
switch (w->id) {
|
||||||
case snd_soc_dapm_siggen:
|
case snd_soc_dapm_siggen:
|
||||||
|
case snd_soc_dapm_vmid:
|
||||||
break;
|
break;
|
||||||
case snd_soc_dapm_supply:
|
case snd_soc_dapm_supply:
|
||||||
case snd_soc_dapm_regulator_supply:
|
case snd_soc_dapm_regulator_supply:
|
||||||
|
@ -2791,7 +2796,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_soc_card *card = codec->card;
|
struct snd_soc_card *card = codec->card;
|
||||||
struct soc_mixer_control *mc =
|
struct soc_mixer_control *mc =
|
||||||
(struct soc_mixer_control *)kcontrol->private_value;
|
(struct soc_mixer_control *)kcontrol->private_value;
|
||||||
unsigned int reg = mc->reg;
|
int reg = mc->reg;
|
||||||
unsigned int shift = mc->shift;
|
unsigned int shift = mc->shift;
|
||||||
int max = mc->max;
|
int max = mc->max;
|
||||||
unsigned int mask = (1 << fls(max)) - 1;
|
unsigned int mask = (1 << fls(max)) - 1;
|
||||||
|
@ -2804,7 +2809,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
|
||||||
kcontrol->id.name);
|
kcontrol->id.name);
|
||||||
|
|
||||||
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
||||||
if (dapm_kcontrol_is_powered(kcontrol))
|
if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM)
|
||||||
val = (snd_soc_read(codec, reg) >> shift) & mask;
|
val = (snd_soc_read(codec, reg) >> shift) & mask;
|
||||||
else
|
else
|
||||||
val = dapm_kcontrol_get_value(kcontrol);
|
val = dapm_kcontrol_get_value(kcontrol);
|
||||||
|
@ -2835,7 +2840,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_soc_card *card = codec->card;
|
struct snd_soc_card *card = codec->card;
|
||||||
struct soc_mixer_control *mc =
|
struct soc_mixer_control *mc =
|
||||||
(struct soc_mixer_control *)kcontrol->private_value;
|
(struct soc_mixer_control *)kcontrol->private_value;
|
||||||
unsigned int reg = mc->reg;
|
int reg = mc->reg;
|
||||||
unsigned int shift = mc->shift;
|
unsigned int shift = mc->shift;
|
||||||
int max = mc->max;
|
int max = mc->max;
|
||||||
unsigned int mask = (1 << fls(max)) - 1;
|
unsigned int mask = (1 << fls(max)) - 1;
|
||||||
|
@ -2857,19 +2862,24 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
||||||
|
|
||||||
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
||||||
|
|
||||||
dapm_kcontrol_set_value(kcontrol, val);
|
change = dapm_kcontrol_set_value(kcontrol, val);
|
||||||
|
|
||||||
mask = mask << shift;
|
if (reg != SND_SOC_NOPM) {
|
||||||
val = val << shift;
|
mask = mask << shift;
|
||||||
|
val = val << shift;
|
||||||
|
|
||||||
|
change = snd_soc_test_bits(codec, reg, mask, val);
|
||||||
|
}
|
||||||
|
|
||||||
change = snd_soc_test_bits(codec, reg, mask, val);
|
|
||||||
if (change) {
|
if (change) {
|
||||||
update.kcontrol = kcontrol;
|
if (reg != SND_SOC_NOPM) {
|
||||||
update.reg = reg;
|
update.kcontrol = kcontrol;
|
||||||
update.mask = mask;
|
update.reg = reg;
|
||||||
update.val = val;
|
update.mask = mask;
|
||||||
|
update.val = val;
|
||||||
|
|
||||||
card->update = &update;
|
card->update = &update;
|
||||||
|
}
|
||||||
|
|
||||||
soc_dapm_mixer_update_power(card, kcontrol, connect);
|
soc_dapm_mixer_update_power(card, kcontrol, connect);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue