Loading include/sound/soc-dapm.h +4 −0 Original line number Diff line number Diff line Loading @@ -286,6 +286,8 @@ struct device; .info = snd_soc_info_volsw, \ .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ .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) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, \ Loading @@ -300,6 +302,8 @@ struct device; .tlv.p = (tlv_array), \ .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ .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) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_enum_double, \ Loading include/sound/soc.h +2 −1 Original line number Diff line number Diff line Loading @@ -1051,7 +1051,8 @@ struct snd_soc_pcm_runtime { /* mixer control */ struct soc_mixer_control { int min, max, platform_max; unsigned int reg, rreg, shift, rshift; int reg, rreg; unsigned int shift, rshift; unsigned int invert:1; unsigned int autodisable:1; }; Loading sound/soc/codecs/twl4030.c +36 −44 Original line number Diff line number Diff line Loading @@ -46,13 +46,7 @@ /* TWL4030 PMBR1 Register GPIO6 mux bits */ #define TWL4030_GPIO6_PWM0_MUTE(value) ((value & 0x03) << 2) /* Shadow register used by the audio driver */ #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 #define TWL4030_CACHEREGNUM (TWL4030_REG_MISC_SET_2 + 1) /* * twl4030 register cache & default register settings Loading Loading @@ -132,7 +126,6 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { 0x00, /* REG_VIBRA_PWM_SET (0x47) */ 0x00, /* REG_ANAMIC_GAIN (0x48) */ 0x00, /* REG_MISC_SET_2 (0x49) */ 0x00, /* REG_SW_SHADOW (0x4A) - Shadow, non HW register */ }; /* codec private data */ Loading Loading @@ -198,7 +191,6 @@ static int twl4030_write(struct snd_soc_codec *codec, int write_to_reg = 0; twl4030_write_reg_cache(codec, reg, value); if (likely(reg < TWL4030_REG_SW_SHADOW)) { /* Decide if the given register can be written */ switch (reg) { case TWL4030_REG_EAR_CTL: Loading Loading @@ -233,7 +225,7 @@ static int twl4030_write(struct snd_soc_codec *codec, if (write_to_reg) return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); } return 0; } Loading Loading @@ -532,7 +524,7 @@ SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum); /* Handsfree Left virtual mute */ 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 */ static const char *twl4030_handsfreer_texts[] = Loading @@ -548,7 +540,7 @@ SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum); /* Handsfree Right virtual mute */ 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 audio path selection */ Loading sound/soc/soc-dapm.c +28 −18 Original line number Diff line number Diff line Loading @@ -499,18 +499,22 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, int val; struct soc_mixer_control *mc = (struct soc_mixer_control *) w->kcontrol_news[i].private_value; unsigned int reg = mc->reg; int reg = mc->reg; unsigned int shift = mc->shift; int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; if (reg != SND_SOC_NOPM) { val = soc_widget_read(w, reg); val = (val >> shift) & mask; if (invert) val = max - val; p->connect = !!val; } else { p->connect = 0; } } break; case snd_soc_dapm_mux: { Loading Loading @@ -1840,6 +1844,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) */ switch (w->id) { case snd_soc_dapm_siggen: case snd_soc_dapm_vmid: break; case snd_soc_dapm_supply: case snd_soc_dapm_regulator_supply: Loading Loading @@ -2791,7 +2796,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, struct snd_soc_card *card = codec->card; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; unsigned int reg = mc->reg; int reg = mc->reg; unsigned int shift = mc->shift; int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; Loading @@ -2804,7 +2809,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, kcontrol->id.name); 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; else val = dapm_kcontrol_get_value(kcontrol); Loading Loading @@ -2835,7 +2840,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, struct snd_soc_card *card = codec->card; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; unsigned int reg = mc->reg; int reg = mc->reg; unsigned int shift = mc->shift; int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; Loading @@ -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); dapm_kcontrol_set_value(kcontrol, val); change = dapm_kcontrol_set_value(kcontrol, val); if (reg != SND_SOC_NOPM) { mask = mask << shift; val = val << shift; change = snd_soc_test_bits(codec, reg, mask, val); } if (change) { if (reg != SND_SOC_NOPM) { update.kcontrol = kcontrol; update.reg = reg; update.mask = mask; update.val = val; card->update = &update; } soc_dapm_mixer_update_power(card, kcontrol, connect); Loading Loading
include/sound/soc-dapm.h +4 −0 Original line number Diff line number Diff line Loading @@ -286,6 +286,8 @@ struct device; .info = snd_soc_info_volsw, \ .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ .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) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, \ Loading @@ -300,6 +302,8 @@ struct device; .tlv.p = (tlv_array), \ .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ .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) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_enum_double, \ Loading
include/sound/soc.h +2 −1 Original line number Diff line number Diff line Loading @@ -1051,7 +1051,8 @@ struct snd_soc_pcm_runtime { /* mixer control */ struct soc_mixer_control { int min, max, platform_max; unsigned int reg, rreg, shift, rshift; int reg, rreg; unsigned int shift, rshift; unsigned int invert:1; unsigned int autodisable:1; }; Loading
sound/soc/codecs/twl4030.c +36 −44 Original line number Diff line number Diff line Loading @@ -46,13 +46,7 @@ /* TWL4030 PMBR1 Register GPIO6 mux bits */ #define TWL4030_GPIO6_PWM0_MUTE(value) ((value & 0x03) << 2) /* Shadow register used by the audio driver */ #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 #define TWL4030_CACHEREGNUM (TWL4030_REG_MISC_SET_2 + 1) /* * twl4030 register cache & default register settings Loading Loading @@ -132,7 +126,6 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { 0x00, /* REG_VIBRA_PWM_SET (0x47) */ 0x00, /* REG_ANAMIC_GAIN (0x48) */ 0x00, /* REG_MISC_SET_2 (0x49) */ 0x00, /* REG_SW_SHADOW (0x4A) - Shadow, non HW register */ }; /* codec private data */ Loading Loading @@ -198,7 +191,6 @@ static int twl4030_write(struct snd_soc_codec *codec, int write_to_reg = 0; twl4030_write_reg_cache(codec, reg, value); if (likely(reg < TWL4030_REG_SW_SHADOW)) { /* Decide if the given register can be written */ switch (reg) { case TWL4030_REG_EAR_CTL: Loading Loading @@ -233,7 +225,7 @@ static int twl4030_write(struct snd_soc_codec *codec, if (write_to_reg) return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); } return 0; } Loading Loading @@ -532,7 +524,7 @@ SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum); /* Handsfree Left virtual mute */ 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 */ static const char *twl4030_handsfreer_texts[] = Loading @@ -548,7 +540,7 @@ SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum); /* Handsfree Right virtual mute */ 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 audio path selection */ Loading
sound/soc/soc-dapm.c +28 −18 Original line number Diff line number Diff line Loading @@ -499,18 +499,22 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, int val; struct soc_mixer_control *mc = (struct soc_mixer_control *) w->kcontrol_news[i].private_value; unsigned int reg = mc->reg; int reg = mc->reg; unsigned int shift = mc->shift; int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; if (reg != SND_SOC_NOPM) { val = soc_widget_read(w, reg); val = (val >> shift) & mask; if (invert) val = max - val; p->connect = !!val; } else { p->connect = 0; } } break; case snd_soc_dapm_mux: { Loading Loading @@ -1840,6 +1844,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) */ switch (w->id) { case snd_soc_dapm_siggen: case snd_soc_dapm_vmid: break; case snd_soc_dapm_supply: case snd_soc_dapm_regulator_supply: Loading Loading @@ -2791,7 +2796,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, struct snd_soc_card *card = codec->card; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; unsigned int reg = mc->reg; int reg = mc->reg; unsigned int shift = mc->shift; int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; Loading @@ -2804,7 +2809,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, kcontrol->id.name); 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; else val = dapm_kcontrol_get_value(kcontrol); Loading Loading @@ -2835,7 +2840,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, struct snd_soc_card *card = codec->card; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; unsigned int reg = mc->reg; int reg = mc->reg; unsigned int shift = mc->shift; int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; Loading @@ -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); dapm_kcontrol_set_value(kcontrol, val); change = dapm_kcontrol_set_value(kcontrol, val); if (reg != SND_SOC_NOPM) { mask = mask << shift; val = val << shift; change = snd_soc_test_bits(codec, reg, mask, val); } if (change) { if (reg != SND_SOC_NOPM) { update.kcontrol = kcontrol; update.reg = reg; update.mask = mask; update.val = val; card->update = &update; } soc_dapm_mixer_update_power(card, kcontrol, connect); Loading