|
@@ -2891,6 +2891,124 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(snd_soc_bytes_put);
|
|
|
|
|
|
+/**
|
|
|
+ * snd_soc_info_xr_sx - signed multi register info callback
|
|
|
+ * @kcontrol: mreg control
|
|
|
+ * @uinfo: control element information
|
|
|
+ *
|
|
|
+ * Callback to provide information of a control that can
|
|
|
+ * span multiple codec registers which together
|
|
|
+ * forms a single signed value in a MSB/LSB manner.
|
|
|
+ *
|
|
|
+ * Returns 0 for success.
|
|
|
+ */
|
|
|
+int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
|
|
|
+ struct snd_ctl_elem_info *uinfo)
|
|
|
+{
|
|
|
+ struct soc_mreg_control *mc =
|
|
|
+ (struct soc_mreg_control *)kcontrol->private_value;
|
|
|
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
|
|
+ uinfo->count = 1;
|
|
|
+ uinfo->value.integer.min = mc->min;
|
|
|
+ uinfo->value.integer.max = mc->max;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx);
|
|
|
+
|
|
|
+/**
|
|
|
+ * snd_soc_get_xr_sx - signed multi register get callback
|
|
|
+ * @kcontrol: mreg control
|
|
|
+ * @ucontrol: control element information
|
|
|
+ *
|
|
|
+ * Callback to get the value of a control that can span
|
|
|
+ * multiple codec registers which together forms a single
|
|
|
+ * signed value in a MSB/LSB manner. The control supports
|
|
|
+ * specifying total no of bits used to allow for bitfields
|
|
|
+ * across the multiple codec registers.
|
|
|
+ *
|
|
|
+ * Returns 0 for success.
|
|
|
+ */
|
|
|
+int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
|
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
|
+{
|
|
|
+ struct soc_mreg_control *mc =
|
|
|
+ (struct soc_mreg_control *)kcontrol->private_value;
|
|
|
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
|
|
+ unsigned int regbase = mc->regbase;
|
|
|
+ unsigned int regcount = mc->regcount;
|
|
|
+ unsigned int regwshift = codec->driver->reg_word_size * BITS_PER_BYTE;
|
|
|
+ unsigned int regwmask = (1<<regwshift)-1;
|
|
|
+ unsigned int invert = mc->invert;
|
|
|
+ unsigned long mask = (1UL<<mc->nbits)-1;
|
|
|
+ long min = mc->min;
|
|
|
+ long max = mc->max;
|
|
|
+ long val = 0;
|
|
|
+ unsigned long regval;
|
|
|
+ unsigned int i;
|
|
|
+
|
|
|
+ for (i = 0; i < regcount; i++) {
|
|
|
+ regval = snd_soc_read(codec, regbase+i) & regwmask;
|
|
|
+ val |= regval << (regwshift*(regcount-i-1));
|
|
|
+ }
|
|
|
+ val &= mask;
|
|
|
+ if (min < 0 && val > max)
|
|
|
+ val |= ~mask;
|
|
|
+ if (invert)
|
|
|
+ val = max - val;
|
|
|
+ ucontrol->value.integer.value[0] = val;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx);
|
|
|
+
|
|
|
+/**
|
|
|
+ * snd_soc_put_xr_sx - signed multi register get callback
|
|
|
+ * @kcontrol: mreg control
|
|
|
+ * @ucontrol: control element information
|
|
|
+ *
|
|
|
+ * Callback to set the value of a control that can span
|
|
|
+ * multiple codec registers which together forms a single
|
|
|
+ * signed value in a MSB/LSB manner. The control supports
|
|
|
+ * specifying total no of bits used to allow for bitfields
|
|
|
+ * across the multiple codec registers.
|
|
|
+ *
|
|
|
+ * Returns 0 for success.
|
|
|
+ */
|
|
|
+int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
|
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
|
+{
|
|
|
+ struct soc_mreg_control *mc =
|
|
|
+ (struct soc_mreg_control *)kcontrol->private_value;
|
|
|
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
|
|
+ unsigned int regbase = mc->regbase;
|
|
|
+ unsigned int regcount = mc->regcount;
|
|
|
+ unsigned int regwshift = codec->driver->reg_word_size * BITS_PER_BYTE;
|
|
|
+ unsigned int regwmask = (1<<regwshift)-1;
|
|
|
+ unsigned int invert = mc->invert;
|
|
|
+ unsigned long mask = (1UL<<mc->nbits)-1;
|
|
|
+ long min = mc->min;
|
|
|
+ long max = mc->max;
|
|
|
+ long val = ucontrol->value.integer.value[0];
|
|
|
+ unsigned int i, regval, regmask;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ if (invert)
|
|
|
+ val = max - val;
|
|
|
+ val &= mask;
|
|
|
+ for (i = 0; i < regcount; i++) {
|
|
|
+ regval = (val >> (regwshift*(regcount-i-1))) & regwmask;
|
|
|
+ regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask;
|
|
|
+ err = snd_soc_update_bits_locked(codec, regbase+i,
|
|
|
+ regmask, regval);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx);
|
|
|
+
|
|
|
/**
|
|
|
* snd_soc_dai_set_sysclk - configure DAI system or master clock.
|
|
|
* @dai: DAI
|