[alsa-devel] [RFC 00/12] Combining snd_soc_*_volsw/volsw_2r

Hello Mark,
This series will combine the snd_soc_*_volsw, and snd_soc_*_volsw_2r callbacks.
We are going to drop the volsw_r2 callbacks, and merge the support to the _volsw functions. In order to achieve this, the macros need to be adjusted, and also the drivers, which were not using the macros to construct the soc_mixer_control needed to be changed, so I'm not going to introduce any breakage, inconsistency.
This has been suggested in this thread: http://mailman.alsa-project.org/pipermail/alsa-devel/2011-September/044287.h...
By Mark in this mail (I hope I did not misunderstood it): http://mailman.alsa-project.org/pipermail/alsa-devel/2011-September/044343.h...
The use of the existing macros will not change, but underneath we are not going to have two sets of functions for single, or double mixer controls.
I think the last 3 patch can be squashed, I did not wanted to touch the core, and a codec driver in a same patch.
Generated on top of: git://opensource.wolfsonmicro.com/linux-2.6-asoc, for-3.2 branch
Regards, Peter --- Peter Ujfalusi (12): ASoC: core: Introduce SOC_DOUBLE_VALUE macro ASoC: core: Introduce SOC_DOUBLE_R_VALUE macro ASoC: Consolidate use of controls with custom get/put function ASoC: twl6040: Simplify custom get_volsw callback ASoC: twl6040: Simplify custom put_volsw callback ASoC: twl6040: Prepare for core put_volsw/volsw_2r merger ASoC: core: Change SOC_SINGLE/DOUBLE_VALUE representation ASoC: core: Combine snd_soc_info_volsw/info_volsw_2r functions ASoC: core: Combine snd_soc_get_volsw/get_volsw_2r functions ASoC: core: Combine snd_soc_out_volsw/put_volsw_2r functions ASoC: twl6040: Simply call snd_soc_put_volsw form the custom code ASoC: core: Remove snd_soc_put_volsw_2r definition
include/sound/soc.h | 82 +++++++++++---------- sound/soc/codecs/tlv320aic23.c | 14 +--- sound/soc/codecs/twl4030.c | 48 +++--------- sound/soc/codecs/twl6040.c | 71 ++++-------------- sound/soc/codecs/wm8350.c | 39 ++++------ sound/soc/codecs/wm8580.c | 36 +++------ sound/soc/codecs/wm_hubs.c | 18 +--- sound/soc/soc-core.c | 161 +++++++++------------------------------- 8 files changed, 142 insertions(+), 327 deletions(-)

With the new macro we can remove duplicated code for the SOC_DOUBLE type of controls. We can also remap the SOC_SINGLE_VALUE macro to SOC_DOUBLE_VALUE
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- include/sound/soc.h | 34 ++++++++++++++++------------------ 1 files changed, 16 insertions(+), 18 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index a4dc699..3d7c7f7 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -28,10 +28,12 @@ /* * Convenience kcontrol builders */ -#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \ +#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .shift = xshift, .rshift = xshift, .max = xmax, \ - .platform_max = xmax, .invert = xinvert}) + {.reg = xreg, .shift = shift_left, .rshift = shift_right, \ + .max = xmax, .platform_max = xmax, .invert = xinvert}) +#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \ + SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert) #define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert}) @@ -48,13 +50,12 @@ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ .put = snd_soc_put_volsw, \ .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } -#define SOC_DOUBLE(xname, xreg, shift_left, shift_right, xmax, xinvert) \ +#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ .put = snd_soc_put_volsw, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .shift = shift_left, .rshift = shift_right, \ - .max = xmax, .platform_max = xmax, .invert = xinvert} } + .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ + max, invert) } #define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .info = snd_soc_info_volsw_2r, \ @@ -62,16 +63,15 @@ .private_value = (unsigned long)&(struct soc_mixer_control) \ {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ .max = xmax, .platform_max = xmax, .invert = xinvert} } -#define SOC_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert, tlv_array) \ +#define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ .put = snd_soc_put_volsw, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .shift = shift_left, .rshift = shift_right,\ - .max = xmax, .platform_max = xmax, .invert = xinvert} } + .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ + max, invert) } #define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -121,14 +121,13 @@ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) } -#define SOC_DOUBLE_EXT(xname, xreg, shift_left, shift_right, xmax, xinvert,\ +#define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\ xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .shift = shift_left, .rshift = shift_right, \ - .max = xmax, .platform_max = xmax, .invert = xinvert} } + .private_value = \ + SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert) } #define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -146,9 +145,8 @@ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .shift = shift_left, .rshift = shift_right, \ - .max = xmax, .platform_max = xmax, .invert = xinvert} } + .private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \ + xmax, xinvert) } #define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \

