[alsa-devel] [0/2] Jack reporting
This is a repost of the the jack reporting API I posted recently. There are no chances since the last submission - as discussed in that thread the existing users and the need to support buttons implemented in jacks pushes me towards use of an input device to represent jacks.
Currently very few systems provide information about jack status to user space, even though many have hardware facilities to do detection. Those systems that do use an input device with the existing SW_HEADPHONE_INSERT switch type to do so, often independently of ALSA.
This patch introduces a standard method for representing jacks to user space into ALSA. It allows drivers to register jacks for a sound card with the input subsystem, binding the input device to the card to help user space associate the input devices with their sound cards. The created input devices are named in the form "card longname jack" where jack is provided by the driver when allocating a jack. By default the parent for the input device is the sound card but this can be overridden by the card driver.
The existing user space API with SW_HEADPHONE_INSERT is preserved.
Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- include/sound/core.h | 1 + include/sound/jack.h | 52 +++++++++++++++++ sound/Kconfig | 1 + sound/core/Makefile | 3 +- sound/core/jack.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 213 insertions(+), 1 deletions(-) create mode 100644 include/sound/jack.h create mode 100644 sound/core/jack.c
diff --git a/include/sound/core.h b/include/sound/core.h index 695ee53..67543c5 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -63,6 +63,7 @@ typedef int __bitwise snd_device_type_t; #define SNDRV_DEV_INFO ((__force snd_device_type_t) 0x1006) #define SNDRV_DEV_BUS ((__force snd_device_type_t) 0x1007) #define SNDRV_DEV_CODEC ((__force snd_device_type_t) 0x1008) +#define SNDRV_DEV_JACK ((__force snd_device_type_t) 0x1009) #define SNDRV_DEV_LOWLEVEL ((__force snd_device_type_t) 0x2000)
typedef int __bitwise snd_device_state_t; diff --git a/include/sound/jack.h b/include/sound/jack.h new file mode 100644 index 0000000..5cb610d --- /dev/null +++ b/include/sound/jack.h @@ -0,0 +1,52 @@ +#ifndef __SOUND_JACK_H +#define __SOUND_JACK_H + +/* + * Jack abstraction layer + * + * Copyright 2008 Wolfson Microelectronics plc + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <sound/core.h> + +struct input_dev; + +/** + * Jack types which can be reported. These values are used as a + * bitmask. + */ +enum snd_jack_types { + SND_JACK_HEADPHONE = 0x0001, +}; + +struct snd_jack { + struct input_dev *input_dev; + int registered; + int type; + const char *id; + char name[100]; +}; + +int snd_jack_new(struct snd_card *card, const char *id, int type, + struct snd_jack **jack); +void snd_jack_set_parent(struct snd_jack *jack, struct device *parent); + +void snd_jack_report(struct snd_jack *jack, int status); + +#endif diff --git a/sound/Kconfig b/sound/Kconfig index 4247406..6564c03 100644 --- a/sound/Kconfig +++ b/sound/Kconfig @@ -38,6 +38,7 @@ menu "Advanced Linux Sound Architecture" config SND tristate "Advanced Linux Sound Architecture" depends on SOUND + depends on INPUT help Say 'Y' or 'M' to enable ALSA (Advanced Linux Sound Architecture), the new base sound system. diff --git a/sound/core/Makefile b/sound/core/Makefile index da8e685..6a7f416 100644 --- a/sound/core/Makefile +++ b/sound/core/Makefile @@ -3,7 +3,8 @@ # Copyright (c) 1999,2001 by Jaroslav Kysela perex@perex.cz #
-snd-y := sound.o init.o memory.o info.o control.o misc.o device.o +snd-y := sound.o init.o memory.o info.o control.o misc.o device.o \ + jack.o snd-$(CONFIG_ISA_DMA_API) += isadma.o snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o snd-$(CONFIG_SND_VMASTER) += vmaster.o diff --git a/sound/core/jack.c b/sound/core/jack.c new file mode 100644 index 0000000..36ecc57 --- /dev/null +++ b/sound/core/jack.c @@ -0,0 +1,157 @@ +/* + * Jack abstraction layer + * + * Copyright 2008 Wolfson Microelectronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/input.h> +#include <sound/jack.h> +#include <sound/core.h> + +static int snd_jack_dev_free(struct snd_device *device) +{ + struct snd_jack *jack = device->device_data; + + /* If the input device is registered with the input subsystem + * then we need to use a different deallocator. */ + if (jack->registered) + input_unregister_device(jack->input_dev); + else + input_free_device(jack->input_dev); + + kfree(jack); + + return 0; +} + +static int snd_jack_dev_register(struct snd_device *device) +{ + struct snd_jack *jack = device->device_data; + struct snd_card *card = device->card; + int err; + + snprintf(jack->name, sizeof(jack->name), "%s %s", + card->longname, jack->id); + jack->input_dev->name = jack->name; + + /* Default to the sound card device. */ + if (!jack->input_dev->dev.parent) + jack->input_dev->dev.parent = card->dev; + + err = input_register_device(jack->input_dev); + if (err == 0) + jack->registered = 1; + + return err; +} + +/** + * snd_jack_new - Create a new jack + * @card: the card instance + * @id: an identifying string for this jack + * @type: a bitmask of enum snd_jack_type values that can be detected by + * this jack + * @jjack: Used to provide the allocated jack object to the caller. + * + * Creates a new jack object. + * + * Returns zero if successful, or a negative error code on failure. + * On success jjack will be initialised. + */ +int snd_jack_new(struct snd_card *card, const char *id, int type, + struct snd_jack **jjack) +{ + struct snd_jack *jack; + int err; + static struct snd_device_ops ops = { + .dev_free = snd_jack_dev_free, + .dev_register = snd_jack_dev_register, + }; + + jack = kzalloc(sizeof(struct snd_jack), GFP_KERNEL); + if (jack == NULL) + return -ENOMEM; + + jack->id = id; + + jack->input_dev = input_allocate_device(); + if (jack->input_dev == NULL) { + err = -ENOMEM; + goto fail_input; + } + + jack->input_dev->phys = "ALSA"; + + jack->type = type; + + if (type & SND_JACK_HEADPHONE) + input_set_capability(jack->input_dev, EV_SW, + SW_HEADPHONE_INSERT); + + err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); + if (err < 0) + goto fail_input; + + *jjack = jack; + + return 0; + +fail_input: + input_free_device(jack->input_dev); + kfree(jack); + return err; +} +EXPORT_SYMBOL(snd_jack_new); + +/** + * snd_jack_set_parent - Set the parent device for a jack + * + * @jack: The jack to configure + * @parent: The device to set as parent for the jack. + * + * Set the parent for the jack input device in the device tree. This + * function is only valid prior to registration of the jack. If no + * parent is configured then the parent device will be the sound card. + */ +void snd_jack_set_parent(struct snd_jack *jack, struct device *parent) +{ + BUG_ON(jack->registered); + + jack->input_dev->dev.parent = parent; +} +EXPORT_SYMBOL(snd_jack_set_parent); + +/** + * snd_jack_report - Report the current status of a jack + * + * @jack: The jack to report status for + * @status: The current status of the jack + */ +void snd_jack_report(struct snd_jack *jack, int status) +{ + if (jack->type & SND_JACK_HEADPHONE) + input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT, + status & SND_JACK_HEADPHONE); + + input_sync(jack->input_dev); +} +EXPORT_SYMBOL(snd_jack_report); + +MODULE_AUTHOR("Mark Brown broonie@opensource.wolfsonmicro.com"); +MODULE_DESCRIPTION("Jack detection support for ALSA"); +MODULE_LICENSE("GPL");
Add a new switch type to the input API for reporting microphone insertion and extend the ALSA jack reporting API to include this. Since a headset is a combination of a microphone and at least a mono headphone a convenience defintion is provided for describing them.
Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- include/linux/input.h | 1 + include/sound/jack.h | 4 +++- sound/core/jack.c | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/include/linux/input.h b/include/linux/input.h index d150c57..d297dec 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -640,6 +640,7 @@ struct input_absinfo { #define SW_RFKILL_ALL 0x03 /* rfkill master switch, type "any" set = radio enabled */ #define SW_RADIO SW_RFKILL_ALL /* deprecated */ +#define SW_MICROPHONE_INSERT 0x04 /* set = inserted */ #define SW_MAX 0x0f #define SW_CNT (SW_MAX+1)
diff --git a/include/sound/jack.h b/include/sound/jack.h index 5cb610d..743f559 100644 --- a/include/sound/jack.h +++ b/include/sound/jack.h @@ -32,7 +32,9 @@ struct input_dev; * bitmask. */ enum snd_jack_types { - SND_JACK_HEADPHONE = 0x0001, + SND_JACK_HEADPHONE = 0x0001, + SND_JACK_MICROPHONE = 0x0002, + SND_JACK_HEADSET = 0x0003, /* Both microphone and headphone */ };
struct snd_jack { diff --git a/sound/core/jack.c b/sound/core/jack.c index 36ecc57..9c05ec8 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -102,6 +102,9 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, if (type & SND_JACK_HEADPHONE) input_set_capability(jack->input_dev, EV_SW, SW_HEADPHONE_INSERT); + if (type & SND_JACK_MICROPHONE) + input_set_capability(jack->input_dev, EV_SW, + SW_MICROPHONE_INSERT);
err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); if (err < 0) @@ -147,6 +150,9 @@ void snd_jack_report(struct snd_jack *jack, int status) if (jack->type & SND_JACK_HEADPHONE) input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT, status & SND_JACK_HEADPHONE); + if (jack->type & SND_JACK_MICROPHONE) + input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT, + status & SND_JACK_MICROPHONE);
input_sync(jack->input_dev); }
On Thu, Jul 03, 2008 at 10:50:27AM +0100, Mark Brown wrote:
This is a repost of the the jack reporting API I posted recently. There are no chances since the last submission - as discussed in that thread the existing users and the need to support buttons implemented in jacks pushes me towards use of an input device to represent jacks.
Takashi, do you have any comments on these patches?
At Mon, 14 Jul 2008 16:11:00 +0100, Mark Brown wrote:
On Thu, Jul 03, 2008 at 10:50:27AM +0100, Mark Brown wrote:
This is a repost of the the jack reporting API I posted recently. There are no chances since the last submission - as discussed in that thread the existing users and the need to support buttons implemented in jacks pushes me towards use of an input device to represent jacks.
Takashi, do you have any comments on these patches?
I have no strong opinion about this. Your implementation looks small enough. But, if Dmitry finds the input layer not suitable for such a purpose, this isn't a good way to go.
I think the question is how general and how extensible these features should be. If it's just a jack reporting, there are bunch of other possible implementations. Even ALSA control API could provide a similar functionality.
Takashi
On Wed, Jul 16, 2008 at 01:02:35PM +0200, Takashi Iwai wrote:
Mark Brown wrote:
Takashi, do you have any comments on these patches?
I have no strong opinion about this. Your implementation looks small enough. But, if Dmitry finds the input layer not suitable for such a purpose, this isn't a good way to go.
Unfortunately Dimitry hasn't been responding to any of the e-mails on this subject since his initial one. :/
I think the question is how general and how extensible these features should be. If it's just a jack reporting, there are bunch of other
To reiterate points I've previously made:
As well as detecting the presence of a connected device typical jack detection implementations also support the implementation of at least one button which would require an input device for at least some jacks even if something else were done. This is consistent with existing usage of the input layer - it's similar to multimedia keys which are normally reported via the input layer. Things like sleep and power buttons are implemented as individual input devices.
We do also already have existing in-kernel users of the input API to report jack status (usually done via GPIOs outside of ALSA). From that point of view this ALSA helper is simply implementing the existing user space interface for reporting jacks. I feel that if we want to do something different we should work out how to transition these existing users to it too. We can always add the existing code while working out what that transition plan might be.
The concern Dmirty raised about requring an ioctl() to get the initial switch state seems to be something that ought to be addressed anyway regardless of what happens here. Similarly, the concerns about the resouce consumption of the input layer seem to be a general issue (and to be honest I'm not convinced that they're a practical problem).
Without the existing users of this interface and the button I'd probably agree with Dmitry but those two factors persuade me otherwise.
possible implementations. Even ALSA control API could provide a similar functionality.
This has most of the concerns that applied to the existing input API :(
On Wed, Jul 16, 2008 at 01:50:53PM +0100, Mark Brown wrote:
On Wed, Jul 16, 2008 at 01:02:35PM +0200, Takashi Iwai wrote:
Mark Brown wrote:
Takashi, do you have any comments on these patches?
I have no strong opinion about this. Your implementation looks small enough. But, if Dmitry finds the input layer not suitable for such a purpose, this isn't a good way to go.
Unfortunately Dimitry hasn't been responding to any of the e-mails on this subject since his initial one. :/
Completely my fault, I am verry sorry.
I think the question is how general and how extensible these features should be. If it's just a jack reporting, there are bunch of other
To reiterate points I've previously made:
As well as detecting the presence of a connected device typical jack detection implementations also support the implementation of at least one button which would require an input device for at least some jacks even if something else were done. This is consistent with existing usage of the input layer - it's similar to multimedia keys which are normally reported via the input layer. Things like sleep and power buttons are implemented as individual input devices.
It really depends on what you can do with this button. If it is just a simple circuit breaker then it is not really an input device. However is you can remap it for different purposes or map a regular key on a keybaord to perform this function then I will agree with you. For example sleep and power buttons can be anywhere. They can be implemented as ACPI button but there also a bunch of keyboards that have a sleep button on them. Or, like you said, multimedia keys - they not always control hardware directly, often you have an option to remap and re-use them.
We do also already have existing in-kernel users of the input API to report jack status (usually done via GPIOs outside of ALSA). From that point of view this ALSA helper is simply implementing the existing user space interface for reporting jacks. I feel that if we want to do something different we should work out how to transition these existing users to it too. We can always add the existing code while working out what that transition plan might be.
Yes, I agree, we would need to transit the existing users to the new scheme.
On Wed, Jul 16, 2008 at 12:36:06PM -0400, Dmitry Torokhov wrote:
On Wed, Jul 16, 2008 at 01:50:53PM +0100, Mark Brown wrote:
As well as detecting the presence of a connected device typical jack detection implementations also support the implementation of at least one button which would require an input device for at least some jacks
It really depends on what you can do with this button. If it is just a simple circuit breaker then it is not really an input device. However is you can remap it for different purposes or map a regular key on a keybaord to perform this function then I will agree with you. For example
As far as the hardware is concerned it's just a button - if it's visible to software then there's no fixed function for it and any action taken will be application/system specific. There will normally be a side effect in hardware muting the microphone but that's not intended to be the main effect.
On Thu, Jul 17, 2008 at 11:31:12AM +0100, Mark Brown wrote:
On Wed, Jul 16, 2008 at 12:36:06PM -0400, Dmitry Torokhov wrote:
On Wed, Jul 16, 2008 at 01:50:53PM +0100, Mark Brown wrote:
As well as detecting the presence of a connected device typical jack detection implementations also support the implementation of at least one button which would require an input device for at least some jacks
It really depends on what you can do with this button. If it is just a simple circuit breaker then it is not really an input device. However is you can remap it for different purposes or map a regular key on a keybaord to perform this function then I will agree with you. For example
As far as the hardware is concerned it's just a button - if it's visible to software then there's no fixed function for it and any action taken will be application/system specific. There will normally be a side effect in hardware muting the microphone but that's not intended to be the main effect.
Ok, let's add it to the input subsystem then. If we see lots of switch types sprnging up we cam talk about the new subsystem again.
I added the switch definition to input.h and it shoudl hit the mainline when I ask Linus to pull early next week.
On Sun, Jul 20, 2008 at 01:23:20AM -0400, Dmitry Torokhov wrote:
I added the switch definition to input.h and it shoudl hit the mainline when I ask Linus to pull early next week.
Excellent, thanks.
Takashi, what's the best way to handle the ALSA bits? The first patch doesn't depend on the new switch type so could be applied as-is but the second (adding the microphone switch type) depends on the input switch type being added - should I resubmit that when the switch type has been merged?
At Sun, 20 Jul 2008 13:17:48 +0100, Mark Brown wrote:
On Sun, Jul 20, 2008 at 01:23:20AM -0400, Dmitry Torokhov wrote:
I added the switch definition to input.h and it shoudl hit the mainline when I ask Linus to pull early next week.
Excellent, thanks.
Takashi, what's the best way to handle the ALSA bits? The first patch doesn't depend on the new switch type so could be applied as-is but the second (adding the microphone switch type) depends on the input switch type being added - should I resubmit that when the switch type has been merged?
Yes, please. We need also some consensus how to handle these patches covering both areas.
BTW, I'll be on vacation for the next week, so the reply will be delayed.
thanks,
Takashi
On Sun, Jul 20, 2008 at 05:23:26PM +0200, Takashi Iwai wrote:
Mark Brown wrote:
Takashi, what's the best way to handle the ALSA bits? The first patch doesn't depend on the new switch type so could be applied as-is but the second (adding the microphone switch type) depends on the input switch type being added - should I resubmit that when the switch type has been merged?
Yes, please. We need also some consensus how to handle these patches covering both areas.
OK, I'll add all the bits that apply to my patch queue for you. Hopefully we shouldn't find too many changes that need to touch both sides of things. For those that do hopefully we can do something similar to what we do with ARM and agree to merge both via one of the trees.
BTW, I'll be on vacation for the next week, so the reply will be delayed.
Enjoy your holiday!
participants (3)
-
Dmitry Torokhov
-
Mark Brown
-
Takashi Iwai