Commit 484faec8 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-5.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "A collection of small fixes:

   - A few regression fixes (PCM core fixes, USB-audio fixes)

   - Follow up fixes for the USB-audio mixer changes in this cycle

   - A long-standing ALSA sequencer race bug fix

   - Usual device-specific quirks for HD- and USB-audio"

* tag 'sound-5.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: seq: Fix racy deletion of subscriber
  ALSA: memalloc: Fix regression with SNDRV_DMA_TYPE_CONTINUOUS
  ALSA: pcm - fix mmap capability check for the snd-dummy driver
  ALSA: usb-audio: Avoid unnecessary or invalid connector selection at resume
  ALSA: hda/realtek: add mic quirk for Acer SF314-42
  ALSA: usb-audio: Add registration quirk for JBL Quantum 600
  ALSA: hda/realtek: Fix headset mic for Acer SWIFT SF314-56 (ALC256)
  ALSA: usb-audio: Fix superfluous autosuspend recovery
  ALSA: usb-audio: fix incorrect clock source setting
  ALSA: scarlett2: Fix line out/speaker switching notifications
  ALSA: scarlett2: Correct channel mute status after mute button pressed
  ALSA: scarlett2: Fix Direct Monitor control name for 2i2
  ALSA: scarlett2: Fix Mute/Dim/MSD Mode control names
