Merge branch 'for-next' into for-linus

This commit is contained in:
Takashi Iwai 2020-10-12 08:51:00 +02:00
commit 4dda3a1914
50 changed files with 2097 additions and 887 deletions

View File

@ -117,6 +117,10 @@ struct drm_audio_component {
* @audio_ops: Ops implemented by hda driver, called by DRM driver
*/
const struct drm_audio_component_audio_ops *audio_ops;
/**
* @master_bind_complete: completion held during component master binding
*/
struct completion master_bind_complete;
};
#endif /* _DRM_AUDIO_COMPONENT_H_ */

View File

@ -23,11 +23,6 @@ int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
#define MASK_OFS(i) ((i) >> 5)
#define MASK_BIT(i) (1U << ((i) & 31))
static inline size_t snd_mask_sizeof(void)
{
return sizeof(struct snd_mask);
}
static inline void snd_mask_none(struct snd_mask *mask)
{
memset(mask, 0, sizeof(*mask));

View File

@ -21,13 +21,13 @@
#define SNDRV_TIMER_HW_STOP 0x00000002 /* call stop before start */
#define SNDRV_TIMER_HW_SLAVE 0x00000004 /* only slave timer (variable resolution) */
#define SNDRV_TIMER_HW_FIRST 0x00000008 /* first tick can be incomplete */
#define SNDRV_TIMER_HW_TASKLET 0x00000010 /* timer is called from tasklet */
#define SNDRV_TIMER_HW_WORK 0x00000010 /* timer is called from work */
#define SNDRV_TIMER_IFLG_SLAVE 0x00000001
#define SNDRV_TIMER_IFLG_RUNNING 0x00000002
#define SNDRV_TIMER_IFLG_START 0x00000004
#define SNDRV_TIMER_IFLG_AUTO 0x00000008 /* auto restart */
#define SNDRV_TIMER_IFLG_FAST 0x00000010 /* fast callback (do not use tasklet) */
#define SNDRV_TIMER_IFLG_FAST 0x00000010 /* fast callback (do not use work) */
#define SNDRV_TIMER_IFLG_CALLBACK 0x00000020 /* timer callback is active */
#define SNDRV_TIMER_IFLG_EXCLUSIVE 0x00000040 /* exclusive owner - no more instances */
#define SNDRV_TIMER_IFLG_EARLY_EVENT 0x00000080 /* write early event to the poll queue */
@ -74,7 +74,7 @@ struct snd_timer {
struct list_head active_list_head;
struct list_head ack_list_head;
struct list_head sack_list_head; /* slow ack list head */
struct tasklet_struct task_queue;
struct work_struct task_work;
int max_instances; /* upper limit of timer instances */
int num_instances; /* current number of timer instances */
};
@ -96,7 +96,7 @@ struct snd_timer_instance {
unsigned long ticks; /* auto-load ticks when expired */
unsigned long cticks; /* current ticks */
unsigned long pticks; /* accumulated ticks for callback */
unsigned long resolution; /* current resolution for tasklet */
unsigned long resolution; /* current resolution for work */
unsigned long lost; /* lost ticks */
int slave_class;
unsigned int slave_id;

View File

@ -3,7 +3,7 @@
* Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr>
*/
unsigned int snd_ac97_bus_scan_one(struct ac97_controller *ac97,
unsigned int snd_ac97_bus_scan_one(struct ac97_controller *adrv,
unsigned int codec_num);
static inline bool ac97_ids_match(unsigned int id1, unsigned int id2,

View File

@ -254,12 +254,11 @@ static void i2sbus_wait_for_stop(struct i2sbus_dev *i2sdev,
struct pcm_info *pi)
{
unsigned long flags;
struct completion done;
DECLARE_COMPLETION_ONSTACK(done);
long timeout;
spin_lock_irqsave(&i2sdev->low_lock, flags);
if (pi->dbdma_ring.stopping) {
init_completion(&done);
pi->stop_completion = &done;
spin_unlock_irqrestore(&i2sdev->low_lock, flags);
timeout = wait_for_completion_timeout(&done, HZ);

View File

@ -475,11 +475,11 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev)
struct snd_pcm_runtime *runtime;
int offset, next_period, block_size;
dev_dbg(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n",
casr & AC97C_CSR_OVRUN ? " OVRUN" : "",
casr & AC97C_CSR_RXRDY ? " RXRDY" : "",
casr & AC97C_CSR_UNRUN ? " UNRUN" : "",
casr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "",
casr & AC97C_CSR_TXRDY ? " TXRDY" : "",
(casr & AC97C_CSR_OVRUN) ? " OVRUN" : "",
(casr & AC97C_CSR_RXRDY) ? " RXRDY" : "",
(casr & AC97C_CSR_UNRUN) ? " UNRUN" : "",
(casr & AC97C_CSR_TXEMPTY) ? " TXEMPTY" : "",
(casr & AC97C_CSR_TXRDY) ? " TXRDY" : "",
!casr ? " NONE" : "");
if ((casr & camr) & AC97C_CSR_ENDTX) {
runtime = chip->playback_substream->runtime;
@ -521,10 +521,10 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev)
if (sr & AC97C_SR_COEVT) {
dev_info(&chip->pdev->dev, "codec channel event%s%s%s%s%s\n",
cosr & AC97C_CSR_OVRUN ? " OVRUN" : "",
cosr & AC97C_CSR_RXRDY ? " RXRDY" : "",
cosr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "",
cosr & AC97C_CSR_TXRDY ? " TXRDY" : "",
(cosr & AC97C_CSR_OVRUN) ? " OVRUN" : "",
(cosr & AC97C_CSR_RXRDY) ? " RXRDY" : "",
(cosr & AC97C_CSR_TXEMPTY) ? " TXEMPTY" : "",
(cosr & AC97C_CSR_TXRDY) ? " TXRDY" : "",
!cosr ? " NONE" : "");
retval = IRQ_HANDLED;
}

View File

@ -513,10 +513,11 @@ EXPORT_SYMBOL(snd_compr_malloc_pages);
int snd_compr_free_pages(struct snd_compr_stream *stream)
{
struct snd_compr_runtime *runtime = stream->runtime;
struct snd_compr_runtime *runtime;
if (snd_BUG_ON(!(stream) || !(stream)->runtime))
return -EINVAL;
runtime = stream->runtime;
if (runtime->dma_area == NULL)
return 0;
if (runtime->dma_buffer_p != &stream->dma_buffer) {
@ -1031,7 +1032,7 @@ static const struct file_operations snd_compr_file_ops = {
static int snd_compress_dev_register(struct snd_device *device)
{
int ret = -EINVAL;
int ret;
struct snd_compr *compr;
if (snd_BUG_ON(!device || !device->device_data))

View File

@ -150,14 +150,14 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
return;
if (card->shutdown)
return;
read_lock(&card->ctl_files_rwlock);
read_lock_irqsave(&card->ctl_files_rwlock, flags);
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
card->mixer_oss_change_count++;
#endif
list_for_each_entry(ctl, &card->ctl_files, list) {
if (!ctl->subscribed)
continue;
spin_lock_irqsave(&ctl->read_lock, flags);
spin_lock(&ctl->read_lock);
list_for_each_entry(ev, &ctl->events, list) {
if (ev->id.numid == id->numid) {
ev->mask |= mask;
@ -174,10 +174,10 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
}
_found:
wake_up(&ctl->change_sleep);
spin_unlock_irqrestore(&ctl->read_lock, flags);
spin_unlock(&ctl->read_lock);
kill_fasync(&ctl->fasync, SIGIO, POLL_IN);
}
read_unlock(&card->ctl_files_rwlock);
read_unlock_irqrestore(&card->ctl_files_rwlock, flags);
}
EXPORT_SYMBOL(snd_ctl_notify);
@ -717,22 +717,19 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
}
static int snd_ctl_elem_list(struct snd_card *card,
struct snd_ctl_elem_list __user *_list)
struct snd_ctl_elem_list *list)
{
struct snd_ctl_elem_list list;
struct snd_kcontrol *kctl;
struct snd_ctl_elem_id id;
unsigned int offset, space, jidx;
int err = 0;
if (copy_from_user(&list, _list, sizeof(list)))
return -EFAULT;
offset = list.offset;
space = list.space;
offset = list->offset;
space = list->space;
down_read(&card->controls_rwsem);
list.count = card->controls_count;
list.used = 0;
list->count = card->controls_count;
list->used = 0;
if (space > 0) {
list_for_each_entry(kctl, &card->controls, list) {
if (offset >= kctl->count) {
@ -741,12 +738,12 @@ static int snd_ctl_elem_list(struct snd_card *card,
}
for (jidx = offset; jidx < kctl->count; jidx++) {
snd_ctl_build_ioff(&id, kctl, jidx);
if (copy_to_user(list.pids + list.used, &id,
if (copy_to_user(list->pids + list->used, &id,
sizeof(id))) {
err = -EFAULT;
goto out;
}
list.used++;
list->used++;
if (!--space)
goto out;
}
@ -755,11 +752,26 @@ static int snd_ctl_elem_list(struct snd_card *card,
}
out:
up_read(&card->controls_rwsem);
if (!err && copy_to_user(_list, &list, sizeof(list)))
err = -EFAULT;
return err;
}
static int snd_ctl_elem_list_user(struct snd_card *card,
struct snd_ctl_elem_list __user *_list)
{
struct snd_ctl_elem_list list;
int err;
if (copy_from_user(&list, _list, sizeof(list)))
return -EFAULT;
err = snd_ctl_elem_list(card, &list);
if (err)
return err;
if (copy_to_user(_list, &list, sizeof(list)))
return -EFAULT;
return 0;
}
/* Check whether the given kctl info is valid */
static int snd_ctl_check_elem_info(struct snd_card *card,
const struct snd_ctl_elem_info *info)
@ -1703,7 +1715,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
case SNDRV_CTL_IOCTL_CARD_INFO:
return snd_ctl_card_info(card, ctl, cmd, argp);
case SNDRV_CTL_IOCTL_ELEM_LIST:
return snd_ctl_elem_list(card, argp);
return snd_ctl_elem_list_user(card, argp);
case SNDRV_CTL_IOCTL_ELEM_INFO:
return snd_ctl_elem_info_user(ctl, argp);
case SNDRV_CTL_IOCTL_ELEM_READ:
@ -1939,8 +1951,9 @@ int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type)
{
struct snd_ctl_file *kctl;
int subdevice = -1;
unsigned long flags;
read_lock(&card->ctl_files_rwlock);
read_lock_irqsave(&card->ctl_files_rwlock, flags);
list_for_each_entry(kctl, &card->ctl_files, list) {
if (kctl->pid == task_pid(current)) {
subdevice = kctl->preferred_subdevice[type];
@ -1948,7 +1961,7 @@ int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type)
break;
}
}
read_unlock(&card->ctl_files_rwlock);
read_unlock_irqrestore(&card->ctl_files_rwlock, flags);
return subdevice;
}
EXPORT_SYMBOL_GPL(snd_ctl_get_preferred_subdevice);
@ -1997,13 +2010,14 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
{
struct snd_card *card = device->device_data;
struct snd_ctl_file *ctl;
unsigned long flags;
read_lock(&card->ctl_files_rwlock);
read_lock_irqsave(&card->ctl_files_rwlock, flags);
list_for_each_entry(ctl, &card->ctl_files, list) {
wake_up(&ctl->change_sleep);
kill_fasync(&ctl->fasync, SIGIO, POLL_ERR);
}
read_unlock(&card->ctl_files_rwlock);
read_unlock_irqrestore(&card->ctl_files_rwlock, flags);
return snd_unregister_device(&card->ctl_dev);
}

View File

@ -22,24 +22,22 @@ struct snd_ctl_elem_list32 {
static int snd_ctl_elem_list_compat(struct snd_card *card,
struct snd_ctl_elem_list32 __user *data32)
{
struct snd_ctl_elem_list __user *data;
struct snd_ctl_elem_list data = {};
compat_caddr_t ptr;
int err;
data = compat_alloc_user_space(sizeof(*data));
/* offset, space, used, count */
if (copy_in_user(data, data32, 4 * sizeof(u32)))
if (copy_from_user(&data, data32, 4 * sizeof(u32)))
return -EFAULT;
/* pids */
if (get_user(ptr, &data32->pids) ||
put_user(compat_ptr(ptr), &data->pids))
if (get_user(ptr, &data32->pids))
return -EFAULT;
err = snd_ctl_elem_list(card, data);
data.pids = compat_ptr(ptr);
err = snd_ctl_elem_list(card, &data);
if (err < 0)
return err;
/* copy the result */
if (copy_in_user(data32, data, 4 * sizeof(u32)))
if (copy_to_user(data32, &data, 4 * sizeof(u32)))
return -EFAULT;
return 0;
}

View File

@ -114,7 +114,7 @@ static int snd_hrtimer_stop(struct snd_timer *t)
}
static const struct snd_timer_hardware hrtimer_hw __initconst = {
.flags = SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_TASKLET,
.flags = SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_WORK,
.open = snd_hrtimer_open,
.close = snd_hrtimer_close,
.start = snd_hrtimer_start,

View File

@ -203,28 +203,35 @@ static int snd_hwdep_dsp_status(struct snd_hwdep *hw,
}
static int snd_hwdep_dsp_load(struct snd_hwdep *hw,
struct snd_hwdep_dsp_image __user *_info)
struct snd_hwdep_dsp_image *info)
{
struct snd_hwdep_dsp_image info;
int err;
if (! hw->ops.dsp_load)
return -ENXIO;
memset(&info, 0, sizeof(info));
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
if (info.index >= 32)
if (info->index >= 32)
return -EINVAL;
/* check whether the dsp was already loaded */
if (hw->dsp_loaded & (1u << info.index))
if (hw->dsp_loaded & (1u << info->index))
return -EBUSY;
err = hw->ops.dsp_load(hw, &info);
err = hw->ops.dsp_load(hw, info);
if (err < 0)
return err;
hw->dsp_loaded |= (1u << info.index);
hw->dsp_loaded |= (1u << info->index);
return 0;
}
static int snd_hwdep_dsp_load_user(struct snd_hwdep *hw,
struct snd_hwdep_dsp_image __user *_info)
{
struct snd_hwdep_dsp_image info = {};
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
return snd_hwdep_dsp_load(hw, &info);
}
static long snd_hwdep_ioctl(struct file * file, unsigned int cmd,
unsigned long arg)
{
@ -238,7 +245,7 @@ static long snd_hwdep_ioctl(struct file * file, unsigned int cmd,
case SNDRV_HWDEP_IOCTL_DSP_STATUS:
return snd_hwdep_dsp_status(hw, argp);
case SNDRV_HWDEP_IOCTL_DSP_LOAD:
return snd_hwdep_dsp_load(hw, argp);
return snd_hwdep_dsp_load_user(hw, argp);
}
if (hw->ops.ioctl)
return hw->ops.ioctl(hw, file, cmd, arg);

View File

@ -19,26 +19,17 @@ struct snd_hwdep_dsp_image32 {
static int snd_hwdep_dsp_load_compat(struct snd_hwdep *hw,
struct snd_hwdep_dsp_image32 __user *src)
{
struct snd_hwdep_dsp_image __user *dst;
struct snd_hwdep_dsp_image info = {};
compat_caddr_t ptr;
u32 val;
dst = compat_alloc_user_space(sizeof(*dst));
if (copy_from_user(&info, src, 4 + 64) ||
get_user(ptr, &src->image) ||
get_user(info.length, &src->length) ||
get_user(info.driver_data, &src->driver_data))
return -EFAULT;
info.image = compat_ptr(ptr);
/* index and name */
if (copy_in_user(dst, src, 4 + 64))
return -EFAULT;
if (get_user(ptr, &src->image) ||
put_user(compat_ptr(ptr), &dst->image))
return -EFAULT;
if (get_user(val, &src->length) ||
put_user(val, &dst->length))
return -EFAULT;
if (get_user(val, &src->driver_data) ||
put_user(val, &dst->driver_data))
return -EFAULT;
return snd_hwdep_dsp_load(hw, dst);
return snd_hwdep_dsp_load(hw, &info);
}
enum {

View File

@ -519,10 +519,9 @@ EXPORT_SYMBOL(snd_card_free_when_closed);
*/
int snd_card_free(struct snd_card *card)
{
struct completion released;
DECLARE_COMPLETION_ONSTACK(released);
int ret;
init_completion(&released);
card->release_completion = &released;
ret = snd_card_free_when_closed(card);
if (ret)

View File

@ -157,8 +157,8 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
* so if we fail to malloc, try to fetch memory traditionally.
*/
dmab->dev.type = SNDRV_DMA_TYPE_DEV;
#endif /* CONFIG_GENERIC_ALLOCATOR */
fallthrough;
#endif /* CONFIG_GENERIC_ALLOCATOR */
case SNDRV_DMA_TYPE_DEV:
case SNDRV_DMA_TYPE_DEV_UC:
snd_malloc_dev_pages(dmab, size);

View File

@ -991,11 +991,13 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)));
kfree(runtime->hw_constraints.rules);
/* Avoid concurrent access to runtime via PCM timer interface */
if (substream->timer)
if (substream->timer) {
spin_lock_irq(&substream->timer->lock);
substream->runtime = NULL;
if (substream->timer)
spin_unlock_irq(&substream->timer->lock);
} else {
substream->runtime = NULL;
}
kfree(runtime);
put_pid(substream->pid);
substream->pid = NULL;

View File

@ -377,7 +377,7 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne
*/
int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
{
struct snd_card *card = substream->pcm->card;
struct snd_card *card;
struct snd_pcm_runtime *runtime;
struct snd_dma_buffer *dmab = NULL;
@ -387,6 +387,7 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
SNDRV_DMA_TYPE_UNKNOWN))
return -EINVAL;
runtime = substream->runtime;
card = substream->pcm->card;
if (runtime->dma_buffer_p) {
/* perphaps, we might free the large DMA memory region

View File

@ -35,7 +35,7 @@ module_param_array(amidi_map, int, NULL, 0444);
MODULE_PARM_DESC(amidi_map, "Raw MIDI device number assigned to 2nd OSS device.");
#endif /* CONFIG_SND_OSSEMUL */
static int snd_rawmidi_free(struct snd_rawmidi *rawmidi);
static int snd_rawmidi_free(struct snd_rawmidi *rmidi);
static int snd_rawmidi_dev_free(struct snd_device *device);
static int snd_rawmidi_dev_register(struct snd_device *device);
static int snd_rawmidi_dev_disconnect(struct snd_device *device);

View File

@ -174,8 +174,11 @@ odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (snd_BUG_ON(!dp))
return -ENXIO;
mutex_lock(&register_mutex);
if (cmd != SNDCTL_SEQ_SYNC &&
mutex_lock_interruptible(&register_mutex))
return -ERESTARTSYS;
rc = snd_seq_oss_ioctl(dp, cmd, arg);
if (cmd != SNDCTL_SEQ_SYNC)
mutex_unlock(&register_mutex);
return rc;
}

View File

@ -173,7 +173,7 @@ EXPORT_SYMBOL(snd_timer_instance_free);
*/
static struct snd_timer *snd_timer_find(struct snd_timer_id *tid)
{
struct snd_timer *timer = NULL;
struct snd_timer *timer;
list_for_each_entry(timer, &snd_timer_list, device_list) {
if (timer->tmr_class != tid->dev_class)
@ -813,12 +813,12 @@ static void snd_timer_clear_callbacks(struct snd_timer *timer,
}
/*
* timer tasklet
* timer work
*
*/
static void snd_timer_tasklet(struct tasklet_struct *t)
static void snd_timer_work(struct work_struct *work)
{
struct snd_timer *timer = from_tasklet(timer, t, task_queue);
struct snd_timer *timer = container_of(work, struct snd_timer, task_work);
unsigned long flags;
if (timer->card && timer->card->shutdown) {
@ -843,7 +843,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
unsigned long resolution;
struct list_head *ack_list_head;
unsigned long flags;
int use_tasklet = 0;
bool use_work = false;
if (timer == NULL)
return;
@ -884,7 +884,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
--timer->running;
list_del_init(&ti->active_list);
}
if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
if ((timer->hw.flags & SNDRV_TIMER_HW_WORK) ||
(ti->flags & SNDRV_TIMER_IFLG_FAST))
ack_list_head = &timer->ack_list_head;
else
@ -919,11 +919,11 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
snd_timer_process_callbacks(timer, &timer->ack_list_head);
/* do we have any slow callbacks? */
use_tasklet = !list_empty(&timer->sack_list_head);
use_work = !list_empty(&timer->sack_list_head);
spin_unlock_irqrestore(&timer->lock, flags);
if (use_tasklet)
tasklet_schedule(&timer->task_queue);
if (use_work)
queue_work(system_highpri_wq, &timer->task_work);
}
EXPORT_SYMBOL(snd_timer_interrupt);
@ -967,7 +967,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
INIT_LIST_HEAD(&timer->ack_list_head);
INIT_LIST_HEAD(&timer->sack_list_head);
spin_lock_init(&timer->lock);
tasklet_setup(&timer->task_queue, snd_timer_tasklet);
INIT_WORK(&timer->task_work, snd_timer_work);
timer->max_instances = 1000; /* default limit per timer */
if (card != NULL) {
timer->module = card->module;
@ -1200,7 +1200,7 @@ static int snd_timer_s_close(struct snd_timer *timer)
static const struct snd_timer_hardware snd_timer_system =
{
.flags = SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_TASKLET,
.flags = SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_WORK,
.resolution = 1000000000L / HZ,
.ticks = 10000000L,
.close = snd_timer_s_close,
@ -1280,8 +1280,8 @@ static void snd_timer_proc_read(struct snd_info_entry *entry,
list_for_each_entry(ti, &timer->open_list_head, open_list)
snd_iprintf(buffer, " Client %s : %s\n",
ti->owner ? ti->owner : "unknown",
ti->flags & (SNDRV_TIMER_IFLG_START |
SNDRV_TIMER_IFLG_RUNNING)
(ti->flags & (SNDRV_TIMER_IFLG_START |
SNDRV_TIMER_IFLG_RUNNING))
? "running" : "stopped");
}
mutex_unlock(&register_mutex);

View File

@ -110,7 +110,7 @@ struct loopback_cable {
struct {
int stream;
struct snd_timer_id id;
struct tasklet_struct event_tasklet;
struct work_struct event_work;
struct snd_timer_instance *instance;
} snd_timer;
};
@ -309,8 +309,8 @@ static int loopback_snd_timer_close_cable(struct loopback_pcm *dpcm)
*/
snd_timer_close(cable->snd_timer.instance);
/* wait till drain tasklet has finished if requested */
tasklet_kill(&cable->snd_timer.event_tasklet);
/* wait till drain work has finished if requested */
cancel_work_sync(&cable->snd_timer.event_work);
snd_timer_instance_free(cable->snd_timer.instance);
memset(&cable->snd_timer, 0, sizeof(cable->snd_timer));
@ -794,11 +794,11 @@ static void loopback_snd_timer_function(struct snd_timer_instance *timeri,
resolution);
}
static void loopback_snd_timer_tasklet(unsigned long arg)
static void loopback_snd_timer_work(struct work_struct *work)
{
struct snd_timer_instance *timeri = (struct snd_timer_instance *)arg;
struct loopback_cable *cable = timeri->callback_data;
struct loopback_cable *cable;
cable = container_of(work, struct loopback_cable, snd_timer.event_work);
loopback_snd_timer_period_elapsed(cable, SNDRV_TIMER_EVENT_MSTOP, 0);
}
@ -828,9 +828,9 @@ static void loopback_snd_timer_event(struct snd_timer_instance *timeri,
* state the streaming will be aborted by the usual timeout. It
* should not be aborted here because may be the timer sound
* card does only a recovery and the timer is back soon.
* This tasklet triggers loopback_snd_timer_tasklet()
* This work triggers loopback_snd_timer_work()
*/
tasklet_schedule(&cable->snd_timer.event_tasklet);
schedule_work(&cable->snd_timer.event_work);
}
}
@ -1124,7 +1124,7 @@ static int loopback_snd_timer_open(struct loopback_pcm *dpcm)
err = -ENOMEM;
goto exit;
}
/* The callback has to be called from another tasklet. If
/* The callback has to be called from another work. If
* SNDRV_TIMER_IFLG_FAST is specified it will be called from the
* snd_pcm_period_elapsed() call of the selected sound card.
* snd_pcm_period_elapsed() helds snd_pcm_stream_lock_irqsave().
@ -1137,9 +1137,8 @@ static int loopback_snd_timer_open(struct loopback_pcm *dpcm)
timeri->callback_data = (void *)cable;
timeri->ccallback = loopback_snd_timer_event;
/* initialise a tasklet used for draining */
tasklet_init(&cable->snd_timer.event_tasklet,
loopback_snd_timer_tasklet, (unsigned long)timeri);
/* initialise a work used for draining */
INIT_WORK(&cable->snd_timer.event_work, loopback_snd_timer_work);
/* The mutex loopback->cable_lock is kept locked.
* Therefore snd_timer_open() cannot be called a second time

View File

@ -23,10 +23,10 @@ MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround "
#define DMIX_WANTS_S16 1
/*
* Call snd_pcm_period_elapsed in a tasklet
* Call snd_pcm_period_elapsed in a work
* This avoids spinlock messes and long-running irq contexts
*/
static void pcsp_call_pcm_elapsed(unsigned long priv)
static void pcsp_call_pcm_elapsed(struct work_struct *work)
{
if (atomic_read(&pcsp_chip.timer_active)) {
struct snd_pcm_substream *substream;
@ -36,7 +36,7 @@ static void pcsp_call_pcm_elapsed(unsigned long priv)
}
}
static DECLARE_TASKLET_OLD(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed);
static DECLARE_WORK(pcsp_pcm_work, pcsp_call_pcm_elapsed);
/* write the port and returns the next expire time in ns;
* called at the trigger-start and in hrtimer callback
@ -119,11 +119,9 @@ static void pcsp_pointer_update(struct snd_pcsp *chip)
if (periods_elapsed) {
chip->period_ptr += periods_elapsed * period_bytes;
chip->period_ptr %= buffer_bytes;
queue_work(system_highpri_wq, &pcsp_pcm_work);
}
spin_unlock_irqrestore(&chip->substream_lock, flags);
if (periods_elapsed)
tasklet_schedule(&pcsp_pcm_tasklet);
}
enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
@ -196,7 +194,7 @@ void pcsp_sync_stop(struct snd_pcsp *chip)
pcsp_stop_playing(chip);
local_irq_enable();
hrtimer_cancel(&chip->timer);
tasklet_kill(&pcsp_pcm_tasklet);
cancel_work_sync(&pcsp_pcm_work);
}
static int snd_pcsp_playback_close(struct snd_pcm_substream *substream)

View File

@ -467,7 +467,7 @@ static int portman_probe(struct parport *p)
parport_write_control(p, 0); /* Reset Strobe=0. */
/* Check if Tx circuitry is functioning properly. If initialized
* unit TxEmpty is false, send out char and see if if goes true.
* unit TxEmpty is false, send out char and see if it goes true.
*/
/* 8 */
parport_write_control(p, TXDATA0); /* Tx channel 0, strobe off. */

View File

@ -597,9 +597,9 @@ static void vx_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *b
snd_iprintf(buffer, "%s\n", chip->card->longname);
snd_iprintf(buffer, "Xilinx Firmware: %s\n",
chip->chip_status & VX_STAT_XILINX_LOADED ? "Loaded" : "No");
(chip->chip_status & VX_STAT_XILINX_LOADED) ? "Loaded" : "No");
snd_iprintf(buffer, "Device Initialized: %s\n",
chip->chip_status & VX_STAT_DEVICE_INIT ? "Yes" : "No");
(chip->chip_status & VX_STAT_DEVICE_INIT) ? "Yes" : "No");
snd_iprintf(buffer, "DSP audio info:");
if (chip->audio_info & VX_AUDIO_INFO_REAL_TIME)
snd_iprintf(buffer, " realtime");

View File

@ -60,7 +60,6 @@ static void vx_pcm_read_per_bytes(struct vx_core *chip, struct snd_pcm_runtime *
*buf++ = vx_inb(chip, RXL);
if (++offset >= pipe->buffer_bytes) {
offset = 0;
buf = (unsigned char *)runtime->dma_area;
}
pipe->hw_ptr = offset;
}
@ -530,7 +529,6 @@ static int vx_pcm_playback_open(struct snd_pcm_substream *subs)
err = vx_alloc_pipe(chip, 0, audio, 2, &pipe); /* stereo playback */
if (err < 0)
return err;
chip->playback_pipes[audio] = pipe;
}
/* open for playback */
pipe->references++;

View File

@ -64,7 +64,7 @@
#define IT_PKT_HEADER_SIZE_CIP 8 // For 2 CIP header.
#define IT_PKT_HEADER_SIZE_NO_CIP 0 // Nothing.
static void pcm_period_tasklet(struct tasklet_struct *t);
static void pcm_period_work(struct work_struct *work);
/**
* amdtp_stream_init - initialize an AMDTP stream structure
@ -94,7 +94,7 @@ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit,
s->flags = flags;
s->context = ERR_PTR(-1);
mutex_init(&s->mutex);
tasklet_setup(&s->period_tasklet, pcm_period_tasklet);
INIT_WORK(&s->period_work, pcm_period_work);
s->packet_index = 0;
init_waitqueue_head(&s->callback_wait);
@ -203,7 +203,7 @@ int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s,
// Linux driver for 1394 OHCI controller voluntarily flushes isoc
// context when total size of accumulated context header reaches
// PAGE_SIZE. This kicks tasklet for the isoc context and brings
// PAGE_SIZE. This kicks work for the isoc context and brings
// callback in the middle of scheduled interrupts.
// Although AMDTP streams in the same domain use the same events per
// IRQ, use the largest size of context header between IT/IR contexts.
@ -333,7 +333,7 @@ EXPORT_SYMBOL(amdtp_stream_get_max_payload);
*/
void amdtp_stream_pcm_prepare(struct amdtp_stream *s)
{
tasklet_kill(&s->period_tasklet);
cancel_work_sync(&s->period_work);
s->pcm_buffer_pointer = 0;
s->pcm_period_pointer = 0;
}
@ -437,13 +437,14 @@ static void update_pcm_pointers(struct amdtp_stream *s,
s->pcm_period_pointer += frames;
if (s->pcm_period_pointer >= pcm->runtime->period_size) {
s->pcm_period_pointer -= pcm->runtime->period_size;
tasklet_hi_schedule(&s->period_tasklet);
queue_work(system_highpri_wq, &s->period_work);
}
}
static void pcm_period_tasklet(struct tasklet_struct *t)
static void pcm_period_work(struct work_struct *work)
{
struct amdtp_stream *s = from_tasklet(s, t, period_tasklet);
struct amdtp_stream *s = container_of(work, struct amdtp_stream,
period_work);
struct snd_pcm_substream *pcm = READ_ONCE(s->pcm);
if (pcm)
@ -794,7 +795,7 @@ static void generate_pkt_descs(struct amdtp_stream *s, struct pkt_desc *descs,
static inline void cancel_stream(struct amdtp_stream *s)
{
s->packet_index = -1;
if (in_interrupt())
if (current_work() == &s->period_work)
amdtp_stream_pcm_abort(s);
WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN);
}
@ -1184,7 +1185,7 @@ unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d,
if (irq_target && amdtp_stream_running(irq_target)) {
// This function is called in software IRQ context of
// period_tasklet or process context.
// period_work or process context.
//
// When the software IRQ context was scheduled by software IRQ
// context of IT contexts, queued packets were already handled.
@ -1195,9 +1196,9 @@ unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d,
// immediately to keep better granularity of PCM pointer.
//
// Later, the process context will sometimes schedules software
// IRQ context of the period_tasklet. Then, no need to flush the
// IRQ context of the period_work. Then, no need to flush the
// queue by the same reason as described in the above
if (!in_interrupt()) {
if (current_work() != &s->period_work) {
// Queued packet should be processed without any kernel
// preemption to keep latency against bus cycle.
preempt_disable();
@ -1263,7 +1264,7 @@ static void amdtp_stream_stop(struct amdtp_stream *s)
return;
}
tasklet_kill(&s->period_tasklet);
cancel_work_sync(&s->period_work);
fw_iso_context_stop(s->context);
fw_iso_context_destroy(s->context);
s->context = ERR_PTR(-1);

View File

@ -163,7 +163,7 @@ struct amdtp_stream {
/* For a PCM substream processing. */
struct snd_pcm_substream *pcm;
struct tasklet_struct period_tasklet;
struct work_struct period_work;
snd_pcm_uframes_t pcm_buffer_pointer;
unsigned int pcm_period_pointer;

View File

@ -210,12 +210,14 @@ static int hdac_component_master_bind(struct device *dev)
goto module_put;
}
complete_all(&acomp->master_bind_complete);
return 0;
module_put:
module_put(acomp->ops->owner);
out_unbind:
component_unbind_all(dev, acomp);
complete_all(&acomp->master_bind_complete);
return ret;
}
@ -296,6 +298,7 @@ int snd_hdac_acomp_init(struct hdac_bus *bus,
if (!acomp)
return -ENOMEM;
acomp->audio_ops = aops;
init_completion(&acomp->master_bind_complete);
bus->audio_component = acomp;
devres_add(dev, acomp);

View File

@ -11,9 +11,7 @@
#include <sound/hda_i915.h>
#include <sound/hda_register.h>
static struct completion bind_complete;
#define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \
#define IS_HSW_CONTROLLER(pci) (((pci)->device == 0x0a0c) || \
((pci)->device == 0x0c0c) || \
((pci)->device == 0x0d0c) || \
((pci)->device == 0x160c))
@ -41,7 +39,7 @@ void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
if (!acomp || !acomp->ops || !acomp->ops->get_cdclk_freq)
return; /* only for i915 binding */
if (!CONTROLLER_IN_GPU(pci))
if (!IS_HSW_CONTROLLER(pci))
return; /* only HSW/BDW */
cdclk_freq = acomp->ops->get_cdclk_freq(acomp->dev);
@ -73,11 +71,49 @@ void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
}
EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk);
/* returns true if the devices can be connected for audio */
static bool connectivity_check(struct pci_dev *i915, struct pci_dev *hdac)
{
struct pci_bus *bus_a = i915->bus, *bus_b = hdac->bus;
/* directly connected on the same bus */
if (bus_a == bus_b)
return true;
/*
* on i915 discrete GPUs with embedded HDA audio, the two
* devices are connected via 2nd level PCI bridge
*/
bus_a = bus_a->parent;
bus_b = bus_b->parent;
if (!bus_a || !bus_b)
return false;
bus_a = bus_a->parent;
bus_b = bus_b->parent;
if (bus_a && bus_a == bus_b)
return true;
return false;
}
static int i915_component_master_match(struct device *dev, int subcomponent,
void *data)
{
return !strcmp(dev->driver->name, "i915") &&
subcomponent == I915_COMPONENT_AUDIO;
struct pci_dev *hdac_pci, *i915_pci;
struct hdac_bus *bus = data;
if (!dev_is_pci(dev))
return 0;
hdac_pci = to_pci_dev(bus->dev);
i915_pci = to_pci_dev(dev);
if (!strcmp(dev->driver->name, "i915") &&
subcomponent == I915_COMPONENT_AUDIO &&
connectivity_check(i915_pci, hdac_pci))
return 1;
return 0;
}
/* check whether intel graphics is present */
@ -92,19 +128,6 @@ static bool i915_gfx_present(void)
return pci_dev_present(ids);
}
static int i915_master_bind(struct device *dev,
struct drm_audio_component *acomp)
{
complete_all(&bind_complete);
/* clear audio_ops here as it was needed only for completion call */
acomp->audio_ops = NULL;
return 0;
}
static const struct drm_audio_component_audio_ops i915_init_ops = {
.master_bind = i915_master_bind
};
/**
* snd_hdac_i915_init - Initialize i915 audio component
* @bus: HDA core bus
@ -125,9 +148,7 @@ int snd_hdac_i915_init(struct hdac_bus *bus)
if (!i915_gfx_present())
return -ENODEV;
init_completion(&bind_complete);
err = snd_hdac_acomp_init(bus, &i915_init_ops,
err = snd_hdac_acomp_init(bus, NULL,
i915_component_master_match,
sizeof(struct i915_audio_component) - sizeof(*acomp));
if (err < 0)
@ -139,7 +160,7 @@ int snd_hdac_i915_init(struct hdac_bus *bus)
if (!IS_ENABLED(CONFIG_MODULES) ||
!request_module("i915")) {
/* 60s timeout */
wait_for_completion_timeout(&bind_complete,
wait_for_completion_timeout(&acomp->master_bind_complete,
msecs_to_jiffies(60 * 1000));
}
}

View File

@ -117,7 +117,6 @@ struct snd_card_asihpi {
* snd_card_asihpi_timer_function().
*/
struct snd_card_asihpi_pcm *llmode_streampriv;
struct tasklet_struct t;
void (*pcm_start)(struct snd_pcm_substream *substream);
void (*pcm_stop)(struct snd_pcm_substream *substream);
@ -258,15 +257,6 @@ static inline u16 hpi_stream_group_reset(u32 h_stream)
return hpi_instream_group_reset(h_stream);
}
static inline u16 hpi_stream_group_get_map(
u32 h_stream, u32 *mo, u32 *mi)
{
if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM)
return hpi_outstream_group_get_map(h_stream, mo, mi);
else
return hpi_instream_group_get_map(h_stream, mo, mi);
}
static u16 handle_error(u16 err, int line, char *filename)
{
if (err)
@ -547,9 +537,7 @@ static void snd_card_asihpi_pcm_int_start(struct snd_pcm_substream *substream)
card = snd_pcm_substream_chip(substream);
WARN_ON(in_interrupt());
tasklet_disable(&card->t);
card->llmode_streampriv = dpcm;
tasklet_enable(&card->t);
hpi_handle_error(hpi_adapter_set_property(card->hpi->adapter->index,
HPI_ADAPTER_PROPERTY_IRQ_RATE,
@ -565,13 +553,7 @@ static void snd_card_asihpi_pcm_int_stop(struct snd_pcm_substream *substream)
hpi_handle_error(hpi_adapter_set_property(card->hpi->adapter->index,
HPI_ADAPTER_PROPERTY_IRQ_RATE, 0, 0));
if (in_interrupt())
card->llmode_streampriv = NULL;
else {
tasklet_disable(&card->t);
card->llmode_streampriv = NULL;
tasklet_enable(&card->t);
}
}
static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
@ -921,25 +903,15 @@ static void snd_card_asihpi_timer_function(struct timer_list *t)
add_timer(&dpcm->timer);
}
static void snd_card_asihpi_int_task(struct tasklet_struct *t)
{
struct snd_card_asihpi *asihpi = from_tasklet(asihpi, t, t);
struct hpi_adapter *a = asihpi->hpi;
WARN_ON(!a || !a->snd_card || !a->snd_card->private_data);
asihpi = (struct snd_card_asihpi *)a->snd_card->private_data;
if (asihpi->llmode_streampriv)
snd_card_asihpi_timer_function(
&asihpi->llmode_streampriv->timer);
}
static void snd_card_asihpi_isr(struct hpi_adapter *a)
{
struct snd_card_asihpi *asihpi;
WARN_ON(!a || !a->snd_card || !a->snd_card->private_data);
asihpi = (struct snd_card_asihpi *)a->snd_card->private_data;
tasklet_schedule(&asihpi->t);
if (asihpi->llmode_streampriv)
snd_card_asihpi_timer_function(
&asihpi->llmode_streampriv->timer);
}
/***************************** PLAYBACK OPS ****************/
@ -2871,7 +2843,6 @@ static int snd_asihpi_probe(struct pci_dev *pci_dev,
if (hpi->interrupt_mode) {
asihpi->pcm_start = snd_card_asihpi_pcm_int_start;
asihpi->pcm_stop = snd_card_asihpi_pcm_int_stop;
tasklet_setup(&asihpi->t, snd_card_asihpi_int_task);
hpi->interrupt_callback = snd_card_asihpi_isr;
} else {
asihpi->pcm_start = snd_card_asihpi_pcm_timer_start;
@ -2960,14 +2931,12 @@ __nodev:
static void snd_asihpi_remove(struct pci_dev *pci_dev)
{
struct hpi_adapter *hpi = pci_get_drvdata(pci_dev);
struct snd_card_asihpi *asihpi = hpi->snd_card->private_data;
/* Stop interrupts */
if (hpi->interrupt_mode) {
hpi->interrupt_callback = NULL;
hpi_handle_error(hpi_adapter_set_property(hpi->adapter->index,
HPI_ADAPTER_PROPERTY_IRQ_RATE, 0, 0));
tasklet_kill(&asihpi->t);
}
snd_card_free(hpi->snd_card);

View File

@ -329,11 +329,20 @@ static irqreturn_t asihpi_isr(int irq, void *dev_id)
asihpi_irq_count, a->adapter->type, a->adapter->index); */
if (a->interrupt_callback)
a->interrupt_callback(a);
return IRQ_WAKE_THREAD;
return IRQ_HANDLED;
}
static irqreturn_t asihpi_isr_thread(int irq, void *dev_id)
{
struct hpi_adapter *a = dev_id;
if (a->interrupt_callback)
a->interrupt_callback(a);
return IRQ_HANDLED;
}
int asihpi_adapter_probe(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id)
{
@ -478,7 +487,8 @@ int asihpi_adapter_probe(struct pci_dev *pci_dev,
}
/* Note: request_irq calls asihpi_isr here */
if (request_irq(pci_dev->irq, asihpi_isr, IRQF_SHARED,
if (request_threaded_irq(pci_dev->irq, asihpi_isr,
asihpi_isr_thread, IRQF_SHARED,
"asihpi", &adapters[adapter_index])) {
dev_err(&pci_dev->dev, "request_irq(%d) failed\n",
pci_dev->irq);

View File

@ -67,7 +67,7 @@ struct hpi_ioctl_linux {
};
/* Conflict?: H is already used by a number of drivers hid, bluetooth hci,
and some sound drivers sb16, hdsp, emu10k. AFAIK 0xFC is ununsed command
and some sound drivers sb16, hdsp, emu10k. AFAIK 0xFC is unused command
*/
#define HPI_IOCTL_LINUX _IOWR('H', 0xFC, struct hpi_ioctl_linux)

View File

@ -350,7 +350,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
*/
if (!cfg->line_outs && cfg->hp_outs > 1 &&
!(cond_flags & HDA_PINCFG_NO_HP_FIXUP)) {
int i = 0;
i = 0;
while (i < cfg->hp_outs) {
/* The real HPs should have the sequence 0x0f */
if ((hp_out[i].seq & 0x0f) == 0x0f) {

View File

@ -368,7 +368,8 @@ enum {
#define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \
((pci)->device == 0x0c0c) || \
((pci)->device == 0x0d0c) || \
((pci)->device == 0x160c))
((pci)->device == 0x160c) || \
((pci)->device == 0x490d))
#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
@ -2493,6 +2494,9 @@ static const struct pci_device_id azx_ids[] = {
/* Tigerlake-H */
{ PCI_DEVICE(0x8086, 0x43c8),
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
/* DG1 */
{ PCI_DEVICE(0x8086, 0x490d),
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
/* Elkhart Lake */
{ PCI_DEVICE(0x8086, 0x4b55),
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},

View File

@ -77,7 +77,7 @@ int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
struct hda_jack_callback *
snd_hda_jack_detect_enable_callback_mst(struct hda_codec *codec, hda_nid_t nid,
int dev_id, hda_jack_callback_fn cb);
int dev_id, hda_jack_callback_fn func);
/**
* snd_hda_jack_detect_enable - enable the jack-detection

View File

@ -100,7 +100,7 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *tlv);
unsigned int size, unsigned int __user *_tlv);
int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
@ -119,7 +119,7 @@ int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid,
int ch, int dir, int idx, int mask, int val);
int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
int dir, int idx, int mask, int val);
int direction, int idx, int mask, int val);
int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
int direction, int idx, int mask, int val);
int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
@ -198,7 +198,7 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
unsigned int *cur_val);
int snd_hda_add_imux_item(struct hda_codec *codec,
struct hda_input_mux *imux, const char *label,
int index, int *type_index_ret);
int index, int *type_idx);
/*
* Multi-channel / digital-out PCM helper
@ -642,7 +642,7 @@ unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
*/
int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo,
int num_entries, const char * const *texts);
int num_items, const char * const *texts);
#define snd_hda_enum_bool_helper_info(kcontrol, uinfo) \
snd_hda_enum_helper_info(kcontrol, uinfo, 0, NULL)

File diff suppressed because it is too large Load Diff

View File

@ -4269,6 +4269,7 @@ HDA_CODEC_ENTRY(0x8086280c, "Cannonlake HDMI", patch_i915_glk_hdmi),
HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI", patch_i915_glk_hdmi),
HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi),
HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI", patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x80862814, "DG1 HDMI", patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x80862816, "Rocketlake HDMI", patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi),
HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI", patch_i915_icl_hdmi),

View File

@ -69,7 +69,7 @@ struct mixart_mgr {
u32 msg_fifo[MSG_FIFO_SIZE];
int msg_fifo_readptr;
int msg_fifo_writeptr;
atomic_t msg_processed; /* number of messages to be processed in tasklet */
atomic_t msg_processed; /* number of messages to be processed in irq thread */
struct mutex lock; /* interrupt lock */
struct mutex msg_lock; /* mailbox lock */

View File

@ -445,7 +445,6 @@ struct snd_riptide {
union firmware_version firmware;
spinlock_t lock;
struct tasklet_struct riptide_tq;
struct snd_info_entry *proc_entry;
unsigned long received_irqs;
@ -1070,9 +1069,9 @@ getmixer(struct cmdif *cif, short num, unsigned short *rval,
return 0;
}
static void riptide_handleirq(struct tasklet_struct *t)
static irqreturn_t riptide_handleirq(int irq, void *dev_id)
{
struct snd_riptide *chip = from_tasklet(chip, t, riptide_tq);
struct snd_riptide *chip = dev_id;
struct cmdif *cif = chip->cif;
struct snd_pcm_substream *substream[PLAYBACK_SUBSTREAMS + 1];
struct snd_pcm_runtime *runtime;
@ -1083,7 +1082,7 @@ static void riptide_handleirq(struct tasklet_struct *t)
unsigned int flag;
if (!cif)
return;
return IRQ_HANDLED;
for (i = 0; i < PLAYBACK_SUBSTREAMS; i++)
substream[i] = chip->playback_substream[i];
@ -1134,6 +1133,8 @@ static void riptide_handleirq(struct tasklet_struct *t)
}
}
}
return IRQ_HANDLED;
}
#ifdef CONFIG_PM_SLEEP
@ -1699,13 +1700,14 @@ snd_riptide_interrupt(int irq, void *dev_id)
{
struct snd_riptide *chip = dev_id;
struct cmdif *cif = chip->cif;
irqreturn_t ret = IRQ_HANDLED;
if (cif) {
chip->received_irqs++;
if (IS_EOBIRQ(cif->hwport) || IS_EOSIRQ(cif->hwport) ||
IS_EOCIRQ(cif->hwport)) {
chip->handled_irqs++;
tasklet_schedule(&chip->riptide_tq);
ret = IRQ_WAKE_THREAD;
}
if (chip->rmidi && IS_MPUIRQ(cif->hwport)) {
chip->handled_irqs++;
@ -1714,7 +1716,7 @@ snd_riptide_interrupt(int irq, void *dev_id)
}
SET_AIACK(cif->hwport);
}
return IRQ_HANDLED;
return ret;
}
static void
@ -1843,7 +1845,6 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
chip->received_irqs = 0;
chip->handled_irqs = 0;
chip->cif = NULL;
tasklet_setup(&chip->riptide_tq, riptide_handleirq);
if ((chip->res_port =
request_region(chip->port, 64, "RIPTIDE")) == NULL) {
@ -1856,7 +1857,8 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
hwport = (struct riptideport *)chip->port;
UNSET_AIE(hwport);
if (request_irq(pci->irq, snd_riptide_interrupt, IRQF_SHARED,
if (request_threaded_irq(pci->irq, snd_riptide_interrupt,
riptide_handleirq, IRQF_SHARED,
KBUILD_MODNAME, chip)) {
snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n",
pci->irq);

View File

@ -447,8 +447,8 @@ struct hdsp {
struct snd_pcm_substream *capture_substream;
struct snd_pcm_substream *playback_substream;
struct hdsp_midi midi[2];
struct tasklet_struct midi_tasklet;
int use_midi_tasklet;
struct work_struct midi_work;
int use_midi_work;
int precise_ptr;
u32 control_register; /* cached value */
u32 control2_register; /* cached value */
@ -1385,7 +1385,6 @@ static void snd_hdsp_midi_input_trigger(struct snd_rawmidi_substream *substream,
}
} else {
hdsp->control_register &= ~ie;
tasklet_kill(&hdsp->midi_tasklet);
}
hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
@ -2542,37 +2541,37 @@ static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct sn
return change;
}
#define HDSP_USE_MIDI_TASKLET(xname, xindex) \
#define HDSP_USE_MIDI_WORK(xname, xindex) \
{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
.name = xname, \
.index = xindex, \
.info = snd_hdsp_info_use_midi_tasklet, \
.get = snd_hdsp_get_use_midi_tasklet, \
.put = snd_hdsp_put_use_midi_tasklet \
.info = snd_hdsp_info_use_midi_work, \
.get = snd_hdsp_get_use_midi_work, \
.put = snd_hdsp_put_use_midi_work \
}
static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet)
static int hdsp_set_use_midi_work(struct hdsp *hdsp, int use_work)
{
if (use_tasklet)
hdsp->use_midi_tasklet = 1;
if (use_work)
hdsp->use_midi_work = 1;
else
hdsp->use_midi_tasklet = 0;
hdsp->use_midi_work = 0;
return 0;
}
#define snd_hdsp_info_use_midi_tasklet snd_ctl_boolean_mono_info
#define snd_hdsp_info_use_midi_work snd_ctl_boolean_mono_info
static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
static int snd_hdsp_get_use_midi_work(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&hdsp->lock);
ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet;
ucontrol->value.integer.value[0] = hdsp->use_midi_work;
spin_unlock_irq(&hdsp->lock);
return 0;
}
static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
static int snd_hdsp_put_use_midi_work(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
@ -2582,8 +2581,8 @@ static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct s
return -EBUSY;
val = ucontrol->value.integer.value[0] & 1;
spin_lock_irq(&hdsp->lock);
change = (int)val != hdsp->use_midi_tasklet;
hdsp_set_use_midi_tasklet(hdsp, val);
change = (int)val != hdsp->use_midi_work;
hdsp_set_use_midi_work(hdsp, val);
spin_unlock_irq(&hdsp->lock);
return change;
}
@ -2950,7 +2949,7 @@ HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0),
HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0),
HDSP_TOGGLE_SETTING("Line Out", HDSP_LineOut),
HDSP_PRECISE_POINTER("Precise Pointer", 0),
HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0),
HDSP_USE_MIDI_WORK("Use Midi Tasklet", 0),
};
@ -3370,7 +3369,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0));
snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1));
snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1));
snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off");
snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_work ? "on" : "off");
snd_iprintf(buffer, "\n");
@ -3791,9 +3790,9 @@ static int snd_hdsp_set_defaults(struct hdsp *hdsp)
return 0;
}
static void hdsp_midi_tasklet(struct tasklet_struct *t)
static void hdsp_midi_work(struct work_struct *work)
{
struct hdsp *hdsp = from_tasklet(hdsp, t, midi_tasklet);
struct hdsp *hdsp = container_of(work, struct hdsp, midi_work);
if (hdsp->midi[0].pending)
snd_hdsp_midi_input_read (&hdsp->midi[0]);
@ -3838,7 +3837,7 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
}
if (midi0 && midi0status) {
if (hdsp->use_midi_tasklet) {
if (hdsp->use_midi_work) {
/* we disable interrupts for this input until processing is done */
hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
@ -3849,7 +3848,7 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
}
}
if (hdsp->io_type != Multiface && hdsp->io_type != RPM && hdsp->io_type != H9632 && midi1 && midi1status) {
if (hdsp->use_midi_tasklet) {
if (hdsp->use_midi_work) {
/* we disable interrupts for this input until processing is done */
hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
@ -3859,8 +3858,8 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
snd_hdsp_midi_input_read (&hdsp->midi[1]);
}
}
if (hdsp->use_midi_tasklet && schedule)
tasklet_schedule(&hdsp->midi_tasklet);
if (hdsp->use_midi_work && schedule)
queue_work(system_highpri_wq, &hdsp->midi_work);
return IRQ_HANDLED;
}
@ -5182,7 +5181,7 @@ static int snd_hdsp_create(struct snd_card *card,
spin_lock_init(&hdsp->lock);
tasklet_setup(&hdsp->midi_tasklet, hdsp_midi_tasklet);
INIT_WORK(&hdsp->midi_work, hdsp_midi_work);
pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
hdsp->firmware_rev &= 0xff;
@ -5235,7 +5234,7 @@ static int snd_hdsp_create(struct snd_card *card,
hdsp->irq = pci->irq;
card->sync_irq = hdsp->irq;
hdsp->precise_ptr = 0;
hdsp->use_midi_tasklet = 1;
hdsp->use_midi_work = 1;
hdsp->dds_value = 0;
if ((err = snd_hdsp_initialize_memory(hdsp)) < 0)
@ -5305,7 +5304,7 @@ static int snd_hdsp_free(struct hdsp *hdsp)
{
if (hdsp->port) {
/* stop the audio, and cancel all interrupts */
tasklet_kill(&hdsp->midi_tasklet);
cancel_work_sync(&hdsp->midi_work);
hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
}

View File

@ -997,7 +997,7 @@ struct hdspm {
u32 settings_register; /* cached value for AIO / RayDat (sync reference, master/slave) */
struct hdspm_midi midi[4];
struct tasklet_struct midi_tasklet;
struct work_struct midi_work;
size_t period_bytes;
unsigned char ss_in_channels;
@ -1217,7 +1217,7 @@ static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
return ret;
}
/* round arbitary sample rates to commonly known rates */
/* round arbitrary sample rates to commonly known rates */
static int hdspm_round_frequency(int rate)
{
if (rate < 38050)
@ -2169,9 +2169,9 @@ static int snd_hdspm_create_midi(struct snd_card *card,
}
static void hdspm_midi_tasklet(struct tasklet_struct *t)
static void hdspm_midi_work(struct work_struct *work)
{
struct hdspm *hdspm = from_tasklet(hdspm, t, midi_tasklet);
struct hdspm *hdspm = container_of(work, struct hdspm, midi_work);
int i = 0;
while (i < hdspm->midiPorts) {
@ -5449,7 +5449,7 @@ static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
}
if (schedule)
tasklet_hi_schedule(&hdspm->midi_tasklet);
queue_work(system_highpri_wq, &hdspm->midi_work);
}
return IRQ_HANDLED;
@ -6538,6 +6538,7 @@ static int snd_hdspm_create(struct snd_card *card,
hdspm->card = card;
spin_lock_init(&hdspm->lock);
INIT_WORK(&hdspm->midi_work, hdspm_midi_work);
pci_read_config_word(hdspm->pci,
PCI_CLASS_REVISION, &hdspm->firmware_rev);
@ -6836,9 +6837,6 @@ static int snd_hdspm_create(struct snd_card *card,
}
tasklet_setup(&hdspm->midi_tasklet, hdspm_midi_tasklet);
if (hdspm->io_type != MADIface) {
hdspm->serial = (hdspm_read(hdspm,
HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
@ -6873,6 +6871,7 @@ static int snd_hdspm_free(struct hdspm * hdspm)
{
if (hdspm->port) {
cancel_work_sync(&hdspm->midi_work);
/* stop th audio, and cancel all interrupts */
hdspm->control_register &=

View File

@ -332,6 +332,106 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
return 0;
}
/*
* Profile name preset table
*/
struct usb_audio_device_name {
u32 id;
const char *vendor_name;
const char *product_name;
const char *profile_name; /* override card->longname */
};
#define PROFILE_NAME(vid, pid, vendor, product, profile) \
{ .id = USB_ID(vid, pid), .vendor_name = (vendor), \
.product_name = (product), .profile_name = (profile) }
#define DEVICE_NAME(vid, pid, vendor, product) \
PROFILE_NAME(vid, pid, vendor, product, NULL)
/* vendor/product and profile name presets, sorted in device id order */
static const struct usb_audio_device_name usb_audio_names[] = {
/* HP Thunderbolt Dock Audio Headset */
PROFILE_NAME(0x03f0, 0x0269, "HP", "Thunderbolt Dock Audio Headset",
"HP-Thunderbolt-Dock-Audio-Headset"),
/* HP Thunderbolt Dock Audio Module */
PROFILE_NAME(0x03f0, 0x0567, "HP", "Thunderbolt Dock Audio Module",
"HP-Thunderbolt-Dock-Audio-Module"),
/* Two entries for Gigabyte TRX40 Aorus Master:
* TRX40 Aorus Master has two USB-audio devices, one for the front
* headphone with ESS SABRE9218 DAC chip, while another for the rest
* I/O (the rear panel and the front mic) with Realtek ALC1220-VB.
* Here we provide two distinct names for making UCM profiles easier.
*/
PROFILE_NAME(0x0414, 0xa000, "Gigabyte", "Aorus Master Front Headphone",
"Gigabyte-Aorus-Master-Front-Headphone"),
PROFILE_NAME(0x0414, 0xa001, "Gigabyte", "Aorus Master Main Audio",
"Gigabyte-Aorus-Master-Main-Audio"),
/* Gigabyte TRX40 Aorus Pro WiFi */
PROFILE_NAME(0x0414, 0xa002,
"Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
/* Creative/E-Mu devices */
DEVICE_NAME(0x041e, 0x3010, "Creative Labs", "Sound Blaster MP3+"),
/* Creative/Toshiba Multimedia Center SB-0500 */
DEVICE_NAME(0x041e, 0x3048, "Toshiba", "SB-0500"),
DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"),
/* Dell WD15 Dock */
PROFILE_NAME(0x0bda, 0x4014, "Dell", "WD15 Dock", "Dell-WD15-Dock"),
/* Dell WD19 Dock */
PROFILE_NAME(0x0bda, 0x402e, "Dell", "WD19 Dock", "Dell-WD15-Dock"),
DEVICE_NAME(0x0ccd, 0x0028, "TerraTec", "Aureon5.1MkII"),
/*
* The original product_name is "USB Sound Device", however this name
* is also used by the CM106 based cards, so make it unique.
*/
DEVICE_NAME(0x0d8c, 0x0102, NULL, "ICUSBAUDIO7D"),
DEVICE_NAME(0x0d8c, 0x0103, NULL, "Audio Advantage MicroII"),
/* MSI TRX40 Creator */
PROFILE_NAME(0x0db0, 0x0d64,
"Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
/* MSI TRX40 */
PROFILE_NAME(0x0db0, 0x543d,
"Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
/* Stanton/N2IT Final Scratch v1 device ('Scratchamp') */
DEVICE_NAME(0x103d, 0x0100, "Stanton", "ScratchAmp"),
DEVICE_NAME(0x103d, 0x0101, "Stanton", "ScratchAmp"),
/* aka. Serato Scratch Live DJ Box */
DEVICE_NAME(0x13e5, 0x0001, "Rane", "SL-1"),
/* Lenovo ThinkStation P620 Rear Line-in, Line-out and Microphone */
PROFILE_NAME(0x17aa, 0x1046, "Lenovo", "ThinkStation P620 Rear",
"Lenovo-ThinkStation-P620-Rear"),
/* Lenovo ThinkStation P620 Internal Speaker + Front Headset */
PROFILE_NAME(0x17aa, 0x104d, "Lenovo", "ThinkStation P620 Main",
"Lenovo-ThinkStation-P620-Main"),
/* Asrock TRX40 Creator */
PROFILE_NAME(0x26ce, 0x0a01,
"Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
{ } /* terminator */
};
static const struct usb_audio_device_name *
lookup_device_name(u32 id)
{
static const struct usb_audio_device_name *p;
for (p = usb_audio_names; p->id; p++)
if (p->id == id)
return p;
return NULL;
}
/*
* free the chip instance
*
@ -357,10 +457,16 @@ static void usb_audio_make_shortname(struct usb_device *dev,
const struct snd_usb_audio_quirk *quirk)
{
struct snd_card *card = chip->card;
const struct usb_audio_device_name *preset;
const char *s = NULL;
if (quirk && quirk->product_name && *quirk->product_name) {
strlcpy(card->shortname, quirk->product_name,
sizeof(card->shortname));
preset = lookup_device_name(chip->usb_id);
if (preset && preset->product_name)
s = preset->product_name;
else if (quirk && quirk->product_name)
s = quirk->product_name;
if (s && *s) {
strlcpy(card->shortname, s, sizeof(card->shortname));
return;
}
@ -382,17 +488,26 @@ static void usb_audio_make_longname(struct usb_device *dev,
const struct snd_usb_audio_quirk *quirk)
{
struct snd_card *card = chip->card;
const struct usb_audio_device_name *preset;
const char *s = NULL;
int len;
preset = lookup_device_name(chip->usb_id);
/* shortcut - if any pre-defined string is given, use it */
if (quirk && quirk->profile_name && *quirk->profile_name) {
strlcpy(card->longname, quirk->profile_name,
sizeof(card->longname));
if (preset && preset->profile_name)
s = preset->profile_name;
if (s && *s) {
strlcpy(card->longname, s, sizeof(card->longname));
return;
}
if (quirk && quirk->vendor_name && *quirk->vendor_name) {
len = strlcpy(card->longname, quirk->vendor_name, sizeof(card->longname));
if (preset && preset->vendor_name)
s = preset->vendor_name;
else if (quirk && quirk->vendor_name)
s = quirk->vendor_name;
if (s && *s) {
len = strlcpy(card->longname, s, sizeof(card->longname));
} else {
/* retrieve the vendor and device strings as longname */
if (dev->descriptor.iManufacturer)

View File

@ -318,7 +318,7 @@ static inline void prepare_inbound_urb(struct snd_usb_endpoint *ep,
/*
* Send output urbs that have been prepared previously. URBs are dequeued
* from ep->ready_playback_urbs and in case there there aren't any available
* from ep->ready_playback_urbs and in case there aren't any available
* or there are no packets that have been prepared, this function does
* nothing.
*

View File

@ -142,7 +142,7 @@ struct snd_usb_midi_out_endpoint {
unsigned int active_urbs;
unsigned int drain_urbs;
int max_transfer; /* size of urb buffer */
struct tasklet_struct tasklet;
struct work_struct work;
unsigned int next_urb;
spinlock_t buffer_lock;
@ -344,9 +344,10 @@ static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint *ep)
spin_unlock_irqrestore(&ep->buffer_lock, flags);
}
static void snd_usbmidi_out_tasklet(struct tasklet_struct *t)
static void snd_usbmidi_out_work(struct work_struct *work)
{
struct snd_usb_midi_out_endpoint *ep = from_tasklet(ep, t, tasklet);
struct snd_usb_midi_out_endpoint *ep =
container_of(work, struct snd_usb_midi_out_endpoint, work);
snd_usbmidi_do_output(ep);
}
@ -1177,7 +1178,7 @@ static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream,
snd_rawmidi_proceed(substream);
return;
}
tasklet_schedule(&port->ep->tasklet);
queue_work(system_highpri_wq, &port->ep->work);
}
}
@ -1440,7 +1441,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
}
spin_lock_init(&ep->buffer_lock);
tasklet_setup(&ep->tasklet, snd_usbmidi_out_tasklet);
INIT_WORK(&ep->work, snd_usbmidi_out_work);
init_waitqueue_head(&ep->drain_wait);
for (i = 0; i < 0x10; ++i)
@ -1503,7 +1504,7 @@ void snd_usbmidi_disconnect(struct list_head *p)
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i];
if (ep->out)
tasklet_kill(&ep->out->tasklet);
cancel_work_sync(&ep->out->work);
if (ep->out) {
for (j = 0; j < OUTPUT_URBS; ++j)
usb_kill_urb(ep->out->urbs[j].urb);

View File

@ -96,7 +96,7 @@ struct ua101 {
u8 rate_feedback[MAX_QUEUE_LENGTH];
struct list_head ready_playback_urbs;
struct tasklet_struct playback_tasklet;
struct work_struct playback_work;
wait_queue_head_t alsa_capture_wait;
wait_queue_head_t rate_feedback_wait;
wait_queue_head_t alsa_playback_wait;
@ -188,7 +188,7 @@ static void playback_urb_complete(struct urb *usb_urb)
spin_lock_irqsave(&ua->lock, flags);
list_add_tail(&urb->ready_list, &ua->ready_playback_urbs);
if (ua->rate_feedback_count > 0)
tasklet_schedule(&ua->playback_tasklet);
queue_work(system_highpri_wq, &ua->playback_work);
ua->playback.substream->runtime->delay -=
urb->urb.iso_frame_desc[0].length /
ua->playback.frame_bytes;
@ -247,9 +247,9 @@ static inline void add_with_wraparound(struct ua101 *ua,
*value -= ua->playback.queue_length;
}
static void playback_tasklet(struct tasklet_struct *t)
static void playback_work(struct work_struct *work)
{
struct ua101 *ua = from_tasklet(ua, t, playback_tasklet);
struct ua101 *ua = container_of(work, struct ua101, playback_work);
unsigned long flags;
unsigned int frames;
struct ua101_urb *urb;
@ -401,7 +401,7 @@ static void capture_urb_complete(struct urb *urb)
}
if (test_bit(USB_PLAYBACK_RUNNING, &ua->states) &&
!list_empty(&ua->ready_playback_urbs))
tasklet_schedule(&ua->playback_tasklet);
queue_work(system_highpri_wq, &ua->playback_work);
}
spin_unlock_irqrestore(&ua->lock, flags);
@ -532,7 +532,7 @@ static void stop_usb_playback(struct ua101 *ua)
kill_stream_urbs(&ua->playback);
tasklet_kill(&ua->playback_tasklet);
cancel_work_sync(&ua->playback_work);
disable_iso_interface(ua, INTF_PLAYBACK);
}
@ -550,7 +550,7 @@ static int start_usb_playback(struct ua101 *ua)
return 0;
kill_stream_urbs(&ua->playback);
tasklet_kill(&ua->playback_tasklet);
cancel_work_sync(&ua->playback_work);
err = enable_iso_interface(ua, INTF_PLAYBACK);
if (err < 0)
@ -1218,7 +1218,7 @@ static int ua101_probe(struct usb_interface *interface,
spin_lock_init(&ua->lock);
mutex_init(&ua->mutex);
INIT_LIST_HEAD(&ua->ready_playback_urbs);
tasklet_setup(&ua->playback_tasklet, playback_tasklet);
INIT_WORK(&ua->playback_work, playback_work);
init_waitqueue_head(&ua->alsa_capture_wait);
init_waitqueue_head(&ua->rate_feedback_wait);
init_waitqueue_head(&ua->alsa_playback_wait);

View File

@ -2602,6 +2602,216 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer)
return 0;
}
/*
* Pioneer DJ DJM-250MK2 and maybe other DJM models
*
* For playback, no duplicate mapping should be set.
* There are three mixer stereo channels (CH1, CH2, AUX)
* and three stereo sources (Playback 1-2, Playback 3-4, Playback 5-6).
* Each channel should be mapped just once to one source.
* If mapped multiple times, only one source will play on given channel
* (sources are not mixed together).
*
* For recording, duplicate mapping is OK. We will get the same signal multiple times.
*
* Channels 7-8 are in both directions fixed to FX SEND / FX RETURN.
*
* See also notes in the quirks-table.h file.
*/
struct snd_pioneer_djm_option {
const u16 wIndex;
const u16 wValue;
const char *name;
};
static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_level[] = {
{ .name = "-5 dB", .wValue = 0x0300, .wIndex = 0x8003 },
{ .name = "-10 dB", .wValue = 0x0200, .wIndex = 0x8003 },
{ .name = "-15 dB", .wValue = 0x0100, .wIndex = 0x8003 },
{ .name = "-19 dB", .wValue = 0x0000, .wIndex = 0x8003 }
};
static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch12[] = {
{ .name = "CH1 Control Tone PHONO", .wValue = 0x0103, .wIndex = 0x8002 },
{ .name = "CH1 Control Tone LINE", .wValue = 0x0100, .wIndex = 0x8002 },
{ .name = "Post CH1 Fader", .wValue = 0x0106, .wIndex = 0x8002 },
{ .name = "Cross Fader A", .wValue = 0x0107, .wIndex = 0x8002 },
{ .name = "Cross Fader B", .wValue = 0x0108, .wIndex = 0x8002 },
{ .name = "MIC", .wValue = 0x0109, .wIndex = 0x8002 },
{ .name = "AUX", .wValue = 0x010d, .wIndex = 0x8002 },
{ .name = "REC OUT", .wValue = 0x010a, .wIndex = 0x8002 }
};
static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch34[] = {
{ .name = "CH2 Control Tone PHONO", .wValue = 0x0203, .wIndex = 0x8002 },
{ .name = "CH2 Control Tone LINE", .wValue = 0x0200, .wIndex = 0x8002 },
{ .name = "Post CH2 Fader", .wValue = 0x0206, .wIndex = 0x8002 },
{ .name = "Cross Fader A", .wValue = 0x0207, .wIndex = 0x8002 },
{ .name = "Cross Fader B", .wValue = 0x0208, .wIndex = 0x8002 },
{ .name = "MIC", .wValue = 0x0209, .wIndex = 0x8002 },
{ .name = "AUX", .wValue = 0x020d, .wIndex = 0x8002 },
{ .name = "REC OUT", .wValue = 0x020a, .wIndex = 0x8002 }
};
static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch56[] = {
{ .name = "REC OUT", .wValue = 0x030a, .wIndex = 0x8002 },
{ .name = "Post CH1 Fader", .wValue = 0x0311, .wIndex = 0x8002 },
{ .name = "Post CH2 Fader", .wValue = 0x0312, .wIndex = 0x8002 },
{ .name = "Cross Fader A", .wValue = 0x0307, .wIndex = 0x8002 },
{ .name = "Cross Fader B", .wValue = 0x0308, .wIndex = 0x8002 },
{ .name = "MIC", .wValue = 0x0309, .wIndex = 0x8002 },
{ .name = "AUX", .wValue = 0x030d, .wIndex = 0x8002 }
};
static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_12[] = {
{ .name = "CH1", .wValue = 0x0100, .wIndex = 0x8016 },
{ .name = "CH2", .wValue = 0x0101, .wIndex = 0x8016 },
{ .name = "AUX", .wValue = 0x0104, .wIndex = 0x8016 }
};
static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_34[] = {
{ .name = "CH1", .wValue = 0x0200, .wIndex = 0x8016 },
{ .name = "CH2", .wValue = 0x0201, .wIndex = 0x8016 },
{ .name = "AUX", .wValue = 0x0204, .wIndex = 0x8016 }
};
static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_56[] = {
{ .name = "CH1", .wValue = 0x0300, .wIndex = 0x8016 },
{ .name = "CH2", .wValue = 0x0301, .wIndex = 0x8016 },
{ .name = "AUX", .wValue = 0x0304, .wIndex = 0x8016 }
};
struct snd_pioneer_djm_option_group {
const char *name;
const struct snd_pioneer_djm_option *options;
const size_t count;
const u16 default_value;
};
#define snd_pioneer_djm_option_group_item(_name, suffix, _default_value) { \
.name = _name, \
.options = snd_pioneer_djm_options_##suffix, \
.count = ARRAY_SIZE(snd_pioneer_djm_options_##suffix), \
.default_value = _default_value }
static const struct snd_pioneer_djm_option_group snd_pioneer_djm_option_groups[] = {
snd_pioneer_djm_option_group_item("Master Capture Level Capture Switch", capture_level, 0),
snd_pioneer_djm_option_group_item("Capture 1-2 Capture Switch", capture_ch12, 2),
snd_pioneer_djm_option_group_item("Capture 3-4 Capture Switch", capture_ch34, 2),
snd_pioneer_djm_option_group_item("Capture 5-6 Capture Switch", capture_ch56, 0),
snd_pioneer_djm_option_group_item("Playback 1-2 Playback Switch", playback_12, 0),
snd_pioneer_djm_option_group_item("Playback 3-4 Playback Switch", playback_34, 1),
snd_pioneer_djm_option_group_item("Playback 5-6 Playback Switch", playback_56, 2)
};
// layout of the kcontrol->private_value:
#define SND_PIONEER_DJM_VALUE_MASK 0x0000ffff
#define SND_PIONEER_DJM_GROUP_MASK 0xffff0000
#define SND_PIONEER_DJM_GROUP_SHIFT 16
static int snd_pioneer_djm_controls_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *info)
{
u16 group_index = kctl->private_value >> SND_PIONEER_DJM_GROUP_SHIFT;
size_t count;
const char *name;
const struct snd_pioneer_djm_option_group *group;
if (group_index >= ARRAY_SIZE(snd_pioneer_djm_option_groups))
return -EINVAL;
group = &snd_pioneer_djm_option_groups[group_index];
count = group->count;
if (info->value.enumerated.item >= count)
info->value.enumerated.item = count - 1;
name = group->options[info->value.enumerated.item].name;
strlcpy(info->value.enumerated.name, name, sizeof(info->value.enumerated.name));
info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
info->count = 1;
info->value.enumerated.items = count;
return 0;
}
static int snd_pioneer_djm_controls_update(struct usb_mixer_interface *mixer, u16 group, u16 value)
{
int err;
if (group >= ARRAY_SIZE(snd_pioneer_djm_option_groups)
|| value >= snd_pioneer_djm_option_groups[group].count)
return -EINVAL;
err = snd_usb_lock_shutdown(mixer->chip);
if (err)
return err;
err = snd_usb_ctl_msg(
mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0),
USB_REQ_SET_FEATURE,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
snd_pioneer_djm_option_groups[group].options[value].wValue,
snd_pioneer_djm_option_groups[group].options[value].wIndex,
NULL, 0);
snd_usb_unlock_shutdown(mixer->chip);
return err;
}
static int snd_pioneer_djm_controls_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem)
{
elem->value.enumerated.item[0] = kctl->private_value & SND_PIONEER_DJM_VALUE_MASK;
return 0;
}
static int snd_pioneer_djm_controls_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem)
{
struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
struct usb_mixer_interface *mixer = list->mixer;
unsigned long private_value = kctl->private_value;
u16 group = (private_value & SND_PIONEER_DJM_GROUP_MASK) >> SND_PIONEER_DJM_GROUP_SHIFT;
u16 value = elem->value.enumerated.item[0];
kctl->private_value = (group << SND_PIONEER_DJM_GROUP_SHIFT) | value;
return snd_pioneer_djm_controls_update(mixer, group, value);
}
static int snd_pioneer_djm_controls_resume(struct usb_mixer_elem_list *list)
{
unsigned long private_value = list->kctl->private_value;
u16 group = (private_value & SND_PIONEER_DJM_GROUP_MASK) >> SND_PIONEER_DJM_GROUP_SHIFT;
u16 value = (private_value & SND_PIONEER_DJM_VALUE_MASK);
return snd_pioneer_djm_controls_update(list->mixer, group, value);
}
static int snd_pioneer_djm_controls_create(struct usb_mixer_interface *mixer)
{
int err, i;
const struct snd_pioneer_djm_option_group *group;
struct snd_kcontrol_new knew = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.index = 0,
.info = snd_pioneer_djm_controls_info,
.get = snd_pioneer_djm_controls_get,
.put = snd_pioneer_djm_controls_put
};
for (i = 0; i < ARRAY_SIZE(snd_pioneer_djm_option_groups); i++) {
group = &snd_pioneer_djm_option_groups[i];
knew.name = group->name;
knew.private_value = (i << SND_PIONEER_DJM_GROUP_SHIFT) | group->default_value;
err = snd_pioneer_djm_controls_update(mixer, i, group->default_value);
if (err)
return err;
err = add_single_ctl_with_resume(mixer, 0, snd_pioneer_djm_controls_resume,
&knew, NULL);
if (err)
return err;
}
return 0;
}
int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
{
int err = 0;
@ -2706,6 +2916,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
case USB_ID(0x2a39, 0x3fb0): /* RME Babyface Pro FS */
err = snd_bbfpro_controls_create(mixer);
break;
case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */
err = snd_pioneer_djm_controls_create(mixer);
break;
}
return err;

View File

@ -1946,7 +1946,7 @@ static void scarlett2_mixer_interrupt(struct urb *urb)
goto requeue;
if (len == 8) {
data = le32_to_cpu(*(u32 *)urb->transfer_buffer);
data = le32_to_cpu(*(__le32 *)urb->transfer_buffer);
if (data & SCARLETT2_USB_INTERRUPT_VOL_CHANGE)
scarlett2_mixer_interrupt_vol_change(mixer);
if (data & SCARLETT2_USB_INTERRUPT_BUTTON_CHANGE)

View File

@ -1109,7 +1109,7 @@ static const struct snd_us16x08_control_params eq_controls[] = {
.control_id = SND_US16X08_ID_EQLOWFREQ,
.type = USB_MIXER_U8,
.num_channels = 16,
.name = "EQ Low Frequence",
.name = "EQ Low Frequency",
},
{ /* EQ mid low gain */
.kcontrol_new = &snd_us16x08_eq_gain_ctl,
@ -1123,7 +1123,7 @@ static const struct snd_us16x08_control_params eq_controls[] = {
.control_id = SND_US16X08_ID_EQLOWMIDFREQ,
.type = USB_MIXER_U8,
.num_channels = 16,
.name = "EQ MidLow Frequence",
.name = "EQ MidLow Frequency",
},
{ /* EQ mid low Q */
.kcontrol_new = &snd_us16x08_eq_mid_width_ctl,
@ -1144,7 +1144,7 @@ static const struct snd_us16x08_control_params eq_controls[] = {
.control_id = SND_US16X08_ID_EQHIGHMIDFREQ,
.type = USB_MIXER_U8,
.num_channels = 16,
.name = "EQ MidHigh Frequence",
.name = "EQ MidHigh Frequency",
},
{ /* EQ mid high Q */
.kcontrol_new = &snd_us16x08_eq_mid_width_ctl,
@ -1165,7 +1165,7 @@ static const struct snd_us16x08_control_params eq_controls[] = {
.control_id = SND_US16X08_ID_EQHIGHFREQ,
.type = USB_MIXER_U8,
.num_channels = 16,
.name = "EQ High Frequence",
.name = "EQ High Frequency",
},
};

View File

@ -25,33 +25,16 @@
.idProduct = prod, \
.bInterfaceClass = USB_CLASS_VENDOR_SPEC
#define QUIRK_RENAME_DEVICE(_vendor, _device) \
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \
.vendor_name = _vendor, \
.product_name = _device, \
.ifnum = QUIRK_NO_INTERFACE \
}
/* A standard entry matching with vid/pid and the audio class/subclass */
#define USB_AUDIO_DEVICE(vend, prod) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_CLASS | \
USB_DEVICE_ID_MATCH_INT_SUBCLASS, \
.idVendor = vend, \
.idProduct = prod, \
.bInterfaceClass = USB_CLASS_AUDIO, \
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL
#define QUIRK_DEVICE_PROFILE(_vendor, _device, _profile) \
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \
.vendor_name = _vendor, \
.product_name = _device, \
.profile_name = _profile, \
.ifnum = QUIRK_NO_INTERFACE \
}
/* HP Thunderbolt Dock Audio Headset */
{
USB_DEVICE(0x03f0, 0x0269),
QUIRK_DEVICE_PROFILE("HP", "Thunderbolt Dock Audio Headset",
"HP-Thunderbolt-Dock-Audio-Headset"),
},
/* HP Thunderbolt Dock Audio Module */
{
USB_DEVICE(0x03f0, 0x0567),
QUIRK_DEVICE_PROFILE("HP", "Thunderbolt Dock Audio Module",
"HP-Thunderbolt-Dock-Audio-Module"),
},
/* FTDI devices */
{
USB_DEVICE(0x0403, 0xb8d8),
@ -85,44 +68,14 @@
}
},
/* Creative/E-Mu devices */
{
USB_DEVICE(0x041e, 0x3010),
QUIRK_RENAME_DEVICE("Creative Labs", "Sound Blaster MP3+")
},
/* Creative/Toshiba Multimedia Center SB-0500 */
{
USB_DEVICE(0x041e, 0x3048),
QUIRK_RENAME_DEVICE("Toshiba", "SB-0500")
},
{
/* E-Mu 0202 USB */
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x041e,
.idProduct = 0x3f02,
.bInterfaceClass = USB_CLASS_AUDIO,
},
{
/* E-Mu 0404 USB */
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x041e,
.idProduct = 0x3f04,
.bInterfaceClass = USB_CLASS_AUDIO,
},
{
/* E-Mu Tracker Pre */
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x041e,
.idProduct = 0x3f0a,
.bInterfaceClass = USB_CLASS_AUDIO,
},
{
/* E-Mu 0204 USB */
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x041e,
.idProduct = 0x3f19,
.bInterfaceClass = USB_CLASS_AUDIO,
},
/* E-Mu 0202 USB */
{ USB_DEVICE_VENDOR_SPEC(0x041e, 0x3f02) },
/* E-Mu 0404 USB */
{ USB_DEVICE_VENDOR_SPEC(0x041e, 0x3f04) },
/* E-Mu Tracker Pre */
{ USB_DEVICE_VENDOR_SPEC(0x041e, 0x3f0a) },
/* E-Mu 0204 USB */
{ USB_DEVICE_VENDOR_SPEC(0x041e, 0x3f19) },
/*
* HP Wireless Audio
@ -164,70 +117,13 @@
* Logitech QuickCam: bDeviceClass is vendor-specific, so generic interface
* class matches do not take effect without an explicit ID match.
*/
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.idVendor = 0x046d,
.idProduct = 0x0850,
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL
},
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.idVendor = 0x046d,
.idProduct = 0x08ae,
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL
},
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.idVendor = 0x046d,
.idProduct = 0x08c6,
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL
},
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.idVendor = 0x046d,
.idProduct = 0x08f0,
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL
},
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.idVendor = 0x046d,
.idProduct = 0x08f5,
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL
},
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.idVendor = 0x046d,
.idProduct = 0x08f6,
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL
},
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.idVendor = 0x046d,
.idProduct = 0x0990,
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
QUIRK_RENAME_DEVICE("Logitech, Inc.", "QuickCam Pro 9000")
},
{ USB_AUDIO_DEVICE(0x046d, 0x0850) },
{ USB_AUDIO_DEVICE(0x046d, 0x08ae) },
{ USB_AUDIO_DEVICE(0x046d, 0x08c6) },
{ USB_AUDIO_DEVICE(0x046d, 0x08f0) },
{ USB_AUDIO_DEVICE(0x046d, 0x08f5) },
{ USB_AUDIO_DEVICE(0x046d, 0x08f6) },
{ USB_AUDIO_DEVICE(0x046d, 0x0990) },
/*
* Yamaha devices
@ -2609,10 +2505,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.type = QUIRK_MIDI_STANDARD_INTERFACE
}
},
{
USB_DEVICE(0x0ccd, 0x0028),
QUIRK_RENAME_DEVICE("TerraTec", "Aureon5.1MkII")
},
{
USB_DEVICE(0x0ccd, 0x0035),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
@ -2623,16 +2515,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
/* Stanton/N2IT Final Scratch v1 device ('Scratchamp') */
{
USB_DEVICE(0x103d, 0x0100),
QUIRK_RENAME_DEVICE("Stanton", "ScratchAmp")
},
{
USB_DEVICE(0x103d, 0x0101),
QUIRK_RENAME_DEVICE("Stanton", "ScratchAmp")
},
/* Novation EMS devices */
{
USB_DEVICE_VENDOR_SPEC(0x1235, 0x0001),
@ -2817,20 +2699,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
/* */
{
/* aka. Serato Scratch Live DJ Box */
USB_DEVICE(0x13e5, 0x0001),
QUIRK_RENAME_DEVICE("Rane", "SL-1")
},
/* Lenovo ThinkStation P620 Rear Line-in, Line-out and Microphone */
{
USB_DEVICE(0x17aa, 0x1046),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Lenovo",
.product_name = "ThinkStation P620 Rear",
.profile_name = "Lenovo-ThinkStation-P620-Rear",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_SETUP_DISABLE_AUTOSUSPEND
}
@ -2839,9 +2711,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
USB_DEVICE(0x17aa, 0x104d),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Lenovo",
.product_name = "ThinkStation P620 Main",
.profile_name = "Lenovo-ThinkStation-P620-Main",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_SETUP_DISABLE_AUTOSUSPEND
}
@ -2879,10 +2748,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
/* KeithMcMillen Stringport */
{
USB_DEVICE(0x1f38, 0x0001),
.bInterfaceClass = USB_CLASS_AUDIO,
},
{ USB_DEVICE(0x1f38, 0x0001) }, /* FIXME: should be more restrictive matching */
/* Miditech devices */
{
@ -2913,13 +2779,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
*/
#define AU0828_DEVICE(vid, pid, vname, pname) { \
.idVendor = vid, \
.idProduct = pid, \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_CLASS | \
USB_DEVICE_ID_MATCH_INT_SUBCLASS, \
.bInterfaceClass = USB_CLASS_AUDIO, \
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, \
USB_AUDIO_DEVICE(vid, pid), \
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { \
.vendor_name = vname, \
.product_name = pname, \
@ -2949,13 +2809,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
/* Syntek STK1160 */
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.idVendor = 0x05e1,
.idProduct = 0x0408,
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
USB_AUDIO_DEVICE(0x05e1, 0x0408),
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.vendor_name = "Syntek",
.product_name = "STK1160",
@ -3117,10 +2971,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
},
{
/* Tascam US122 MKII - playback-only support */
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x0644,
.idProduct = 0x8021,
.bInterfaceClass = USB_CLASS_AUDIO,
USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021),
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.vendor_name = "TASCAM",
.product_name = "US122 MKII",
@ -3305,19 +3156,6 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
}
},
/*
* The original product_name is "USB Sound Device", however this name
* is also used by the CM106 based cards, so make it unique.
*/
{
USB_DEVICE(0x0d8c, 0x0102),
QUIRK_RENAME_DEVICE(NULL, "ICUSBAUDIO7D")
},
{
USB_DEVICE(0x0d8c, 0x0103),
QUIRK_RENAME_DEVICE(NULL, "Audio Advantage MicroII")
},
/* disabled due to regression for other devices;
* see https://bugzilla.kernel.org/show_bug.cgi?id=199905
*/
@ -3418,18 +3256,10 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
}
}
},
/* Dell WD15 Dock */
{
USB_DEVICE(0x0bda, 0x4014),
QUIRK_DEVICE_PROFILE("Dell", "WD15 Dock", "Dell-WD15-Dock")
},
/* Dell WD19 Dock */
{
USB_DEVICE(0x0bda, 0x402e),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Dell",
.product_name = "WD19 Dock",
.profile_name = "Dell-WD15-Dock",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_SETUP_FMT_AFTER_RESUME
}
@ -3701,33 +3531,6 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
}
},
#define ALC1220_VB_DESKTOP(vend, prod) { \
USB_DEVICE(vend, prod), \
QUIRK_DEVICE_PROFILE("Realtek", "ALC1220-VB-DT", \
"Realtek-ALC1220-VB-Desktop") \
}
ALC1220_VB_DESKTOP(0x0414, 0xa002), /* Gigabyte TRX40 Aorus Pro WiFi */
ALC1220_VB_DESKTOP(0x0db0, 0x0d64), /* MSI TRX40 Creator */
ALC1220_VB_DESKTOP(0x0db0, 0x543d), /* MSI TRX40 */
ALC1220_VB_DESKTOP(0x26ce, 0x0a01), /* Asrock TRX40 Creator */
#undef ALC1220_VB_DESKTOP
/* Two entries for Gigabyte TRX40 Aorus Master:
* TRX40 Aorus Master has two USB-audio devices, one for the front headphone
* with ESS SABRE9218 DAC chip, while another for the rest I/O (the rear
* panel and the front mic) with Realtek ALC1220-VB.
* Here we provide two distinct names for making UCM profiles easier.
*/
{
USB_DEVICE(0x0414, 0xa000),
QUIRK_DEVICE_PROFILE("Gigabyte", "Aorus Master Front Headphone",
"Gigabyte-Aorus-Master-Front-Headphone")
},
{
USB_DEVICE(0x0414, 0xa001),
QUIRK_DEVICE_PROFILE("Gigabyte", "Aorus Master Main Audio",
"Gigabyte-Aorus-Master-Main-Audio")
},
{
/*
* Pioneer DJ DJM-900NXS2
@ -3804,13 +3607,7 @@ ALC1220_VB_DESKTOP(0x26ce, 0x0a01), /* Asrock TRX40 Creator */
* channels to be swapped and out of phase, which is dealt with in quirks.c.
*/
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.idVendor = 0x534d,
.idProduct = 0x2109,
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
USB_AUDIO_DEVICE(0x534d, 0x2109),
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.vendor_name = "MacroSilicon",
.product_name = "MS2109",
@ -3851,3 +3648,4 @@ ALC1220_VB_DESKTOP(0x26ce, 0x0a01), /* Asrock TRX40 Creator */
},
#undef USB_DEVICE_VENDOR_SPEC
#undef USB_AUDIO_DEVICE

View File

@ -110,7 +110,6 @@ enum quirk_type {
struct snd_usb_audio_quirk {
const char *vendor_name;
const char *product_name;
const char *profile_name; /* override the card->longname */
int16_t ifnum;
uint16_t type;
bool shares_media_device;