Re: ALSA mixer volume control

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I've added a little extra functionality to this. The first is to send 
notifications whenever the mixer volume changes. These are via ALSA and 
simply allow other applications to know when the volume has changed. 
Henrique, I wasn't sure about the cleanest way to do this - we need to 
unmask the volume keys, and the easiest thing to do there was to simply 
change them to KEY_UNKNOWN. The problem with this is that they then 
generate ugly kernel messages. Not sure what the best thing to do here 
is - I guess I could just mangle the mask directly if ALSA_VOL is 
enabled.

The other thing I've done is export attenuation information. This lets 
applications figure out the attenuation or amplification of the entire 
audio pathway, which makes it easier for userspace to set up the default 
volume levels. This was measured on a T60 using 
http://git.0pointer.de/?p=dbmeasure.git;a=summary . It'd be interesting 
to know if different machines have different characteristics - the fact 
that 8 and 9 are identical seems interesting. The other thing to note is 
that the volume keys don't seem to allow me to get to volume level 15. 
Does this work anywhere?

I also removed the writable option and made it the default. I'm not 
entirely sure why we'd want to expose a read-only mixer, but I can add 
it back if it actually helps anyone.

-- 
Matthew Garrett | mjg59@xxxxxxxxxxxxx
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 2066b5b..1798442 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -84,9 +84,9 @@
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/initval.h>
+#include <sound/tlv.h>
 #endif
 
-
 /* ThinkPad CMOS commands */
 #define TP_CMOS_VOLUME_DOWN	0
 #define TP_CMOS_VOLUME_UP	1
@@ -341,6 +341,8 @@ static int tpacpi_uwb_emulstate;
  ************************************************************************/
 #ifdef CONFIG_THINKPAD_ACPI_ALSA_VOL
 static void volume_alsa_notify_change(void);
+#else
+static void volume_alsa_notify_change(void) { return 0; };
 #endif
 
 
@@ -1725,8 +1727,10 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
 		}
 		if (oldn->volume_level > newn->volume_level) {
 			TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN);
+			volume_alsa_notify_change();
 		} else if (oldn->volume_level < newn->volume_level) {
 			TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP);
+			volume_alsa_notify_change();
 		} else if (oldn->mute == newn->mute) {
 			/* repeated key presses that didn't change state */
 			if (newn->mute) {
@@ -1736,6 +1740,7 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
 			} else {
 				TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN);
 			}
+			volume_alsa_notify_change();
 		}
 	}
 
@@ -2345,9 +2350,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 		/* Volume: firmware always react to it and reprograms
 		 * the built-in *extra* mixer.  Never map it to control
 		 * another mixer by default. */
-		KEY_RESERVED,	/* 0x14: VOLUME UP */
-		KEY_RESERVED,	/* 0x15: VOLUME DOWN */
-		KEY_RESERVED,	/* 0x16: MUTE */
+		KEY_UNKNOWN,	/* 0x14: VOLUME UP */
+		KEY_UNKNOWN,	/* 0x15: VOLUME DOWN */
+		KEY_UNKNOWN,	/* 0x16: MUTE */
 
 		KEY_VENDOR,	/* 0x17: Thinkpad/AccessIBM/Lenovo */
 
@@ -2388,9 +2393,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 		 * models.  May cause the BIOS to interfere with the
 		 * HDA mixer.
 		 */
-		KEY_RESERVED,	/* 0x14: VOLUME UP */
-		KEY_RESERVED,	/* 0x15: VOLUME DOWN */
-		KEY_RESERVED,	/* 0x16: MUTE */
+		KEY_UNKNOWN,	/* 0x14: VOLUME UP */
+		KEY_UNKNOWN,	/* 0x15: VOLUME DOWN */
+		KEY_UNKNOWN,	/* 0x16: MUTE */
 
 		KEY_VENDOR,	/* 0x17: Thinkpad/AccessIBM/Lenovo */
 
@@ -2667,6 +2672,13 @@ static bool hotkey_notify_hotkey(const u32 hkey,
 
 	if (scancode > 0 && scancode < 0x21) {
 		scancode--;
+
+		/* Notify ALSA that the volume has been changed */
+		if (scancode == TP_ACPI_HOTKEYSCAN_VOLUMEUP ||
+		    scancode == TP_ACPI_HOTKEYSCAN_VOLUMEDOWN ||
+		    scancode == TP_ACPI_HOTKEYSCAN_MUTE)
+			volume_alsa_notify_change();
+
 		if (!(hotkey_source_mask & (1 << scancode))) {
 			tpacpi_input_send_key(scancode);
 			*send_acpi_ev = false;
@@ -5979,12 +5991,23 @@ static int volume_cmos_set_level_mute(u8 new_level, u8 new_mute);
 #define VOLUME_ALSA_SHORT_NAME "Speaker"
 #define VOLUME_ALSA_LONG_NAME "Thinkpad Speaker Volume"
 
-static int alsavol_writable;
-
 static struct snd_card * volume_alsa_card;
 static struct snd_ctl_elem_id * volume_alsa_mixer_vol_id;
 static struct snd_ctl_elem_id * volume_alsa_mixer_mute_id;
 
+static unsigned int thinkpad_tlv[] = { TLV_DB_RANGE_HEAD(10),
+				       0, 0, TLV_DB_SCALE_ITEM(-7354, 0, 1),
+				       1, 1, TLV_DB_SCALE_ITEM(-4349, 0, 0),
+				       2, 2, TLV_DB_SCALE_ITEM(-3380, 0, 0),
+				       3, 3, TLV_DB_SCALE_ITEM(-2591, 0, 0),
+				       4, 4, TLV_DB_SCALE_ITEM(-2195, 0, 0),
+				       5, 7, TLV_DB_SCALE_ITEM(-1595, 200, 0),
+				       8, 9, TLV_DB_SCALE_ITEM(-797, 0, 0),
+				       10, 12, TLV_DB_SCALE_ITEM(-599, 200, 0),
+				       13, 13, TLV_DB_SCALE_ITEM(-100, 0, 0),
+				       14, 15, TLV_DB_SCALE_ITEM(0, 0, 0),
+};
+
 static void volume_alsa_notify_change(void){
 	if(volume_alsa_mixer_vol_id)
 		snd_ctl_notify(volume_alsa_card, SNDRV_CTL_EVENT_MASK_VALUE,
@@ -6036,6 +6059,7 @@ static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol,
 	u8 new_level;
 	u8 mute;
 	int changed = 0;
+
 	if (!acpi_ec_read(volume_offset, &cur_level))
 		return -EIO;
 
@@ -6060,6 +6084,7 @@ static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol,
 {
 	u8 cur_mute, new_mute, level;
 	int changed = 0;
+
 	if (!acpi_ec_read(volume_offset, &cur_mute))
 		return -EIO;
 
@@ -6084,17 +6109,19 @@ static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Playback Volume",
 	.index = 0,
-	.access = SNDRV_CTL_ELEM_ACCESS_READ,
+	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+		   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 	.info = volume_alsa_vol_info,
 	.get = volume_alsa_vol_get,
-	.put = volume_alsa_vol_put
+	.put = volume_alsa_vol_put,
+	.tlv = { .p = thinkpad_tlv }
 };
 
 static struct snd_kcontrol_new volume_alsa_control_mute __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Playback Switch",
 	.index = 0,
-	.access = SNDRV_CTL_ELEM_ACCESS_READ,
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 	.info = snd_ctl_boolean_mono_info, /* Use builtin ALSA def */
 	.get = volume_alsa_mute_get,
 	.put = volume_alsa_mute_put
@@ -6132,10 +6159,6 @@ static int __init volume_init(struct ibm_init_struct *iibm)
 
 	
 	/* Create Controls */
-	if(alsavol_writable){
-	  volume_alsa_control_vol.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
-	  volume_alsa_control_mute.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
-	}
 	vol_ctl = snd_ctl_new1(&volume_alsa_control_vol,NULL);
 	if(snd_ctl_add(volume_alsa_card,vol_ctl)){
 		vdbg_printk(TPACPI_DBG_INIT, "Failed to create ALSA volume mixer\n");
@@ -6271,9 +6294,7 @@ static int volume_write(char *buf)
 	}
 	mutex_unlock(&volume_write_mutex);
 
-#ifdef CONFIG_THINKPAD_ACPI_ALSA_VOL
 	volume_alsa_notify_change();
-#endif
 
 	return 0;
 }
@@ -7843,13 +7864,6 @@ MODULE_PARM_DESC(hotkey_report_mode,
 		 "used for backwards compatibility with userspace, "
 		 "see documentation");
 
-#ifdef CONFIG_THINKPAD_ACPI_ALSA_VOL
-module_param(alsavol_writable, bool, 0);
-MODULE_PARM_DESC(alsavol_writable,
-		 "When set to 1, allows the ALSA volume control to write "
-		 "the speaker volume rather than simply read it.");
-#endif
-
 #define TPACPI_PARAM(feature) \
 	module_param_call(feature, set_ibm_param, NULL, NULL, 0); \
 	MODULE_PARM_DESC(feature, "Simulates thinkpad-acpi procfs command " \
------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations 
Conference from O'Reilly Media. Velocity features a full day of 
expert-led, hands-on workshops and two days of sessions from industry 
leaders in dedicated Performance & Operations tracks. Use code vel09scf 
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
ibm-acpi-devel mailing list
ibm-acpi-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/ibm-acpi-devel

[Index of Archives]     [Linux ACPI]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Photo]     [Yosemite Photos]     [Yosemite Advice]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]

  Powered by Linux