parents 1254f05c 97367c97
......@@ -215,7 +215,7 @@ static int snd_dma_continuous_mmap(struct snd_dma_buffer *dmab,
struct vm_area_struct *area)
{
return remap_pfn_range(area, area->vm_start,
dmab->addr >> PAGE_SHIFT,
page_to_pfn(virt_to_page(dmab->area)),
area->vm_end - area->vm_start,
area->vm_page_prot);
}
......
......@@ -246,7 +246,7 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP))
return false;
if (substream->ops->mmap)
if (substream->ops->mmap || substream->ops->page)
return true;
switch (substream->dma_buffer.dev.type) {
......
......@@ -514,10 +514,11 @@ static int check_and_subscribe_port(struct snd_seq_client *client,
return err;
}
static void delete_and_unsubscribe_port(struct snd_seq_client *client,
struct snd_seq_client_port *port,
struct snd_seq_subscribers *subs,
bool is_src, bool ack)
/* called with grp->list_mutex held */
static void __delete_and_unsubscribe_port(struct snd_seq_client *client,
struct snd_seq_client_port *port,
struct snd_seq_subscribers *subs,
bool is_src, bool ack)
{
struct snd_seq_port_subs_info *grp;
struct list_head *list;
......@@ -525,7 +526,6 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client,
grp = is_src ? &port->c_src : &port->c_dest;
list = is_src ? &subs->src_list : &subs->dest_list;
down_write(&grp->list_mutex);
write_lock_irq(&grp->list_lock);
empty = list_empty(list);
if (!empty)
......@@ -535,6 +535,18 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client,
if (!empty)
unsubscribe_port(client, port, grp, &subs->info, ack);
}
static void delete_and_unsubscribe_port(struct snd_seq_client *client,
struct snd_seq_client_port *port,
struct snd_seq_subscribers *subs,
bool is_src, bool ack)
{
struct snd_seq_port_subs_info *grp;
grp = is_src ? &port->c_src : &port->c_dest;
down_write(&grp->list_mutex);
__delete_and_unsubscribe_port(client, port, subs, is_src, ack);
up_write(&grp->list_mutex);
}
......@@ -590,27 +602,30 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector,
struct snd_seq_client_port *dest_port,
struct snd_seq_port_subscribe *info)
{
struct snd_seq_port_subs_info *src = &src_port->c_src;
struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
struct snd_seq_subscribers *subs;
int err = -ENOENT;
down_write(&src->list_mutex);
/* always start from deleting the dest port for avoiding concurrent
* deletions
*/
down_write(&dest->list_mutex);
/* look for the connection */
list_for_each_entry(subs, &src->list_head, src_list) {
list_for_each_entry(subs, &dest->list_head, dest_list) {
if (match_subs_info(info, &subs->info)) {
atomic_dec(&subs->ref_count); /* mark as not ready */
__delete_and_unsubscribe_port(dest_client, dest_port,
subs, false,
connector->number != dest_client->number);
err = 0;
break;
}
}
up_write(&src->list_mutex);
up_write(&dest->list_mutex);
if (err < 0)
return err;
delete_and_unsubscribe_port(src_client, src_port, subs, true,
connector->number != src_client->number);
delete_and_unsubscribe_port(dest_client, dest_port, subs, false,
connector->number != dest_client->number);
kfree(subs);
return 0;
}
......
......@@ -8274,9 +8274,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x129c, "Acer SWIFT SF314-55", ALC256_FIXUP_ACER_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x1300, "Acer SWIFT SF314-56", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x142b, "Acer Swift SF314-42", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC),
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
......
......@@ -907,7 +907,7 @@ static void usb_audio_disconnect(struct usb_interface *intf)
}
}
if (chip->quirk_type & QUIRK_SETUP_DISABLE_AUTOSUSPEND)
if (chip->quirk_type == QUIRK_SETUP_DISABLE_AUTOSUSPEND)
usb_enable_autosuspend(interface_to_usbdev(intf));
chip->num_interfaces--;
......
......@@ -324,6 +324,12 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
sources[ret - 1],
visited, validate);
if (ret > 0) {
/*
* For Samsung USBC Headset (AKG), setting clock selector again
* will result in incorrect default clock setting problems
*/
if (chip->usb_id == USB_ID(0x04e8, 0xa051))
return ret;
err = uac_clock_selector_set_val(chip, entity_id, cur);
if (err < 0)
return err;
......
......@@ -1816,6 +1816,15 @@ static void get_connector_control_name(struct usb_mixer_interface *mixer,
strlcat(name, " - Output Jack", name_size);
}
/* get connector value to "wake up" the USB audio */
static int connector_mixer_resume(struct usb_mixer_elem_list *list)
{
struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
get_connector_value(cval, NULL, NULL);
return 0;
}
/* Build a mixer control for a UAC connector control (jack-detect) */
static void build_connector_control(struct usb_mixer_interface *mixer,
const struct usbmix_name_map *imap,
......@@ -1833,6 +1842,10 @@ static void build_connector_control(struct usb_mixer_interface *mixer,
if (!cval)
return;
snd_usb_mixer_elem_init_std(&cval->head, mixer, term->id);
/* set up a specific resume callback */
cval->head.resume = connector_mixer_resume;
/*
* UAC2: The first byte from reading the UAC2_TE_CONNECTOR control returns the
* number of channels connected.
......@@ -3642,23 +3655,15 @@ static int restore_mixer_value(struct usb_mixer_elem_list *list)
return 0;
}
static int default_mixer_resume(struct usb_mixer_elem_list *list)
{
struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
/* get connector value to "wake up" the USB audio */
if (cval->val_type == USB_MIXER_BOOLEAN && cval->channels == 1)
get_connector_value(cval, NULL, NULL);
return 0;
}
static int default_mixer_reset_resume(struct usb_mixer_elem_list *list)
{
int err = default_mixer_resume(list);
int err;
if (err < 0)
return err;
if (list->resume) {
err = list->resume(list);
if (err < 0)
return err;
}
return restore_mixer_value(list);
}
......@@ -3697,7 +3702,7 @@ void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list,
list->id = unitid;
list->dump = snd_usb_mixer_dump_cval;
#ifdef CONFIG_PM
list->resume = default_mixer_resume;
list->resume = NULL;
list->reset_resume = default_mixer_reset_resume;
#endif
}
......@@ -228,7 +228,7 @@ enum {
};
static const char *const scarlett2_dim_mute_names[SCARLETT2_DIM_MUTE_COUNT] = {
"Mute", "Dim"
"Mute Playback Switch", "Dim Playback Switch"
};
/* Description of each hardware port type:
......@@ -1856,9 +1856,15 @@ static int scarlett2_mute_ctl_get(struct snd_kcontrol *kctl,
struct snd_ctl_elem_value *ucontrol)
{
struct usb_mixer_elem_info *elem = kctl->private_data;
struct scarlett2_data *private = elem->head.mixer->private_data;
struct usb_mixer_interface *mixer = elem->head.mixer;
struct scarlett2_data *private = mixer->private_data;
int index = line_out_remap(private, elem->control);
mutex_lock(&private->data_mutex);
if (private->vol_updated)
scarlett2_update_volumes(mixer);
mutex_unlock(&private->data_mutex);
ucontrol->value.integer.value[0] = private->mute_switch[index];
return 0;
}
......@@ -1955,10 +1961,12 @@ static void scarlett2_vol_ctl_set_writable(struct usb_mixer_interface *mixer,
~SNDRV_CTL_ELEM_ACCESS_WRITE;
}
/* Notify of write bit change */
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
/* Notify of write bit and possible value change */
snd_ctl_notify(card,
SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
&private->vol_ctls[index]->id);
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
snd_ctl_notify(card,
SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
&private->mute_ctls[index]->id);
}
......@@ -2530,14 +2538,18 @@ static int scarlett2_add_direct_monitor_ctl(struct usb_mixer_interface *mixer)
{
struct scarlett2_data *private = mixer->private_data;
const struct scarlett2_device_info *info = private->info;
const char *s;
if (!info->direct_monitor)
return 0;
s = info->direct_monitor == 1
? "Direct Monitor Playback Switch"
: "Direct Monitor Playback Enum";
return scarlett2_add_new_ctl(
mixer, &scarlett2_direct_monitor_ctl[info->direct_monitor - 1],
0, 1, "Direct Monitor Playback Switch",
&private->direct_monitor_ctl);
0, 1, s, &private->direct_monitor_ctl);
}
/*** Speaker Switching Control ***/
......@@ -2589,7 +2601,9 @@ static int scarlett2_speaker_switch_enable(struct usb_mixer_interface *mixer)
/* disable the line out SW/HW switch */
scarlett2_sw_hw_ctl_ro(private, i);
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
snd_ctl_notify(card,
SNDRV_CTL_EVENT_MASK_VALUE |
SNDRV_CTL_EVENT_MASK_INFO,
&private->sw_hw_ctls[i]->id);
}
......@@ -2913,7 +2927,7 @@ static int scarlett2_dim_mute_ctl_put(struct snd_kcontrol *kctl,
if (private->vol_sw_hw_switch[line_index]) {
private->mute_switch[line_index] = val;
snd_ctl_notify(mixer->chip->card,
SNDRV_CTL_EVENT_MASK_INFO,
SNDRV_CTL_EVENT_MASK_VALUE,
&private->mute_ctls[i]->id);
}
}
......@@ -3455,7 +3469,7 @@ static int scarlett2_add_msd_ctl(struct usb_mixer_interface *mixer)
/* Add MSD control */
return scarlett2_add_new_ctl(mixer, &scarlett2_msd_ctl,
0, 1, "MSD Mode", NULL);
0, 1, "MSD Mode Switch", NULL);
}
/*** Cleanup/Suspend Callbacks ***/
......
......@@ -1899,6 +1899,7 @@ static const struct registration_quirk registration_quirks[] = {
REG_QUIRK_ENTRY(0x0951, 0x16ea, 2), /* Kingston HyperX Cloud Flight S */
REG_QUIRK_ENTRY(0x0ecb, 0x1f46, 2), /* JBL Quantum 600 */
REG_QUIRK_ENTRY(0x0ecb, 0x2039, 2), /* JBL Quantum 400 */
REG_QUIRK_ENTRY(0x0ecb, 0x203c, 2), /* JBL Quantum 600 */
REG_QUIRK_ENTRY(0x0ecb, 0x203e, 2), /* JBL Quantum 800 */
{ 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