Commit fef66ae7 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: usb-audio: Add connector notifier delegation

It turned out that ALC1220-VB USB-audio device gives the interrupt
event to some PCM terminals while those don't allow the connector
state request but only the actual I/O terminals return the request.
The recent commit 7dc3c5a0 ("ALSA: usb-audio: Don't create jack
controls for PCM terminals") excluded those phantom terminals, so
those events are ignored, too.

My first thought was that this could be easily deduced from the
associated terminals, but some of them have even no associate terminal
ID, hence it's not too trivial to figure out.

Since the number of such terminals are small and limited, this patch
implements another quirk table for the simple mapping of the
connectors.  It's not really scalable, but let's hope that there will
be not many such funky devices in future.

Fixes: 7dc3c5a0 ("ALSA: usb-audio: Don't create jack controls for PCM terminals")
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=206873
Link: https://lore.kernel.org/r/20200422113320.26664-1-tiwai@suse.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent e7b6b3ec
...@@ -3117,6 +3117,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) ...@@ -3117,6 +3117,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
if (map->id == state.chip->usb_id) { if (map->id == state.chip->usb_id) {
state.map = map->map; state.map = map->map;
state.selector_map = map->selector_map; state.selector_map = map->selector_map;
mixer->connector_map = map->connector_map;
mixer->ignore_ctl_error |= map->ignore_ctl_error; mixer->ignore_ctl_error |= map->ignore_ctl_error;
break; break;
} }
...@@ -3198,10 +3199,32 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) ...@@ -3198,10 +3199,32 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
return 0; return 0;
} }
static int delegate_notify(struct usb_mixer_interface *mixer, int unitid,
u8 *control, u8 *channel)
{
const struct usbmix_connector_map *map = mixer->connector_map;
if (!map)
return unitid;
for (; map->id; map++) {
if (map->id == unitid) {
if (control && map->control)
*control = map->control;
if (channel && map->channel)
*channel = map->channel;
return map->delegated_id;
}
}
return unitid;
}
void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid) void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
{ {
struct usb_mixer_elem_list *list; struct usb_mixer_elem_list *list;
unitid = delegate_notify(mixer, unitid, NULL, NULL);
for_each_mixer_elem(list, mixer, unitid) { for_each_mixer_elem(list, mixer, unitid) {
struct usb_mixer_elem_info *info = struct usb_mixer_elem_info *info =
mixer_elem_list_to_info(list); mixer_elem_list_to_info(list);
...@@ -3271,6 +3294,8 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, ...@@ -3271,6 +3294,8 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
return; return;
} }
unitid = delegate_notify(mixer, unitid, &control, &channel);
for_each_mixer_elem(list, mixer, unitid) for_each_mixer_elem(list, mixer, unitid)
count++; count++;
......
...@@ -6,6 +6,13 @@ ...@@ -6,6 +6,13 @@
struct media_mixer_ctl; struct media_mixer_ctl;
struct usbmix_connector_map {
u8 id;
u8 delegated_id;
u8 control;
u8 channel;
};
struct usb_mixer_interface { struct usb_mixer_interface {
struct snd_usb_audio *chip; struct snd_usb_audio *chip;
struct usb_host_interface *hostif; struct usb_host_interface *hostif;
...@@ -18,6 +25,9 @@ struct usb_mixer_interface { ...@@ -18,6 +25,9 @@ struct usb_mixer_interface {
/* the usb audio specification version this interface complies to */ /* the usb audio specification version this interface complies to */
int protocol; int protocol;
/* optional connector delegation map */
const struct usbmix_connector_map *connector_map;
/* Sound Blaster remote control stuff */ /* Sound Blaster remote control stuff */
const struct rc_config *rc_cfg; const struct rc_config *rc_cfg;
u32 rc_code; u32 rc_code;
......
...@@ -27,6 +27,7 @@ struct usbmix_ctl_map { ...@@ -27,6 +27,7 @@ struct usbmix_ctl_map {
u32 id; u32 id;
const struct usbmix_name_map *map; const struct usbmix_name_map *map;
const struct usbmix_selector_map *selector_map; const struct usbmix_selector_map *selector_map;
const struct usbmix_connector_map *connector_map;
int ignore_ctl_error; int ignore_ctl_error;
}; };
...@@ -387,6 +388,15 @@ static const struct usbmix_name_map trx40_mobo_map[] = { ...@@ -387,6 +388,15 @@ static const struct usbmix_name_map trx40_mobo_map[] = {
{} {}
}; };
static const struct usbmix_connector_map trx40_mobo_connector_map[] = {
{ 10, 16 }, /* (Back) Speaker */
{ 11, 17 }, /* Front Headphone */
{ 13, 7 }, /* Line */
{ 14, 8 }, /* Mic */
{ 15, 9 }, /* Front Mic */
{}
};
/* /*
* Control map entries * Control map entries
*/ */
...@@ -519,6 +529,7 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = { ...@@ -519,6 +529,7 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
{ /* Gigabyte TRX40 Aorus Pro WiFi */ { /* Gigabyte TRX40 Aorus Pro WiFi */
.id = USB_ID(0x0414, 0xa002), .id = USB_ID(0x0414, 0xa002),
.map = trx40_mobo_map, .map = trx40_mobo_map,
.connector_map = trx40_mobo_connector_map,
}, },
{ /* ASUS ROG Zenith II */ { /* ASUS ROG Zenith II */
.id = USB_ID(0x0b05, 0x1916), .id = USB_ID(0x0b05, 0x1916),
...@@ -531,10 +542,12 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = { ...@@ -531,10 +542,12 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
{ /* MSI TRX40 Creator */ { /* MSI TRX40 Creator */
.id = USB_ID(0x0db0, 0x0d64), .id = USB_ID(0x0db0, 0x0d64),
.map = trx40_mobo_map, .map = trx40_mobo_map,
.connector_map = trx40_mobo_connector_map,
}, },
{ /* MSI TRX40 */ { /* MSI TRX40 */
.id = USB_ID(0x0db0, 0x543d), .id = USB_ID(0x0db0, 0x543d),
.map = trx40_mobo_map, .map = trx40_mobo_map,
.connector_map = trx40_mobo_connector_map,
}, },
{ 0 } /* terminator */ { 0 } /* terminator */
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment