diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-02-02 23:22:20 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-02-02 23:22:20 -0300 |
commit | 5c545e1fb127a4b11ddc5f1a5ed066b853dd1a1a (patch) | |
tree | d4cd913bc79d37d32756a9bffbeedabf93e32579 /sound | |
parent | b4b7ff4b08e691656c9d77c758fc355833128ac0 (diff) |
Linux-libre 4.4.1-gnupck-4.4.1-gnu
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/control.c | 2 | ||||
-rw-r--r-- | sound/core/hrtimer.c | 3 | ||||
-rw-r--r-- | sound/core/pcm_compat.c | 13 | ||||
-rw-r--r-- | sound/core/seq/seq_clientmgr.c | 2 | ||||
-rw-r--r-- | sound/core/seq/seq_compat.c | 9 | ||||
-rw-r--r-- | sound/core/seq/seq_queue.c | 2 | ||||
-rw-r--r-- | sound/core/timer.c | 100 | ||||
-rw-r--r-- | sound/pci/hda/hda_bind.c | 42 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 10 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 15 | ||||
-rw-r--r-- | sound/soc/codecs/wm5110.c | 8 | ||||
-rw-r--r-- | sound/soc/soc-compress.c | 23 | ||||
-rw-r--r-- | sound/usb/card.c | 2 | ||||
-rw-r--r-- | sound/usb/mixer_quirks.c | 2 | ||||
-rw-r--r-- | sound/usb/quirks.c | 1 |
15 files changed, 186 insertions, 48 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index 196a6fe10..a85d45595 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1405,6 +1405,8 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file, return -EFAULT; if (tlv.length < sizeof(unsigned int) * 2) return -EINVAL; + if (!tlv.numid) + return -EINVAL; down_read(&card->controls_rwsem); kctl = snd_ctl_find_numid(card, tlv.numid); if (kctl == NULL) { diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index f845ecf7e..656d9a903 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c @@ -90,7 +90,7 @@ static int snd_hrtimer_start(struct snd_timer *t) struct snd_hrtimer *stime = t->private_data; atomic_set(&stime->running, 0); - hrtimer_cancel(&stime->hrt); + hrtimer_try_to_cancel(&stime->hrt); hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution), HRTIMER_MODE_REL); atomic_set(&stime->running, 1); @@ -101,6 +101,7 @@ static int snd_hrtimer_stop(struct snd_timer *t) { struct snd_hrtimer *stime = t->private_data; atomic_set(&stime->running, 0); + hrtimer_try_to_cancel(&stime->hrt); return 0; } diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index b48b43444..9630e9f72 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -255,10 +255,15 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, if (! (runtime = substream->runtime)) return -ENOTTY; - /* only fifo_size is different, so just copy all */ - data = memdup_user(data32, sizeof(*data32)); - if (IS_ERR(data)) - return PTR_ERR(data); + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* only fifo_size (RO from userspace) is different, so just copy all */ + if (copy_from_user(data, data32, sizeof(*data32))) { + err = -EFAULT; + goto error; + } if (refine) err = snd_pcm_hw_refine(substream, data); diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index b64f20deb..13cfa8157 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1962,7 +1962,7 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, * No restrictions so for a user client we can clear * the whole fifo */ - if (client->type == USER_CLIENT) + if (client->type == USER_CLIENT && client->data.user.fifo) snd_seq_fifo_clear(client->data.user.fifo); } diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c index 81f7c109d..65175902a 100644 --- a/sound/core/seq/seq_compat.c +++ b/sound/core/seq/seq_compat.c @@ -49,11 +49,12 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned struct snd_seq_port_info *data; mm_segment_t fs; - data = memdup_user(data32, sizeof(*data32)); - if (IS_ERR(data)) - return PTR_ERR(data); + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; - if (get_user(data->flags, &data32->flags) || + if (copy_from_user(data, data32, sizeof(*data32)) || + get_user(data->flags, &data32->flags) || get_user(data->time_queue, &data32->time_queue)) goto error; data->kernel = NULL; diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index 7dfd0f429..0bec02e89 100644 --- a/sound/core/seq/seq_queue.c +++ b/sound/core/seq/seq_queue.c @@ -142,8 +142,10 @@ static struct snd_seq_queue *queue_new(int owner, int locked) static void queue_delete(struct snd_seq_queue *q) { /* stop and release the timer */ + mutex_lock(&q->timer_mutex); snd_seq_timer_stop(q->timer); snd_seq_timer_close(q); + mutex_unlock(&q->timer_mutex); /* wait until access free */ snd_use_lock_sync(&q->use_lock); /* release resources... */ diff --git a/sound/core/timer.c b/sound/core/timer.c index 31f40f03e..0a049c457 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -65,6 +65,7 @@ struct snd_timer_user { int qtail; int qused; int queue_size; + bool disconnected; struct snd_timer_read *queue; struct snd_timer_tread *tqueue; spinlock_t qlock; @@ -73,7 +74,7 @@ struct snd_timer_user { struct timespec tstamp; /* trigger tstamp */ wait_queue_head_t qchange_sleep; struct fasync_struct *fasync; - struct mutex tread_sem; + struct mutex ioctl_lock; }; /* list of timers */ @@ -215,11 +216,13 @@ static void snd_timer_check_master(struct snd_timer_instance *master) slave->slave_id == master->slave_id) { list_move_tail(&slave->open_list, &master->slave_list_head); spin_lock_irq(&slave_active_lock); + spin_lock(&master->timer->lock); slave->master = master; slave->timer = master->timer; if (slave->flags & SNDRV_TIMER_IFLG_RUNNING) list_add_tail(&slave->active_list, &master->slave_active_head); + spin_unlock(&master->timer->lock); spin_unlock_irq(&slave_active_lock); } } @@ -288,6 +291,9 @@ int snd_timer_open(struct snd_timer_instance **ti, mutex_unlock(®ister_mutex); return -ENOMEM; } + /* take a card refcount for safe disconnection */ + if (timer->card) + get_device(&timer->card->card_dev); timeri->slave_class = tid->dev_sclass; timeri->slave_id = slave_id; if (list_empty(&timer->open_list_head) && timer->hw.open) @@ -346,15 +352,21 @@ int snd_timer_close(struct snd_timer_instance *timeri) timer->hw.close) timer->hw.close(timer); /* remove slave links */ + spin_lock_irq(&slave_active_lock); + spin_lock(&timer->lock); list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head, open_list) { - spin_lock_irq(&slave_active_lock); - _snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION); list_move_tail(&slave->open_list, &snd_timer_slave_list); slave->master = NULL; slave->timer = NULL; - spin_unlock_irq(&slave_active_lock); + list_del_init(&slave->ack_list); + list_del_init(&slave->active_list); } + spin_unlock(&timer->lock); + spin_unlock_irq(&slave_active_lock); + /* release a card refcount for safe disconnection */ + if (timer->card) + put_device(&timer->card->card_dev); mutex_unlock(®ister_mutex); } out: @@ -441,9 +453,12 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri) spin_lock_irqsave(&slave_active_lock, flags); timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; - if (timeri->master) + if (timeri->master && timeri->timer) { + spin_lock(&timeri->timer->lock); list_add_tail(&timeri->active_list, &timeri->master->slave_active_head); + spin_unlock(&timeri->timer->lock); + } spin_unlock_irqrestore(&slave_active_lock, flags); return 1; /* delayed start */ } @@ -467,6 +482,8 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks) timer = timeri->timer; if (timer == NULL) return -EINVAL; + if (timer->card && timer->card->shutdown) + return -ENODEV; spin_lock_irqsave(&timer->lock, flags); timeri->ticks = timeri->cticks = ticks; timeri->pticks = 0; @@ -489,6 +506,8 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri, if (!keep_flag) { spin_lock_irqsave(&slave_active_lock, flags); timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; + list_del_init(&timeri->ack_list); + list_del_init(&timeri->active_list); spin_unlock_irqrestore(&slave_active_lock, flags); } goto __end; @@ -499,6 +518,10 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri, spin_lock_irqsave(&timer->lock, flags); list_del_init(&timeri->ack_list); list_del_init(&timeri->active_list); + if (timer->card && timer->card->shutdown) { + spin_unlock_irqrestore(&timer->lock, flags); + return 0; + } if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) && !(--timer->running)) { timer->hw.stop(timer); @@ -561,6 +584,8 @@ int snd_timer_continue(struct snd_timer_instance *timeri) timer = timeri->timer; if (! timer) return -EINVAL; + if (timer->card && timer->card->shutdown) + return -ENODEV; spin_lock_irqsave(&timer->lock, flags); if (!timeri->cticks) timeri->cticks = 1; @@ -624,6 +649,9 @@ static void snd_timer_tasklet(unsigned long arg) unsigned long resolution, ticks; unsigned long flags; + if (timer->card && timer->card->shutdown) + return; + spin_lock_irqsave(&timer->lock, flags); /* now process all callbacks */ while (!list_empty(&timer->sack_list_head)) { @@ -664,6 +692,9 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) if (timer == NULL) return; + if (timer->card && timer->card->shutdown) + return; + spin_lock_irqsave(&timer->lock, flags); /* remember the current resolution */ @@ -694,7 +725,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) } else { ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING; if (--timer->running) - list_del(&ti->active_list); + list_del_init(&ti->active_list); } if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) || (ti->flags & SNDRV_TIMER_IFLG_FAST)) @@ -874,11 +905,28 @@ static int snd_timer_dev_register(struct snd_device *dev) return 0; } +/* just for reference in snd_timer_dev_disconnect() below */ +static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, + int event, struct timespec *tstamp, + unsigned long resolution); + static int snd_timer_dev_disconnect(struct snd_device *device) { struct snd_timer *timer = device->device_data; + struct snd_timer_instance *ti; + mutex_lock(®ister_mutex); list_del_init(&timer->device_list); + /* wake up pending sleepers */ + list_for_each_entry(ti, &timer->open_list_head, open_list) { + /* FIXME: better to have a ti.disconnect() op */ + if (ti->ccallback == snd_timer_user_ccallback) { + struct snd_timer_user *tu = ti->callback_data; + + tu->disconnected = true; + wake_up(&tu->qchange_sleep); + } + } mutex_unlock(®ister_mutex); return 0; } @@ -889,6 +937,8 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam unsigned long resolution = 0; struct snd_timer_instance *ti, *ts; + if (timer->card && timer->card->shutdown) + return; if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)) return; if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_MSTART || @@ -1047,6 +1097,8 @@ static void snd_timer_proc_read(struct snd_info_entry *entry, mutex_lock(®ister_mutex); list_for_each_entry(timer, &snd_timer_list, device_list) { + if (timer->card && timer->card->shutdown) + continue; switch (timer->tmr_class) { case SNDRV_TIMER_CLASS_GLOBAL: snd_iprintf(buffer, "G%i: ", timer->tmr_device); @@ -1253,7 +1305,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file) return -ENOMEM; spin_lock_init(&tu->qlock); init_waitqueue_head(&tu->qchange_sleep); - mutex_init(&tu->tread_sem); + mutex_init(&tu->ioctl_lock); tu->ticks = 1; tu->queue_size = 128; tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read), @@ -1273,8 +1325,10 @@ static int snd_timer_user_release(struct inode *inode, struct file *file) if (file->private_data) { tu = file->private_data; file->private_data = NULL; + mutex_lock(&tu->ioctl_lock); if (tu->timeri) snd_timer_close(tu->timeri); + mutex_unlock(&tu->ioctl_lock); kfree(tu->queue); kfree(tu->tqueue); kfree(tu); @@ -1512,7 +1566,6 @@ static int snd_timer_user_tselect(struct file *file, int err = 0; tu = file->private_data; - mutex_lock(&tu->tread_sem); if (tu->timeri) { snd_timer_close(tu->timeri); tu->timeri = NULL; @@ -1556,7 +1609,6 @@ static int snd_timer_user_tselect(struct file *file, } __err: - mutex_unlock(&tu->tread_sem); return err; } @@ -1769,7 +1821,7 @@ enum { SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23), }; -static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, +static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct snd_timer_user *tu; @@ -1786,17 +1838,11 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, { int xarg; - mutex_lock(&tu->tread_sem); - if (tu->timeri) { /* too late */ - mutex_unlock(&tu->tread_sem); + if (tu->timeri) /* too late */ return -EBUSY; - } - if (get_user(xarg, p)) { - mutex_unlock(&tu->tread_sem); + if (get_user(xarg, p)) return -EFAULT; - } tu->tread = xarg ? 1 : 0; - mutex_unlock(&tu->tread_sem); return 0; } case SNDRV_TIMER_IOCTL_GINFO: @@ -1829,6 +1875,18 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, return -ENOTTY; } +static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct snd_timer_user *tu = file->private_data; + long ret; + + mutex_lock(&tu->ioctl_lock); + ret = __snd_timer_user_ioctl(file, cmd, arg); + mutex_unlock(&tu->ioctl_lock); + return ret; +} + static int snd_timer_user_fasync(int fd, struct file * file, int on) { struct snd_timer_user *tu; @@ -1866,6 +1924,10 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, remove_wait_queue(&tu->qchange_sleep, &wait); + if (tu->disconnected) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -1915,6 +1977,8 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait) mask = 0; if (tu->qused) mask |= POLLIN | POLLRDNORM; + if (tu->disconnected) + mask |= POLLERR; return mask; } diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c index 70671ad65..6efadbfb3 100644 --- a/sound/pci/hda/hda_bind.c +++ b/sound/pci/hda/hda_bind.c @@ -174,14 +174,40 @@ static inline bool codec_probed(struct hda_codec *codec) return device_attach(hda_codec_dev(codec)) > 0 && codec->preset; } -/* try to auto-load and bind the codec module */ -static void codec_bind_module(struct hda_codec *codec) +/* try to auto-load codec module */ +static void request_codec_module(struct hda_codec *codec) { #ifdef MODULE char modalias[32]; + const char *mod = NULL; + + switch (codec->probe_id) { + case HDA_CODEC_ID_GENERIC_HDMI: +#if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI) + mod = "snd-hda-codec-hdmi"; +#endif + break; + case HDA_CODEC_ID_GENERIC: +#if IS_MODULE(CONFIG_SND_HDA_GENERIC) + mod = "snd-hda-codec-generic"; +#endif + break; + default: + snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias)); + mod = modalias; + break; + } + + if (mod) + request_module(mod); +#endif /* MODULE */ +} - snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias)); - request_module(modalias); +/* try to auto-load and bind the codec module */ +static void codec_bind_module(struct hda_codec *codec) +{ +#ifdef MODULE + request_codec_module(codec); if (codec_probed(codec)) return; #endif @@ -218,17 +244,13 @@ static int codec_bind_generic(struct hda_codec *codec) if (is_likely_hdmi_codec(codec)) { codec->probe_id = HDA_CODEC_ID_GENERIC_HDMI; -#if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI) - request_module("snd-hda-codec-hdmi"); -#endif + request_codec_module(codec); if (codec_probed(codec)) return 0; } codec->probe_id = HDA_CODEC_ID_GENERIC; -#if IS_MODULE(CONFIG_SND_HDA_GENERIC) - request_module("snd-hda-codec-generic"); -#endif + request_codec_module(codec); if (codec_probed(codec)) return 0; return -ENODEV; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 3b3658297..614baff1f 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2126,9 +2126,17 @@ i915_power_fail: static void azx_remove(struct pci_dev *pci) { struct snd_card *card = pci_get_drvdata(pci); + struct azx *chip; + struct hda_intel *hda; + + if (card) { + /* flush the pending probing work */ + chip = card->private_data; + hda = container_of(chip, struct hda_intel, chip); + flush_work(&hda->probe_work); - if (card) snd_card_free(card); + } } static void azx_shutdown(struct pci_dev *pci) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3a89d82f8..33753244f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4666,6 +4666,7 @@ enum { ALC290_FIXUP_SUBWOOFER, ALC290_FIXUP_SUBWOOFER_HSJACK, ALC269_FIXUP_THINKPAD_ACPI, + ALC269_FIXUP_DMIC_THINKPAD_ACPI, ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, ALC255_FIXUP_HEADSET_MODE, @@ -5103,6 +5104,12 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = hda_fixup_thinkpad_acpi, }, + [ALC269_FIXUP_DMIC_THINKPAD_ACPI] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_inv_dmic, + .chained = true, + .chain_id = ALC269_FIXUP_THINKPAD_ACPI, + }, [ALC255_FIXUP_DELL1_MIC_NO_PRESENCE] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -5324,6 +5331,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS), SND_PCI_QUIRK(0x1028, 0x05bd, "Dell Latitude E6440", ALC292_FIXUP_DELL_E7X), + SND_PCI_QUIRK(0x1028, 0x05be, "Dell Latitude E6540", ALC292_FIXUP_DELL_E7X), SND_PCI_QUIRK(0x1028, 0x05ca, "Dell Latitude E7240", ALC292_FIXUP_DELL_E7X), SND_PCI_QUIRK(0x1028, 0x05cb, "Dell Latitude E7440", ALC292_FIXUP_DELL_E7X), SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER), @@ -5332,6 +5340,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), + SND_PCI_QUIRK(0x1028, 0x062c, "Dell Latitude E5550", ALC292_FIXUP_DELL_E7X), SND_PCI_QUIRK(0x1028, 0x062e, "Dell Latitude E7450", ALC292_FIXUP_DELL_E7X), SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK), SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), @@ -5457,6 +5466,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK), SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE), SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), + SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP), SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), @@ -5617,6 +5627,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x21, 0x02211040}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, {0x12, 0x90a60170}, + {0x14, 0x90171130}, + {0x21, 0x02211040}), + SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + {0x12, 0x90a60170}, {0x14, 0x90170140}, {0x21, 0x02211050}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell Inspiron 5548", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, @@ -6552,6 +6566,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A), + SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A), SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16), SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16), diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index c04c0bc6f..52b9ccf6d 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -360,15 +360,13 @@ static int wm5110_hp_ev(struct snd_soc_dapm_widget *w, static int wm5110_clear_pga_volume(struct arizona *arizona, int output) { - struct reg_sequence clear_pga = { - ARIZONA_OUTPUT_PATH_CONFIG_1L + output * 4, 0x80 - }; + unsigned int reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + output * 4; int ret; - ret = regmap_multi_reg_write_bypassed(arizona->regmap, &clear_pga, 1); + ret = regmap_write(arizona->regmap, reg, 0x80); if (ret) dev_err(arizona->dev, "Failed to clear PGA (0x%x): %d\n", - clear_pga.reg, ret); + reg, ret); return ret; } diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 12a9820fe..bb82bb966 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -630,6 +630,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) struct snd_pcm *be_pcm; char new_name[64]; int ret = 0, direction = 0; + int playback = 0, capture = 0; if (rtd->num_codecs > 1) { dev_err(rtd->card->dev, "Multicodec not supported for compressed stream\n"); @@ -641,11 +642,27 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) rtd->dai_link->stream_name, codec_dai->name, num); if (codec_dai->driver->playback.channels_min) + playback = 1; + if (codec_dai->driver->capture.channels_min) + capture = 1; + + capture = capture && cpu_dai->driver->capture.channels_min; + playback = playback && cpu_dai->driver->playback.channels_min; + + /* + * Compress devices are unidirectional so only one of the directions + * should be set, check for that (xor) + */ + if (playback + capture != 1) { + dev_err(rtd->card->dev, "Invalid direction for compress P %d, C %d\n", + playback, capture); + return -EINVAL; + } + + if(playback) direction = SND_COMPRESS_PLAYBACK; - else if (codec_dai->driver->capture.channels_min) - direction = SND_COMPRESS_CAPTURE; else - return -EINVAL; + direction = SND_COMPRESS_CAPTURE; compr = kzalloc(sizeof(*compr), GFP_KERNEL); if (compr == NULL) { diff --git a/sound/usb/card.c b/sound/usb/card.c index 18f56646c..1f09d9591 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -675,6 +675,8 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) void snd_usb_autosuspend(struct snd_usb_audio *chip) { + if (atomic_read(&chip->shutdown)) + return; if (atomic_dec_and_test(&chip->active)) usb_autopm_put_interface(chip->pm_intf); } diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 0ce888dce..279025650 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -793,7 +793,7 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, return 0; kcontrol->private_value &= ~(0xff << 24); - kcontrol->private_value |= newval; + kcontrol->private_value |= (unsigned int)newval << 24; err = snd_ni_update_cur_val(list); return err < 0 ? err : 1; } diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index b6c0c8e3b..23ea6d800 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1269,6 +1269,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, case USB_ID(0x20b1, 0x3008): /* iFi Audio micro/nano iDSD */ case USB_ID(0x20b1, 0x2008): /* Matrix Audio X-Sabre */ case USB_ID(0x20b1, 0x300a): /* Matrix Audio Mini-i Pro */ + case USB_ID(0x22d8, 0x0416): /* OPPO HA-1*/ if (fp->altsetting == 2) return SNDRV_PCM_FMTBIT_DSD_U32_BE; break; |