From 085f30654175a91c28d2b66b9ea6cceab627fed0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 16 Jun 2009 13:57:07 +0200 Subject: [PATCH] ALSA: Add new TLV types for dBwith min/max Add new types for TLV dB scale specified with min/max values instead of min/step since the resolution can't match always with the one a device provides. For example, usb audio devices give 1/256 dB resolution while ALSA TLV is based on 1/100 dB resolution. The new min/max types have less problems because the possible rounding error happens only at min/max. Signed-off-by: Takashi Iwai --- include/sound/tlv.h | 14 ++++++++++++++ sound/core/vmaster.c | 8 ++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/include/sound/tlv.h b/include/sound/tlv.h index d136ea2181ed..9fd5b19ccf5c 100644 --- a/include/sound/tlv.h +++ b/include/sound/tlv.h @@ -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), \ diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 257624bd1997..3b9b550109cb 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c @@ -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;