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

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

ALSA: ctxfi - Make volume controls more intuitive



Change the volume control to dB scale (as the raw data seems so).
Also added the TLV dB-scale information.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 54de6bc8
Loading
Loading
Loading
Loading
+32 −17
Original line number Diff line number Diff line
@@ -18,11 +18,12 @@

#include "ctmixer.h"
#include "ctamixer.h"
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/asoundef.h>
#include <sound/pcm.h>
#include <linux/slab.h>
#include <sound/tlv.h>

enum CT_SUM_CTL {
	SUM_IN_F,
@@ -292,6 +293,7 @@ set_switch_state(struct ct_mixer *mixer,
		mixer->switch_state &= ~(0x1 << (type - SWH_MIXER_START));
}

#if 0 /* not used */
/* Map integer value ranging from 0 to 65535 to 14-bit float value ranging
 * from 2^-6 to (1+1023/1024) */
static unsigned int uint16_to_float14(unsigned int x)
@@ -331,6 +333,12 @@ static unsigned int float14_to_uint16(unsigned int x)

	return x;
}
#endif /* not used */

#define VOL_SCALE	0x1c
#define VOL_MAX		0x100

static const DECLARE_TLV_DB_SCALE(ct_vol_db_scale, -6400, 25, 1);

static int ct_alsa_mix_volume_info(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_info *uinfo)
@@ -338,8 +346,7 @@ static int ct_alsa_mix_volume_info(struct snd_kcontrol *kcontrol,
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 2;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 43690;
	uinfo->value.integer.step = 128;
	uinfo->value.integer.max = VOL_MAX;

	return 0;
}
@@ -349,15 +356,18 @@ static int ct_alsa_mix_volume_get(struct snd_kcontrol *kcontrol,
{
	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
	enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
	struct amixer *amixer = NULL;
	int i = 0;
	struct amixer *amixer;
	int i, val;

	for (i = 0; i < 2; i++) {
		amixer = ((struct ct_mixer *)atc->mixer)->
						amixers[type*CHN_NUM+i];
		/* Convert 14-bit float-point scale to 16-bit integer volume */
		ucontrol->value.integer.value[i] =
		(float14_to_uint16(amixer->ops->get_scale(amixer)) & 0xffff);
		val = amixer->ops->get_scale(amixer) / VOL_SCALE;
		if (val < 0)
			val = 0;
		else if (val > VOL_MAX)
			val = VOL_MAX;
		ucontrol->value.integer.value[i] = val;
	}

	return 0;
@@ -369,16 +379,19 @@ static int ct_alsa_mix_volume_put(struct snd_kcontrol *kcontrol,
	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
	struct ct_mixer *mixer = atc->mixer;
	enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
	struct amixer *amixer = NULL;
	int i = 0, j = 0, change = 0, val = 0;
	struct amixer *amixer;
	int i, j, val, oval, change = 0;

	for (i = 0; i < 2; i++) {
		/* Convert 16-bit integer volume to 14-bit float-point scale */
		val = (ucontrol->value.integer.value[i] & 0xffff);
		val = ucontrol->value.integer.value[i];
		if (val < 0)
			val = 0;
		else if (val > VOL_MAX)
			val = VOL_MAX;
		val *= VOL_SCALE;
		amixer = mixer->amixers[type*CHN_NUM+i];
		if ((float14_to_uint16(amixer->ops->get_scale(amixer)) & 0xff80)
				!= (val & 0xff80)) {
			val = uint16_to_float14(val);
		oval = amixer->ops->get_scale(amixer);
		if (val != oval) {
			amixer->ops->set_scale(amixer, val);
			amixer->ops->commit_write(amixer);
			change = 1;
@@ -398,11 +411,13 @@ static int ct_alsa_mix_volume_put(struct snd_kcontrol *kcontrol,
}

static struct snd_kcontrol_new vol_ctl = {
	.access		= SNDRV_CTL_ELEM_ACCESS_READWRITE,
	.access		= SNDRV_CTL_ELEM_ACCESS_READWRITE |
			  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
	.iface		= SNDRV_CTL_ELEM_IFACE_MIXER,
	.info		= ct_alsa_mix_volume_info,
	.get		= ct_alsa_mix_volume_get,
	.put		= ct_alsa_mix_volume_put
	.put		= ct_alsa_mix_volume_put,
	.tlv		= { .p =  ct_vol_db_scale },
};

static void