With the new macro we can remove duplicated code for the SOC_DOUBLE_R type of controls.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- include/sound/soc.h | 19 ++++++++++--------- 1 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 3d7c7f7..9d0524a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -37,6 +37,10 @@ #define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert}) +#define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmax, xinvert) \ + ((unsigned long)&(struct soc_mixer_control) \ + {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ + .max = xmax, .platform_max = xmax, .invert = xinvert}) #define SOC_SINGLE(xname, reg, shift, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ @@ -60,9 +64,8 @@ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .info = snd_soc_info_volsw_2r, \ .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ - .max = xmax, .platform_max = xmax, .invert = xinvert} } + .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ + xmax, xinvert) } #define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -79,9 +82,8 @@ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw_2r, \ .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ - .max = xmax, .platform_max = xmax, .invert = xinvert} } + .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ + xmax, xinvert) } #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ @@ -155,9 +157,8 @@ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw_2r, \ .get = xhandler_get, .put = xhandler_put, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ - .max = xmax, .platform_max = xmax, .invert = xinvert} } + .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ + xmax, xinvert) } #define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_bool_ext, \

Use the macros for controls require custom get/put function. This is to make sure that the soc_mixer_control is used consistently among the drivers.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com Cc: Arun KS arunks@mistralsolutions.com Cc: Misael Lopez Cruz misael.lopez@ti.com --- sound/soc/codecs/tlv320aic23.c | 14 ++--------- sound/soc/codecs/twl4030.c | 48 ++++++++++------------------------------ sound/soc/codecs/twl6040.c | 37 +++++------------------------- sound/soc/codecs/wm8350.c | 39 ++++++++++++-------------------- sound/soc/codecs/wm8580.c | 36 ++++++++++-------------------- sound/soc/codecs/wm_hubs.c | 18 ++++---------- 6 files changed, 53 insertions(+), 139 deletions(-)
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 33bb52f..c3a4bb2 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -159,15 +159,6 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
}
-#define SOC_TLV320AIC23_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, .get = snd_soc_tlv320aic23_get_volsw,\ - .put = snd_soc_tlv320aic23_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } - static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = { SOC_DOUBLE_R_TLV("Digital Playback Volume", TLV320AIC23_LCHNVOL, TLV320AIC23_RCHNVOL, 0, 127, 0, out_gain_tlv), @@ -178,8 +169,9 @@ static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = { TLV320AIC23_RINVOL, 0, 31, 0, input_gain_tlv), SOC_SINGLE("Mic Input Switch", TLV320AIC23_ANLG, 1, 1, 1), SOC_SINGLE("Mic Booster Switch", TLV320AIC23_ANLG, 0, 1, 0), - SOC_TLV320AIC23_SINGLE_TLV("Sidetone Volume", TLV320AIC23_ANLG, - 6, 4, 0, sidetone_vol_tlv), + SOC_SINGLE_EXT_TLV("Sidetone Volume", TLV320AIC23_ANLG, 6, 4, 0, + snd_soc_tlv320aic23_get_volsw, + snd_soc_tlv320aic23_put_volsw, sidetone_vol_tlv), SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph), };
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 71674be..7c244cd 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -863,34 +863,6 @@ static int digimic_event(struct snd_soc_dapm_widget *w, * Inverting not going to help with these. * Custom volsw and volsw_2r get/put functions to handle these gain bits. */ -#define SOC_DOUBLE_TLV_TWL4030(xname, xreg, shift_left, shift_right, xmax,\ - xinvert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw_twl4030, \ - .put = snd_soc_put_volsw_twl4030, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .shift = shift_left, .rshift = shift_right,\ - .max = xmax, .invert = xinvert} } -#define SOC_DOUBLE_R_TLV_TWL4030(xname, reg_left, reg_right, xshift, xmax,\ - xinvert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_2r, \ - .get = snd_soc_get_volsw_r2_twl4030,\ - .put = snd_soc_put_volsw_r2_twl4030, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ - .rshift = xshift, .max = xmax, .invert = xinvert} } -#define SOC_SINGLE_TLV_TWL4030(xname, xreg, xshift, xmax, xinvert, tlv_array) \ - SOC_DOUBLE_TLV_TWL4030(xname, xreg, xshift, xshift, xmax, \ - xinvert, tlv_array) - static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1197,19 +1169,23 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = { TWL4030_REG_VDL_APGA_CTL, 1, 1, 0),
/* Separate output gain controls */ - SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume", + SOC_DOUBLE_R_EXT_TLV("PreDriv Playback Volume", TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL, - 4, 3, 0, output_tvl), + 4, 3, 0, snd_soc_get_volsw_r2_twl4030, + snd_soc_put_volsw_r2_twl4030, output_tvl),
- SOC_DOUBLE_TLV_TWL4030("Headset Playback Volume", - TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, output_tvl), + SOC_DOUBLE_EXT_TLV("Headset Playback Volume", + TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, snd_soc_get_volsw_twl4030, + snd_soc_put_volsw_twl4030, output_tvl),
- SOC_DOUBLE_R_TLV_TWL4030("Carkit Playback Volume", + SOC_DOUBLE_R_EXT_TLV("Carkit Playback Volume", TWL4030_REG_PRECKL_CTL, TWL4030_REG_PRECKR_CTL, - 4, 3, 0, output_tvl), + 4, 3, 0, snd_soc_get_volsw_r2_twl4030, + snd_soc_put_volsw_r2_twl4030, output_tvl),
- SOC_SINGLE_TLV_TWL4030("Earpiece Playback Volume", - TWL4030_REG_EAR_CTL, 4, 3, 0, output_ear_tvl), + SOC_SINGLE_EXT_TLV("Earpiece Playback Volume", + TWL4030_REG_EAR_CTL, 4, 3, 0, snd_soc_get_volsw_twl4030, + snd_soc_put_volsw_twl4030, output_ear_tvl),
/* Common capture gain controls */ SOC_DOUBLE_R_TLV("TX1 Digital Capture Volume", diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index efcb28b..7e1c4c2 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -814,33 +814,6 @@ static int twl6040_get_volsw(struct snd_kcontrol *kcontrol, return snd_soc_get_volsw(kcontrol, ucontrol); }
-/* double control with volume update */ -#define SOC_TWL6040_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax,\ - xinvert, tlv_array)\ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, .get = twl6040_get_volsw, \ - .put = twl6040_put_volsw, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .shift = shift_left, .rshift = shift_right,\ - .max = xmax, .platform_max = xmax, .invert = xinvert} } - -/* double control with volume update */ -#define SOC_TWL6040_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax,\ - xinvert, tlv_array)\ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ - SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_2r, \ - .get = twl6040_get_volsw, .put = twl6040_put_volsw, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ - .rshift = xshift, .max = xmax, .invert = xinvert}, } - static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1070,10 +1043,12 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = { TWL6040_REG_LINEGAIN, 0, 3, 7, 0, afm_amp_tlv),
/* Playback gains */ - SOC_TWL6040_DOUBLE_TLV("Headset Playback Volume", - TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv), - SOC_TWL6040_DOUBLE_R_TLV("Handsfree Playback Volume", - TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv), + SOC_DOUBLE_EXT_TLV("Headset Playback Volume", + TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, twl6040_get_volsw, + twl6040_put_volsw, hs_tlv), + SOC_DOUBLE_R_EXT_TLV("Handsfree Playback Volume", + TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, + twl6040_get_volsw, twl6040_put_volsw, hf_tlv), SOC_SINGLE_TLV("Earphone Playback Volume", TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 6d6dc9e..50ea9d7 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -395,20 +395,6 @@ static int wm8350_get_volsw_2r(struct snd_kcontrol *kcontrol, return snd_soc_get_volsw_2r(kcontrol, ucontrol); }
-/* double control with volume update */ -#define SOC_WM8350_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \ - xinvert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ - SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_2r, \ - .get = wm8350_get_volsw_2r, .put = wm8350_put_volsw_2r_vu, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ - .rshift = xshift, .max = xmax, .invert = xinvert}, } - static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" }; static const char *wm8350_dacmutem[] = { "Normal", "Soft" }; @@ -443,26 +429,29 @@ static const unsigned int capture_sd_tlv[] = { static const struct snd_kcontrol_new wm8350_snd_controls[] = { SOC_ENUM("Playback Deemphasis", wm8350_enum[0]), SOC_ENUM("Playback DAC Inversion", wm8350_enum[1]), - SOC_WM8350_DOUBLE_R_TLV("Playback PCM Volume", + SOC_DOUBLE_R_EXT_TLV("Playback PCM Volume", WM8350_DAC_DIGITAL_VOLUME_L, WM8350_DAC_DIGITAL_VOLUME_R, - 0, 255, 0, dac_pcm_tlv), + 0, 255, 0, wm8350_get_volsw_2r, + wm8350_put_volsw_2r_vu, dac_pcm_tlv), SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]), SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]), SOC_ENUM("Capture PCM Filter", wm8350_enum[4]), SOC_ENUM("Capture PCM HP Filter", wm8350_enum[5]), SOC_ENUM("Capture ADC Inversion", wm8350_enum[6]), - SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume", + SOC_DOUBLE_R_EXT_TLV("Capture PCM Volume", WM8350_ADC_DIGITAL_VOLUME_L, WM8350_ADC_DIGITAL_VOLUME_R, - 0, 255, 0, adc_pcm_tlv), + 0, 255, 0, wm8350_get_volsw_2r, + wm8350_put_volsw_2r_vu, adc_pcm_tlv), SOC_DOUBLE_TLV("Capture Sidetone Volume", WM8350_ADC_DIVIDER, 8, 4, 15, 1, capture_sd_tlv), - SOC_WM8350_DOUBLE_R_TLV("Capture Volume", + SOC_DOUBLE_R_EXT_TLV("Capture Volume", WM8350_LEFT_INPUT_VOLUME, WM8350_RIGHT_INPUT_VOLUME, - 2, 63, 0, pre_amp_tlv), + 2, 63, 0, wm8350_get_volsw_2r, + wm8350_put_volsw_2r_vu, pre_amp_tlv), SOC_DOUBLE_R("Capture ZC Switch", WM8350_LEFT_INPUT_VOLUME, WM8350_RIGHT_INPUT_VOLUME, 13, 1, 0), @@ -490,17 +479,19 @@ static const struct snd_kcontrol_new wm8350_snd_controls[] = { SOC_SINGLE_TLV("Out4 Capture Volume", WM8350_INPUT_MIXER_VOLUME, 1, 7, 0, out_mix_tlv), - SOC_WM8350_DOUBLE_R_TLV("Out1 Playback Volume", + SOC_DOUBLE_R_EXT_TLV("Out1 Playback Volume", WM8350_LOUT1_VOLUME, WM8350_ROUT1_VOLUME, - 2, 63, 0, out_pga_tlv), + 2, 63, 0, wm8350_get_volsw_2r, + wm8350_put_volsw_2r_vu, out_pga_tlv), SOC_DOUBLE_R("Out1 Playback ZC Switch", WM8350_LOUT1_VOLUME, WM8350_ROUT1_VOLUME, 13, 1, 0), - SOC_WM8350_DOUBLE_R_TLV("Out2 Playback Volume", + SOC_DOUBLE_R_EXT_TLV("Out2 Playback Volume", WM8350_LOUT2_VOLUME, WM8350_ROUT2_VOLUME, - 2, 63, 0, out_pga_tlv), + 2, 63, 0, wm8350_get_volsw_2r, + wm8350_put_volsw_2r_vu, out_pga_tlv), SOC_DOUBLE_R("Out2 Playback ZC Switch", WM8350_LOUT2_VOLUME, WM8350_ROUT2_VOLUME, 13, 1, 0), SOC_SINGLE("Out2 Right Invert Switch", WM8350_ROUT2_VOLUME, 10, 1, 0), diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 4664c3a..02cbf13 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -224,31 +224,19 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol, return 0; }
-#define SOC_WM8580_OUT_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \ - xinvert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_2r, \ - .get = snd_soc_get_volsw_2r, .put = wm8580_out_vu, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ - .max = xmax, .invert = xinvert} } - static const struct snd_kcontrol_new wm8580_snd_controls[] = { -SOC_WM8580_OUT_DOUBLE_R_TLV("DAC1 Playback Volume", - WM8580_DIGITAL_ATTENUATION_DACL1, - WM8580_DIGITAL_ATTENUATION_DACR1, - 0, 0xff, 0, dac_tlv), -SOC_WM8580_OUT_DOUBLE_R_TLV("DAC2 Playback Volume", - WM8580_DIGITAL_ATTENUATION_DACL2, - WM8580_DIGITAL_ATTENUATION_DACR2, - 0, 0xff, 0, dac_tlv), -SOC_WM8580_OUT_DOUBLE_R_TLV("DAC3 Playback Volume", - WM8580_DIGITAL_ATTENUATION_DACL3, - WM8580_DIGITAL_ATTENUATION_DACR3, - 0, 0xff, 0, dac_tlv), +SOC_DOUBLE_R_EXT_TLV("DAC1 Playback Volume", + WM8580_DIGITAL_ATTENUATION_DACL1, + WM8580_DIGITAL_ATTENUATION_DACR1, + 0, 0xff, 0, snd_soc_get_volsw_2r, wm8580_out_vu, dac_tlv), +SOC_DOUBLE_R_EXT_TLV("DAC2 Playback Volume", + WM8580_DIGITAL_ATTENUATION_DACL2, + WM8580_DIGITAL_ATTENUATION_DACR2, + 0, 0xff, 0, snd_soc_get_volsw_2r, wm8580_out_vu, dac_tlv), +SOC_DOUBLE_R_EXT_TLV("DAC3 Playback Volume", + WM8580_DIGITAL_ATTENUATION_DACL3, + WM8580_DIGITAL_ATTENUATION_DACR3, + 0, 0xff, 0, snd_soc_get_volsw_2r, wm8580_out_vu, dac_tlv),
SOC_SINGLE("DAC1 Deemphasis Switch", WM8580_DAC_CONTROL3, 0, 1, 0), SOC_SINGLE("DAC2 Deemphasis Switch", WM8580_DAC_CONTROL3, 1, 1, 0), diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index ca8ce03..f3583a5 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -362,19 +362,11 @@ SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 3, 0, 7, 0, SOC_ENUM("Speaker Reference", speaker_ref), SOC_ENUM("Speaker Mode", speaker_mode),
-{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Volume", - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | - SNDRV_CTL_ELEM_ACCESS_READWRITE, - .tlv.p = outpga_tlv, - .info = snd_soc_info_volsw_2r, - .get = snd_soc_get_volsw_2r, .put = wm8993_put_dc_servo, - .private_value = (unsigned long)&(struct soc_mixer_control) { - .reg = WM8993_LEFT_OUTPUT_VOLUME, - .rreg = WM8993_RIGHT_OUTPUT_VOLUME, - .shift = 0, .max = 63 - }, -}, +SOC_DOUBLE_R_EXT_TLV("Headphone Volume", + WM8993_LEFT_OUTPUT_VOLUME, WM8993_RIGHT_OUTPUT_VOLUME, + 0, 63, 0, snd_soc_get_volsw_2r, wm8993_put_dc_servo, + outpga_tlv), + SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME, WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0), SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME,

On Tue, Oct 04, 2011 at 02:39:40PM +0300, Peter Ujfalusi wrote:
Use the macros for controls require custom get/put function. This is to make sure that the soc_mixer_control is used consistently among the drivers.
Hrm, this doesn't actually apply on for-3.2 - looks like it collides with Axel's cleanups. Can you check and regenerate please?

On Tue, Oct 4, 2011 at 6:30 PM, Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Tue, Oct 04, 2011 at 02:39:40PM +0300, Peter Ujfalusi wrote:
Use the macros for controls require custom get/put function. This is to make sure that the soc_mixer_control is used consistently among the drivers.
Hrm, this doesn't actually apply on for-3.2 - looks like it collides with Axel's cleanups. Can you check and regenerate please?
Sure.

The custom get_volsw does not need to call any core get_volsw calls, since we are returning the shadow values for the gains. Return -EINVAL in the unlikely event, if the function has been called for unhandled control. This way we can remove one check in the code.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- sound/soc/codecs/twl6040.c | 16 ++++------------ 1 files changed, 4 insertions(+), 12 deletions(-)
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 7e1c4c2..1d66127 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -798,20 +798,12 @@ static int twl6040_get_volsw(struct snd_kcontrol *kcontrol, out = &twl6040_priv->handsfree; break; default: - break; - } - - if (out) { - ucontrol->value.integer.value[0] = out->left_vol; - ucontrol->value.integer.value[1] = out->right_vol; - return 0; + return -EINVAL; }
- /* call the appropriate handler depending on the rreg */ - if (mc->rreg) - return snd_soc_get_volsw_2r(kcontrol, ucontrol); - else - return snd_soc_get_volsw(kcontrol, ucontrol); + ucontrol->value.integer.value[0] = out->left_vol; + ucontrol->value.integer.value[1] = out->right_vol; + return 0; }
static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,

On Tue, Oct 04, 2011 at 02:39:41PM +0300, Peter Ujfalusi wrote:
The custom get_volsw does not need to call any core get_volsw calls, since we are returning the shadow values for the gains. Return -EINVAL in the unlikely event, if the function has been called for unhandled control. This way we can remove one check in the code.
This, and patch 5 also have an issue (they depend on patch 3 anyway).

Return -EINVAL in the unlikely event, if the function has been called for unhandled control. This way we can remove one check in the code.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- sound/soc/codecs/twl6040.c | 12 +++++------- 1 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 1d66127..cc889e9 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -759,15 +759,13 @@ static int twl6040_put_volsw(struct snd_kcontrol *kcontrol, out = &twl6040_priv->handsfree; break; default: - break; + return -EINVAL; }
- if (out) { - out->left_vol = ucontrol->value.integer.value[0]; - out->right_vol = ucontrol->value.integer.value[1]; - if (!out->active) - return 1; - } + out->left_vol = ucontrol->value.integer.value[0]; + out->right_vol = ucontrol->value.integer.value[1]; + if (!out->active) + return 1;
/* call the appropriate handler depending on the rreg */ if (mc->rreg)

On Tue, Oct 04, 2011 at 02:39:42PM +0300, Peter Ujfalusi wrote:
Return -EINVAL in the unlikely event, if the function has been called for unhandled control. This way we can remove one check in the code.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com
I'll apply this but as with the discussion with the Maxim devices the other day it'd be better if there were some sort of loud warning if we ever hit the error case as it means that the CODEC driver is disagreeing with itself.

On Tue, Oct 4, 2011 at 6:26 PM, Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Tue, Oct 04, 2011 at 02:39:42PM +0300, Peter Ujfalusi wrote:
Return -EINVAL in the unlikely event, if the function has been called for unhandled control. This way we can remove one check in the code.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com
I'll apply this but as with the discussion with the Maxim devices the other day it'd be better if there were some sort of loud warning if we ever hit the error case as it means that the CODEC driver is disagreeing with itself.
Agreed, I'll put dev_err for the error cases.

Avoid using the mc->rreg to identify the 2r type of gain control. Introduce a variable to track this. This change is needed to avoid breakage with the upcoming volsw volsw_2r merger.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- sound/soc/codecs/twl6040.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index cc889e9..ff27eb4 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -746,7 +746,7 @@ static int twl6040_put_volsw(struct snd_kcontrol *kcontrol, struct twl6040_output *out = NULL; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - int ret; + int ret, type_2r;
/* For HS and HF we shadow the values and only actually write * them out when active in order to ensure the amplifier comes on @@ -754,9 +754,11 @@ static int twl6040_put_volsw(struct snd_kcontrol *kcontrol, switch (mc->reg) { case TWL6040_REG_HSGAIN: out = &twl6040_priv->headset; + type_2r = 0; break; case TWL6040_REG_HFLGAIN: out = &twl6040_priv->handsfree; + type_2r = 1; break; default: return -EINVAL; @@ -768,7 +770,7 @@ static int twl6040_put_volsw(struct snd_kcontrol *kcontrol, return 1;
/* call the appropriate handler depending on the rreg */ - if (mc->rreg) + if (type_2r) ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); else ret = snd_soc_put_volsw(kcontrol, ucontrol);

On Tue, Oct 04, 2011 at 02:39:43PM +0300, Peter Ujfalusi wrote:
Avoid using the mc->rreg to identify the 2r type of gain control. Introduce a variable to track this. This change is needed to avoid breakage with the upcoming volsw volsw_2r merger.
I've applied this one, I'll not even try with the rest due to dependency issues but I'm going to carry on with the review.

SOC_SINGLE/DOUBLE_VALUE is used for mixer controls, where the bits are within one register. Assign .rreg to be the same as .reg for these types.
With this change we can tell if the mixer in question: is mono: mc->reg == mc->rreg && mc->shift == mc->rshift
is stereo, within single register: mc->reg == mc->rreg && mc->shift != mc->rshift
is stereo, in two registers: mc->reg != mc->rreg && mc->shift == mc->rshift
The patch provide a small inline function to query, if the mixer is stereo, or mono.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- include/sound/soc.h | 17 +++++++++++++++-- 1 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 9d0524a..59e72a8 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -30,8 +30,9 @@ */ #define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .shift = shift_left, .rshift = shift_right, \ - .max = xmax, .platform_max = xmax, .invert = xinvert}) + {.reg = xreg, .rreg = xreg, .shift = shift_left, \ + .rshift = shift_right, .max = xmax, .platform_max = xmax, \ + .invert = xinvert}) #define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \ SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert) #define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ @@ -946,6 +947,18 @@ static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card) INIT_LIST_HEAD(&card->dapm_list); }
+static inline int snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) +{ + if (mc->reg == mc->rreg && mc->shift == mc->rshift) + return 0; + /* + * mc->reg == mc->rreg && mc->shift != mc->rshift, or + * mc->reg != mc->rreg && mc->shift == mc->rshift means that the control + * is stereo (bits in one register or in two registers) + */ + return 1; +} + int snd_soc_util_init(void); void snd_soc_util_exit(void);

On Tue, Oct 04, 2011 at 02:39:44PM +0300, Peter Ujfalusi wrote:
SOC_SINGLE/DOUBLE_VALUE is used for mixer controls, where the bits are within one register. Assign .rreg to be the same as .reg for these types.
Just a general note about your changelogs - the indentation is really random, normally we have a blank line between paragraphs and have similar line lengths within paragraphs.
With this change we can tell if the mixer in question: is mono: mc->reg == mc->rreg && mc->shift == mc->rshift
is stereo, within single register: mc->reg == mc->rreg && mc->shift != mc->rshift
is stereo, in two registers: mc->reg != mc->rreg && mc->shift == mc->rshift
reg != rreg should be enough.
+static inline int snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) +{
- if (mc->reg == mc->rreg && mc->shift == mc->rshift)
return 0;
- /*
* mc->reg == mc->rreg && mc->shift != mc->rshift, or
* mc->reg != mc->rreg && mc->shift == mc->rshift means that the control
* is stereo (bits in one register or in two registers)
*/
- return 1;
+}
bool.

Handle the info_volsw/info_volsw_2r in one function.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- include/sound/soc.h | 8 +++----- sound/soc/soc-core.c | 40 +++------------------------------------- 2 files changed, 6 insertions(+), 42 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 59e72a8..190d603 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -63,7 +63,7 @@ max, invert) } #define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .info = snd_soc_info_volsw_2r, \ + .info = snd_soc_info_volsw, \ .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ xmax, xinvert) } @@ -81,7 +81,7 @@ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_2r, \ + .info = snd_soc_info_volsw, \ .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ xmax, xinvert) } @@ -156,7 +156,7 @@ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ SNDRV_CTL_ELEM_ACCESS_READWRITE, \ .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_2r, \ + .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ xmax, xinvert) } @@ -393,8 +393,6 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo); int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 1ed8093..d588bb1 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2248,7 +2248,8 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext); * @kcontrol: mixer control * @uinfo: control element information * - * Callback to provide information about a single mixer control. + * Callback to provide information about a single mixer control, or a double + * mixer control that spans 2 registers. * * Returns 0 for success. */ @@ -2258,8 +2259,6 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; int platform_max; - unsigned int shift = mc->shift; - unsigned int rshift = mc->rshift;
if (!mc->platform_max) mc->platform_max = mc->max; @@ -2270,7 +2269,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, else uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = shift == rshift ? 1 : 2; + uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = platform_max; return 0; @@ -2356,39 +2355,6 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
/** - * snd_soc_info_volsw_2r - double mixer info callback - * @kcontrol: mixer control - * @uinfo: control element information - * - * Callback to provide information about a double mixer control that - * spans 2 codec registers. - * - * Returns 0 for success. - */ -int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int platform_max; - - if (!mc->platform_max) - mc->platform_max = mc->max; - platform_max = mc->platform_max; - - if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume")) - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - else - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = platform_max; - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r); - -/** * snd_soc_get_volsw_2r - double mixer get callback * @kcontrol: mixer control * @ucontrol: control element information

