Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b34c8663 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge branch 'topic/tlv-minmax' into for-linus

* topic/tlv-minmax:
  ALSA: usb-audio - Correct bogus volume dB information
  ALSA: usb-audio - Use the new TLV_DB_MINMAX type
  ALSA: Add new TLV types for dBwith min/max
parents 3827119e eedbdf03
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@
#define SNDRV_CTL_TLVT_DB_SCALE	1       /* dB scale */
#define SNDRV_CTL_TLVT_DB_LINEAR 2	/* linear volume */
#define SNDRV_CTL_TLVT_DB_RANGE 3	/* dB range container */
#define SNDRV_CTL_TLVT_DB_MINMAX 4	/* dB scale with min/max */
#define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5	/* dB scale with min/max with mute */

#define TLV_DB_SCALE_ITEM(min, step, mute)			\
	SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int),	\
@@ -42,6 +44,18 @@
#define DECLARE_TLV_DB_SCALE(name, min, step, mute) \
	unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) }

/* dB scale specified with min/max values instead of step */
#define TLV_DB_MINMAX_ITEM(min_dB, max_dB)			\
	SNDRV_CTL_TLVT_DB_MINMAX, 2 * sizeof(unsigned int),	\
	(min_dB), (max_dB)
#define TLV_DB_MINMAX_MUTE_ITEM(min_dB, max_dB)			\
	SNDRV_CTL_TLVT_DB_MINMAX_MUTE, 2 * sizeof(unsigned int),	\
	(min_dB), (max_dB)
#define DECLARE_TLV_DB_MINMAX(name, min_dB, max_dB) \
	unsigned int name[] = { TLV_DB_MINMAX_ITEM(min_dB, max_dB) }
#define DECLARE_TLV_DB_MINMAX_MUTE(name, min_dB, max_dB) \
	unsigned int name[] = { TLV_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) }

/* linear volume between min_dB and max_dB (.01dB unit) */
#define TLV_DB_LINEAR_ITEM(min_dB, max_dB)		    \
	SNDRV_CTL_TLVT_DB_LINEAR, 2 * sizeof(unsigned int), \
+6 −2
Original line number Diff line number Diff line
@@ -353,7 +353,8 @@ static void master_free(struct snd_kcontrol *kcontrol)
 *
 * The optional argument @tlv can be used to specify the TLV information
 * for dB scale of the master control.  It should be a single element
 * with #SNDRV_CTL_TLVT_DB_SCALE type, and should be the max 0dB.
 * with #SNDRV_CTL_TLVT_DB_SCALE, #SNDRV_CTL_TLV_DB_MINMAX or
 * #SNDRV_CTL_TLVT_DB_MINMAX_MUTE type, and should be the max 0dB.
 */
struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
						 const unsigned int *tlv)
@@ -384,7 +385,10 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
	kctl->private_free = master_free;

	/* additional (constant) TLV read */
	if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) {
	if (tlv &&
	    (tlv[0] == SNDRV_CTL_TLVT_DB_SCALE ||
	     tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX ||
	     tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX_MUTE)) {
		kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
		memcpy(master->tlv, tlv, sizeof(master->tlv));
		kctl->tlv.p = master->tlv;
+11 −2
Original line number Diff line number Diff line
@@ -461,7 +461,7 @@ static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
			 unsigned int size, unsigned int __user *_tlv)
{
	struct usb_mixer_elem_info *cval = kcontrol->private_data;
	DECLARE_TLV_DB_SCALE(scale, 0, 0, 0);
	DECLARE_TLV_DB_MINMAX(scale, 0, 0);

	if (size < sizeof(scale))
		return -ENOMEM;
@@ -469,7 +469,16 @@ static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
	 * while ALSA TLV contains in 1/100 dB unit
	 */
	scale[2] = (convert_signed_value(cval, cval->min) * 100) / 256;
	scale[3] = (convert_signed_value(cval, cval->res) * 100) / 256;
	scale[3] = (convert_signed_value(cval, cval->max) * 100) / 256;
	if (scale[3] <= scale[2]) {
		/* something is wrong; assume it's either from/to 0dB */
		if (scale[2] < 0)
			scale[3] = 0;
		else if (scale[2] > 0)
			scale[2] = 0;
		else /* totally crap, return an error */
			return -EINVAL;
	}
	if (copy_to_user(_tlv, scale, sizeof(scale)))
		return -EFAULT;
	return 0;