ASoC: core: Add strobe control
authorKristoffer KARLSSON <kristoffer.karlsson@stericsson.com>
Fri, 20 Apr 2012 09:32:44 +0000 (11:32 +0200)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 23 Apr 2012 19:05:06 +0000 (20:05 +0100)
Added support for a control that strobes a bit in
a register to high then back to low (or the inverse).

This is typically useful for hardware that requires
strobing a singe bit to trigger some functionality
and where exposing the bit in a normal single control
would require the user to first manually set then
again unset the bit again for the strobe to trigger.

Added convenience macro.

SOC_SINGLE_STROBE

Added accessor implementations.

snd_soc_get_strobe
snd_soc_put_strobe

Signed-off-by: Kristoffer KARLSSON <kristoffer.karlsson@stericsson.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
include/sound/soc.h
sound/soc/soc-core.c

index c0656b7..1f38aa1 100644 (file)
                {.regbase = xregbase, .regcount = xregcount, .nbits = xnbits, \
                .invert = xinvert, .min = xmin, .max = xmax} }
 
+#define SOC_SINGLE_STROBE(xname, xreg, xshift, xinvert) \
+       SOC_SINGLE_EXT(xname, xreg, xshift, 1, xinvert, \
+               snd_soc_get_strobe, snd_soc_put_strobe)
+
 /*
  * Simplified versions of above macros, declaring a struct and calculating
  * ARRAY_SIZE internally
@@ -461,6 +465,10 @@ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
 int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
+int snd_soc_get_strobe(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol);
+int snd_soc_put_strobe(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol);
 
 /**
  * struct snd_soc_reg_access - Describes whether a given register is
index 01bbd86..666b81b 100644 (file)
@@ -3010,6 +3010,69 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
 EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx);
 
 /**
+ * snd_soc_get_strobe - strobe get callback
+ * @kcontrol: mixer control
+ * @ucontrol: control element information
+ *
+ * Callback get the value of a strobe mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_get_strobe(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 shift = mc->shift;
+       unsigned int mask = 1 << shift;
+       unsigned int invert = mc->invert != 0;
+       unsigned int val = snd_soc_read(codec, reg) & mask;
+
+       if (shift != 0 && val != 0)
+               val = val >> shift;
+       ucontrol->value.enumerated.item[0] = val ^ invert;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_get_strobe);
+
+/**
+ * snd_soc_put_strobe - strobe put callback
+ * @kcontrol: mixer control
+ * @ucontrol: control element information
+ *
+ * Callback strobe a register bit to high then low (or the inverse)
+ * in one pass of a single mixer enum control.
+ *
+ * Returns 1 for success.
+ */
+int snd_soc_put_strobe(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 shift = mc->shift;
+       unsigned int mask = 1 << shift;
+       unsigned int invert = mc->invert != 0;
+       unsigned int strobe = ucontrol->value.enumerated.item[0] != 0;
+       unsigned int val1 = (strobe ^ invert) ? mask : 0;
+       unsigned int val2 = (strobe ^ invert) ? 0 : mask;
+       int err;
+
+       err = snd_soc_update_bits_locked(codec, reg, mask, val1);
+       if (err < 0)
+               return err;
+
+       err = snd_soc_update_bits_locked(codec, reg, mask, val2);
+       return err;
+}
+EXPORT_SYMBOL_GPL(snd_soc_put_strobe);
+
+/**
  * snd_soc_dai_set_sysclk - configure DAI system or master clock.
  * @dai: DAI
  * @clk_id: DAI specific clock ID