Handle the get_volsw/get_volsw_2r in one function.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- include/sound/soc.h | 6 +--- sound/soc/soc-core.c | 55 +++++++++++-------------------------------------- 2 files changed, 15 insertions(+), 46 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 190d603..fd97659 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -64,7 +64,7 @@ #define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw_2r, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ xmax, xinvert) } #define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \ @@ -82,7 +82,7 @@ SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw_2r, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ xmax, xinvert) } #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ @@ -393,8 +393,6 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d588bb1..a67c113 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2281,7 +2281,8 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw); * @kcontrol: mixer control * @ucontrol: control element information * - * Callback to get the value of a single mixer control. + * Callback to get the value of a single mixer control, or a double mixer + * control that spans 2 registers. * * Returns 0 for success. */ @@ -2292,6 +2293,7 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); unsigned int reg = mc->reg; + unsigned int reg2 = mc->rreg; unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; int max = mc->max; @@ -2300,13 +2302,19 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[0] = (snd_soc_read(codec, reg) >> shift) & mask; - if (shift != rshift) - ucontrol->value.integer.value[1] = - (snd_soc_read(codec, reg) >> rshift) & mask; + + if (snd_soc_volsw_is_stereo(mc)) { + if (shift != rshift) + ucontrol->value.integer.value[1] = + (snd_soc_read(codec, reg) >> rshift) & mask; + else + ucontrol->value.integer.value[1] = + (snd_soc_read(codec, reg2) >> shift) & mask; + } if (invert) { ucontrol->value.integer.value[0] = max - ucontrol->value.integer.value[0]; - if (shift != rshift) + if (snd_soc_volsw_is_stereo(mc)) ucontrol->value.integer.value[1] = max - ucontrol->value.integer.value[1]; } @@ -2355,43 +2363,6 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
/** - * snd_soc_get_volsw_2r - double mixer get callback - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to get the value of a double mixer control that spans 2 registers. - * - * Returns 0 for success. - */ -int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; - unsigned int invert = mc->invert; - - ucontrol->value.integer.value[0] = - (snd_soc_read(codec, reg) >> shift) & mask; - ucontrol->value.integer.value[1] = - (snd_soc_read(codec, reg2) >> shift) & mask; - if (invert) { - ucontrol->value.integer.value[0] = - max - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = - max - ucontrol->value.integer.value[1]; - } - - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r); - -/** * snd_soc_put_volsw_2r - double mixer set callback * @kcontrol: mixer control * @ucontrol: control element information

Handle the put_volsw/put_volsw_2r in one function.
To avoid build breakage in twl6040 keep the snd_soc_put_volsw_2r as define, and map it snd_soc_put_volsw.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- include/sound/soc.h | 7 ++--- sound/soc/soc-core.c | 66 ++++++++++++++----------------------------------- 2 files changed, 22 insertions(+), 51 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index fd97659..8979250 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -64,7 +64,7 @@ #define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw, .put = snd_soc_put_volsw_2r, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ xmax, xinvert) } #define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \ @@ -82,7 +82,7 @@ SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw, .put = snd_soc_put_volsw_2r, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ xmax, xinvert) } #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ @@ -393,8 +393,7 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); +#define snd_soc_put_volsw_2r snd_soc_put_volsw int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a67c113..f6f48f3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2328,7 +2328,8 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw); * @kcontrol: mixer control * @ucontrol: control element information * - * Callback to set the value of a single mixer control. + * Callback to set the value of a single mixer control, or a double mixer + * control that spans 2 registers. * * Returns 0 for success. */ @@ -2339,73 +2340,44 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); unsigned int reg = mc->reg; + unsigned int reg2 = mc->rreg; unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; - unsigned int val, val2, val_mask; + int err; + bool type_2r = 0; + unsigned int val2 = 0; + unsigned int val, val_mask;
val = (ucontrol->value.integer.value[0] & mask); if (invert) val = max - val; val_mask = mask << shift; val = val << shift; - if (shift != rshift) { + if (snd_soc_volsw_is_stereo(mc)) { val2 = (ucontrol->value.integer.value[1] & mask); if (invert) val2 = max - val2; - val_mask |= mask << rshift; - val |= val2 << rshift; - } - return snd_soc_update_bits_locked(codec, reg, val_mask, val); -} -EXPORT_SYMBOL_GPL(snd_soc_put_volsw); - -/** - * snd_soc_put_volsw_2r - double mixer set callback - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to set the value of a double mixer control that spans 2 registers. - * - * Returns 0 for success. - */ -int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; - unsigned int invert = mc->invert; - int err; - unsigned int val, val2, val_mask; - - val_mask = mask << shift; - val = (ucontrol->value.integer.value[0] & mask); - val2 = (ucontrol->value.integer.value[1] & mask); - - if (invert) { - val = max - val; - val2 = max - val2; + if (shift != rshift) { + val_mask |= mask << rshift; + val |= val2 << rshift; + } else { + val2 = val2 << shift; + type_2r = 1; + } } - - val = val << shift; - val2 = val2 << shift; - err = snd_soc_update_bits_locked(codec, reg, val_mask, val); if (err < 0) return err;
- err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2); + if (type_2r) + err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2); + return err; } -EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r); +EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
/** * snd_soc_info_volsw_s8 - signed mixer info callback

The ASoC core now have one callback function, which can handle single, and double register mixer controls.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- sound/soc/codecs/twl6040.c | 10 ++-------- 1 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index ff27eb4..ea814e5 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -746,7 +746,7 @@ static int twl6040_put_volsw(struct snd_kcontrol *kcontrol, struct twl6040_output *out = NULL; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - int ret, type_2r; + int ret;
/* For HS and HF we shadow the values and only actually write * them out when active in order to ensure the amplifier comes on @@ -754,11 +754,9 @@ static int twl6040_put_volsw(struct snd_kcontrol *kcontrol, switch (mc->reg) { case TWL6040_REG_HSGAIN: out = &twl6040_priv->headset; - type_2r = 0; break; case TWL6040_REG_HFLGAIN: out = &twl6040_priv->handsfree; - type_2r = 1; break; default: return -EINVAL; @@ -769,11 +767,7 @@ static int twl6040_put_volsw(struct snd_kcontrol *kcontrol, if (!out->active) return 1;
- /* call the appropriate handler depending on the rreg */ - if (type_2r) - ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); - else - ret = snd_soc_put_volsw(kcontrol, ucontrol); + ret = snd_soc_put_volsw(kcontrol, ucontrol);
if (ret < 0) return ret;

We do not have users for snd_soc_put_volsw_2r anymore. It can be removed.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- include/sound/soc.h | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 8979250..091786c 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -393,7 +393,6 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -#define snd_soc_put_volsw_2r snd_soc_put_volsw int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,

On Tue, Oct 04, 2011 at 02:39:37PM +0300, Peter Ujfalusi wrote:
This has been suggested in this thread: http://mailman.alsa-project.org/pipermail/alsa-devel/2011-September/044287.h...
This all looks good but needs a rebase against the current code, thanks for doing this work! Can you please do the rebase and resend the bits I didn't already apply?

On Tuesday 04 October 2011 16:39:19 Mark Brown wrote:
On Tue, Oct 04, 2011 at 02:39:37PM +0300, Peter Ujfalusi wrote:
This has been suggested in this thread: http://mailman.alsa-project.org/pipermail/alsa-devel/2011-September/0442 87.html
This all looks good but needs a rebase against the current code, thanks for doing this work! Can you please do the rebase and resend the bits I didn't already apply?
Thanks, I can send the rebased series at the morning.
-- Péter
participants (3)
-
Mark Brown
-
Peter Ujfalusi
-
Ujfalusi, Peter