diff options
Diffstat (limited to 'sound')
56 files changed, 823 insertions, 478 deletions
diff --git a/sound/core/info.c b/sound/core/info.c index 96a074019c33..0eb169acc850 100644 --- a/sound/core/info.c +++ b/sound/core/info.c | |||
@@ -713,8 +713,11 @@ snd_info_create_entry(const char *name, struct snd_info_entry *parent, | |||
713 | INIT_LIST_HEAD(&entry->list); | 713 | INIT_LIST_HEAD(&entry->list); |
714 | entry->parent = parent; | 714 | entry->parent = parent; |
715 | entry->module = module; | 715 | entry->module = module; |
716 | if (parent) | 716 | if (parent) { |
717 | mutex_lock(&parent->access); | ||
717 | list_add_tail(&entry->list, &parent->children); | 718 | list_add_tail(&entry->list, &parent->children); |
719 | mutex_unlock(&parent->access); | ||
720 | } | ||
718 | return entry; | 721 | return entry; |
719 | } | 722 | } |
720 | 723 | ||
@@ -792,7 +795,12 @@ void snd_info_free_entry(struct snd_info_entry * entry) | |||
792 | list_for_each_entry_safe(p, n, &entry->children, list) | 795 | list_for_each_entry_safe(p, n, &entry->children, list) |
793 | snd_info_free_entry(p); | 796 | snd_info_free_entry(p); |
794 | 797 | ||
795 | list_del(&entry->list); | 798 | p = entry->parent; |
799 | if (p) { | ||
800 | mutex_lock(&p->access); | ||
801 | list_del(&entry->list); | ||
802 | mutex_unlock(&p->access); | ||
803 | } | ||
796 | kfree(entry->name); | 804 | kfree(entry->name); |
797 | if (entry->private_free) | 805 | if (entry->private_free) |
798 | entry->private_free(entry); | 806 | entry->private_free(entry); |
diff --git a/sound/core/init.c b/sound/core/init.c index 0c4dc40376a7..d64416f0a281 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -49,8 +49,7 @@ static const struct file_operations snd_shutdown_f_ops; | |||
49 | 49 | ||
50 | /* locked for registering/using */ | 50 | /* locked for registering/using */ |
51 | static DECLARE_BITMAP(snd_cards_lock, SNDRV_CARDS); | 51 | static DECLARE_BITMAP(snd_cards_lock, SNDRV_CARDS); |
52 | struct snd_card *snd_cards[SNDRV_CARDS]; | 52 | static struct snd_card *snd_cards[SNDRV_CARDS]; |
53 | EXPORT_SYMBOL(snd_cards); | ||
54 | 53 | ||
55 | static DEFINE_MUTEX(snd_card_mutex); | 54 | static DEFINE_MUTEX(snd_card_mutex); |
56 | 55 | ||
@@ -268,6 +267,26 @@ int snd_card_new(struct device *parent, int idx, const char *xid, | |||
268 | } | 267 | } |
269 | EXPORT_SYMBOL(snd_card_new); | 268 | EXPORT_SYMBOL(snd_card_new); |
270 | 269 | ||
270 | /** | ||
271 | * snd_card_ref - Get the card object from the index | ||
272 | * @idx: the card index | ||
273 | * | ||
274 | * Returns a card object corresponding to the given index or NULL if not found. | ||
275 | * Release the object via snd_card_unref(). | ||
276 | */ | ||
277 | struct snd_card *snd_card_ref(int idx) | ||
278 | { | ||
279 | struct snd_card *card; | ||
280 | |||
281 | mutex_lock(&snd_card_mutex); | ||
282 | card = snd_cards[idx]; | ||
283 | if (card) | ||
284 | get_device(&card->card_dev); | ||
285 | mutex_unlock(&snd_card_mutex); | ||
286 | return card; | ||
287 | } | ||
288 | EXPORT_SYMBOL_GPL(snd_card_ref); | ||
289 | |||
271 | /* return non-zero if a card is already locked */ | 290 | /* return non-zero if a card is already locked */ |
272 | int snd_card_locked(int card) | 291 | int snd_card_locked(int card) |
273 | { | 292 | { |
@@ -382,14 +401,7 @@ int snd_card_disconnect(struct snd_card *card) | |||
382 | card->shutdown = 1; | 401 | card->shutdown = 1; |
383 | spin_unlock(&card->files_lock); | 402 | spin_unlock(&card->files_lock); |
384 | 403 | ||
385 | /* phase 1: disable fops (user space) operations for ALSA API */ | 404 | /* replace file->f_op with special dummy operations */ |
386 | mutex_lock(&snd_card_mutex); | ||
387 | snd_cards[card->number] = NULL; | ||
388 | clear_bit(card->number, snd_cards_lock); | ||
389 | mutex_unlock(&snd_card_mutex); | ||
390 | |||
391 | /* phase 2: replace file->f_op with special dummy operations */ | ||
392 | |||
393 | spin_lock(&card->files_lock); | 405 | spin_lock(&card->files_lock); |
394 | list_for_each_entry(mfile, &card->files_list, list) { | 406 | list_for_each_entry(mfile, &card->files_list, list) { |
395 | /* it's critical part, use endless loop */ | 407 | /* it's critical part, use endless loop */ |
@@ -405,7 +417,7 @@ int snd_card_disconnect(struct snd_card *card) | |||
405 | } | 417 | } |
406 | spin_unlock(&card->files_lock); | 418 | spin_unlock(&card->files_lock); |
407 | 419 | ||
408 | /* phase 3: notify all connected devices about disconnection */ | 420 | /* notify all connected devices about disconnection */ |
409 | /* at this point, they cannot respond to any calls except release() */ | 421 | /* at this point, they cannot respond to any calls except release() */ |
410 | 422 | ||
411 | #if IS_ENABLED(CONFIG_SND_MIXER_OSS) | 423 | #if IS_ENABLED(CONFIG_SND_MIXER_OSS) |
@@ -421,6 +433,13 @@ int snd_card_disconnect(struct snd_card *card) | |||
421 | device_del(&card->card_dev); | 433 | device_del(&card->card_dev); |
422 | card->registered = false; | 434 | card->registered = false; |
423 | } | 435 | } |
436 | |||
437 | /* disable fops (user space) operations for ALSA API */ | ||
438 | mutex_lock(&snd_card_mutex); | ||
439 | snd_cards[card->number] = NULL; | ||
440 | clear_bit(card->number, snd_cards_lock); | ||
441 | mutex_unlock(&snd_card_mutex); | ||
442 | |||
424 | #ifdef CONFIG_PM | 443 | #ifdef CONFIG_PM |
425 | wake_up(&card->power_sleep); | 444 | wake_up(&card->power_sleep); |
426 | #endif | 445 | #endif |
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index eb974235c92b..9f48e1d3a257 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c | |||
@@ -32,53 +32,6 @@ | |||
32 | 32 | ||
33 | /* | 33 | /* |
34 | * | 34 | * |
35 | * Generic memory allocators | ||
36 | * | ||
37 | */ | ||
38 | |||
39 | /** | ||
40 | * snd_malloc_pages - allocate pages with the given size | ||
41 | * @size: the size to allocate in bytes | ||
42 | * @gfp_flags: the allocation conditions, GFP_XXX | ||
43 | * | ||
44 | * Allocates the physically contiguous pages with the given size. | ||
45 | * | ||
46 | * Return: The pointer of the buffer, or %NULL if no enough memory. | ||
47 | */ | ||
48 | void *snd_malloc_pages(size_t size, gfp_t gfp_flags) | ||
49 | { | ||
50 | int pg; | ||
51 | |||
52 | if (WARN_ON(!size)) | ||
53 | return NULL; | ||
54 | if (WARN_ON(!gfp_flags)) | ||
55 | return NULL; | ||
56 | gfp_flags |= __GFP_COMP; /* compound page lets parts be mapped */ | ||
57 | pg = get_order(size); | ||
58 | return (void *) __get_free_pages(gfp_flags, pg); | ||
59 | } | ||
60 | EXPORT_SYMBOL(snd_malloc_pages); | ||
61 | |||
62 | /** | ||
63 | * snd_free_pages - release the pages | ||
64 | * @ptr: the buffer pointer to release | ||
65 | * @size: the allocated buffer size | ||
66 | * | ||
67 | * Releases the buffer allocated via snd_malloc_pages(). | ||
68 | */ | ||
69 | void snd_free_pages(void *ptr, size_t size) | ||
70 | { | ||
71 | int pg; | ||
72 | |||
73 | if (ptr == NULL) | ||
74 | return; | ||
75 | pg = get_order(size); | ||
76 | free_pages((unsigned long) ptr, pg); | ||
77 | } | ||
78 | EXPORT_SYMBOL(snd_free_pages); | ||
79 | |||
80 | /* | ||
81 | * | ||
82 | * Bus-specific memory allocators | 35 | * Bus-specific memory allocators |
83 | * | 36 | * |
84 | */ | 37 | */ |
@@ -190,8 +143,8 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, | |||
190 | dmab->bytes = 0; | 143 | dmab->bytes = 0; |
191 | switch (type) { | 144 | switch (type) { |
192 | case SNDRV_DMA_TYPE_CONTINUOUS: | 145 | case SNDRV_DMA_TYPE_CONTINUOUS: |
193 | dmab->area = snd_malloc_pages(size, | 146 | dmab->area = alloc_pages_exact(size, |
194 | (__force gfp_t)(unsigned long)device); | 147 | (__force gfp_t)(unsigned long)device); |
195 | dmab->addr = 0; | 148 | dmab->addr = 0; |
196 | break; | 149 | break; |
197 | #ifdef CONFIG_HAS_DMA | 150 | #ifdef CONFIG_HAS_DMA |
@@ -275,7 +228,7 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab) | |||
275 | { | 228 | { |
276 | switch (dmab->dev.type) { | 229 | switch (dmab->dev.type) { |
277 | case SNDRV_DMA_TYPE_CONTINUOUS: | 230 | case SNDRV_DMA_TYPE_CONTINUOUS: |
278 | snd_free_pages(dmab->area, dmab->bytes); | 231 | free_pages_exact(dmab->area, dmab->bytes); |
279 | break; | 232 | break; |
280 | #ifdef CONFIG_HAS_DMA | 233 | #ifdef CONFIG_HAS_DMA |
281 | #ifdef CONFIG_GENERIC_ALLOCATOR | 234 | #ifdef CONFIG_GENERIC_ALLOCATOR |
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 64d904bee8bb..c8618678649c 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c | |||
@@ -1403,24 +1403,32 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd) | |||
1403 | 1403 | ||
1404 | static int __init alsa_mixer_oss_init(void) | 1404 | static int __init alsa_mixer_oss_init(void) |
1405 | { | 1405 | { |
1406 | struct snd_card *card; | ||
1406 | int idx; | 1407 | int idx; |
1407 | 1408 | ||
1408 | snd_mixer_oss_notify_callback = snd_mixer_oss_notify_handler; | 1409 | snd_mixer_oss_notify_callback = snd_mixer_oss_notify_handler; |
1409 | for (idx = 0; idx < SNDRV_CARDS; idx++) { | 1410 | for (idx = 0; idx < SNDRV_CARDS; idx++) { |
1410 | if (snd_cards[idx]) | 1411 | card = snd_card_ref(idx); |
1411 | snd_mixer_oss_notify_handler(snd_cards[idx], SND_MIXER_OSS_NOTIFY_REGISTER); | 1412 | if (card) { |
1413 | snd_mixer_oss_notify_handler(card, SND_MIXER_OSS_NOTIFY_REGISTER); | ||
1414 | snd_card_unref(card); | ||
1415 | } | ||
1412 | } | 1416 | } |
1413 | return 0; | 1417 | return 0; |
1414 | } | 1418 | } |
1415 | 1419 | ||
1416 | static void __exit alsa_mixer_oss_exit(void) | 1420 | static void __exit alsa_mixer_oss_exit(void) |
1417 | { | 1421 | { |
1422 | struct snd_card *card; | ||
1418 | int idx; | 1423 | int idx; |
1419 | 1424 | ||
1420 | snd_mixer_oss_notify_callback = NULL; | 1425 | snd_mixer_oss_notify_callback = NULL; |
1421 | for (idx = 0; idx < SNDRV_CARDS; idx++) { | 1426 | for (idx = 0; idx < SNDRV_CARDS; idx++) { |
1422 | if (snd_cards[idx]) | 1427 | card = snd_card_ref(idx); |
1423 | snd_mixer_oss_notify_handler(snd_cards[idx], SND_MIXER_OSS_NOTIFY_FREE); | 1428 | if (card) { |
1429 | snd_mixer_oss_notify_handler(card, SND_MIXER_OSS_NOTIFY_FREE); | ||
1430 | snd_card_unref(card); | ||
1431 | } | ||
1424 | } | 1432 | } |
1425 | } | 1433 | } |
1426 | 1434 | ||
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 7b63aee124af..998e477522fd 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -959,22 +959,22 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
959 | return -ENOMEM; | 959 | return -ENOMEM; |
960 | 960 | ||
961 | size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)); | 961 | size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)); |
962 | runtime->status = snd_malloc_pages(size, GFP_KERNEL); | 962 | runtime->status = alloc_pages_exact(size, GFP_KERNEL); |
963 | if (runtime->status == NULL) { | 963 | if (runtime->status == NULL) { |
964 | kfree(runtime); | 964 | kfree(runtime); |
965 | return -ENOMEM; | 965 | return -ENOMEM; |
966 | } | 966 | } |
967 | memset((void*)runtime->status, 0, size); | 967 | memset(runtime->status, 0, size); |
968 | 968 | ||
969 | size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)); | 969 | size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)); |
970 | runtime->control = snd_malloc_pages(size, GFP_KERNEL); | 970 | runtime->control = alloc_pages_exact(size, GFP_KERNEL); |
971 | if (runtime->control == NULL) { | 971 | if (runtime->control == NULL) { |
972 | snd_free_pages((void*)runtime->status, | 972 | free_pages_exact(runtime->status, |
973 | PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))); | 973 | PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))); |
974 | kfree(runtime); | 974 | kfree(runtime); |
975 | return -ENOMEM; | 975 | return -ENOMEM; |
976 | } | 976 | } |
977 | memset((void*)runtime->control, 0, size); | 977 | memset(runtime->control, 0, size); |
978 | 978 | ||
979 | init_waitqueue_head(&runtime->sleep); | 979 | init_waitqueue_head(&runtime->sleep); |
980 | init_waitqueue_head(&runtime->tsleep); | 980 | init_waitqueue_head(&runtime->tsleep); |
@@ -1000,9 +1000,9 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) | |||
1000 | runtime = substream->runtime; | 1000 | runtime = substream->runtime; |
1001 | if (runtime->private_free != NULL) | 1001 | if (runtime->private_free != NULL) |
1002 | runtime->private_free(runtime); | 1002 | runtime->private_free(runtime); |
1003 | snd_free_pages((void*)runtime->status, | 1003 | free_pages_exact(runtime->status, |
1004 | PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))); | 1004 | PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))); |
1005 | snd_free_pages((void*)runtime->control, | 1005 | free_pages_exact(runtime->control, |
1006 | PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control))); | 1006 | PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control))); |
1007 | kfree(runtime->hw_constraints.rules); | 1007 | kfree(runtime->hw_constraints.rules); |
1008 | /* Avoid concurrent access to runtime via PCM timer interface */ | 1008 | /* Avoid concurrent access to runtime via PCM timer interface */ |
diff --git a/sound/core/seq/oss/seq_oss_device.h b/sound/core/seq/oss/seq_oss_device.h index 2d0e9eaf13aa..77eb1fe1155c 100644 --- a/sound/core/seq/oss/seq_oss_device.h +++ b/sound/core/seq/oss/seq_oss_device.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <sound/rawmidi.h> | 30 | #include <sound/rawmidi.h> |
31 | #include <sound/seq_kernel.h> | 31 | #include <sound/seq_kernel.h> |
32 | #include <sound/info.h> | 32 | #include <sound/info.h> |
33 | #include "../seq_clientmgr.h" | ||
33 | 34 | ||
34 | /* max. applications */ | 35 | /* max. applications */ |
35 | #define SNDRV_SEQ_OSS_MAX_CLIENTS 16 | 36 | #define SNDRV_SEQ_OSS_MAX_CLIENTS 16 |
@@ -150,11 +151,16 @@ snd_seq_oss_dispatch(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int a | |||
150 | return snd_seq_kernel_client_dispatch(dp->cseq, ev, atomic, hop); | 151 | return snd_seq_kernel_client_dispatch(dp->cseq, ev, atomic, hop); |
151 | } | 152 | } |
152 | 153 | ||
153 | /* ioctl */ | 154 | /* ioctl for writeq */ |
154 | static inline int | 155 | static inline int |
155 | snd_seq_oss_control(struct seq_oss_devinfo *dp, unsigned int type, void *arg) | 156 | snd_seq_oss_control(struct seq_oss_devinfo *dp, unsigned int type, void *arg) |
156 | { | 157 | { |
157 | return snd_seq_kernel_client_ctl(dp->cseq, type, arg); | 158 | int err; |
159 | |||
160 | snd_seq_client_ioctl_lock(dp->cseq); | ||
161 | err = snd_seq_kernel_client_ctl(dp->cseq, type, arg); | ||
162 | snd_seq_client_ioctl_unlock(dp->cseq); | ||
163 | return err; | ||
158 | } | 164 | } |
159 | 165 | ||
160 | /* fill the addresses in header */ | 166 | /* fill the addresses in header */ |
diff --git a/sound/core/seq/oss/seq_oss_rw.c b/sound/core/seq/oss/seq_oss_rw.c index 30886f5fb100..eb1ef12181f3 100644 --- a/sound/core/seq/oss/seq_oss_rw.c +++ b/sound/core/seq/oss/seq_oss_rw.c | |||
@@ -180,14 +180,11 @@ insert_queue(struct seq_oss_devinfo *dp, union evrec *rec, struct file *opt) | |||
180 | return 0; /* invalid event - no need to insert queue */ | 180 | return 0; /* invalid event - no need to insert queue */ |
181 | 181 | ||
182 | event.time.tick = snd_seq_oss_timer_cur_tick(dp->timer); | 182 | event.time.tick = snd_seq_oss_timer_cur_tick(dp->timer); |
183 | if (dp->timer->realtime || !dp->timer->running) { | 183 | if (dp->timer->realtime || !dp->timer->running) |
184 | snd_seq_oss_dispatch(dp, &event, 0, 0); | 184 | snd_seq_oss_dispatch(dp, &event, 0, 0); |
185 | } else { | 185 | else |
186 | if (is_nonblock_mode(dp->file_mode)) | 186 | rc = snd_seq_kernel_client_enqueue(dp->cseq, &event, opt, |
187 | rc = snd_seq_kernel_client_enqueue(dp->cseq, &event, 0, 0); | 187 | !is_nonblock_mode(dp->file_mode)); |
188 | else | ||
189 | rc = snd_seq_kernel_client_enqueue_blocking(dp->cseq, &event, opt, 0, 0); | ||
190 | } | ||
191 | return rc; | 188 | return rc; |
192 | } | 189 | } |
193 | 190 | ||
diff --git a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c index 5e04f4df10e4..b2f69617591f 100644 --- a/sound/core/seq/oss/seq_oss_writeq.c +++ b/sound/core/seq/oss/seq_oss_writeq.c | |||
@@ -116,7 +116,7 @@ snd_seq_oss_writeq_sync(struct seq_oss_writeq *q) | |||
116 | rec->t.code = SEQ_SYNCTIMER; | 116 | rec->t.code = SEQ_SYNCTIMER; |
117 | rec->t.time = time; | 117 | rec->t.time = time; |
118 | q->sync_event_put = 1; | 118 | q->sync_event_put = 1; |
119 | snd_seq_kernel_client_enqueue_blocking(dp->cseq, &ev, NULL, 0, 0); | 119 | snd_seq_kernel_client_enqueue(dp->cseq, &ev, NULL, true); |
120 | } | 120 | } |
121 | 121 | ||
122 | wait_event_interruptible_timeout(q->sync_sleep, ! q->sync_event_put, HZ); | 122 | wait_event_interruptible_timeout(q->sync_sleep, ! q->sync_event_put, HZ); |
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 7d4640d1fe9f..c0227a672442 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c | |||
@@ -179,6 +179,41 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid) | |||
179 | return client; | 179 | return client; |
180 | } | 180 | } |
181 | 181 | ||
182 | /* Take refcount and perform ioctl_mutex lock on the given client; | ||
183 | * used only for OSS sequencer | ||
184 | * Unlock via snd_seq_client_ioctl_unlock() below | ||
185 | */ | ||
186 | bool snd_seq_client_ioctl_lock(int clientid) | ||
187 | { | ||
188 | struct snd_seq_client *client; | ||
189 | |||
190 | client = snd_seq_client_use_ptr(clientid); | ||
191 | if (!client) | ||
192 | return false; | ||
193 | mutex_lock(&client->ioctl_mutex); | ||
194 | /* The client isn't unrefed here; see snd_seq_client_ioctl_unlock() */ | ||
195 | return true; | ||
196 | } | ||
197 | EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_lock); | ||
198 | |||
199 | /* Unlock and unref the given client; for OSS sequencer use only */ | ||
200 | void snd_seq_client_ioctl_unlock(int clientid) | ||
201 | { | ||
202 | struct snd_seq_client *client; | ||
203 | |||
204 | client = snd_seq_client_use_ptr(clientid); | ||
205 | if (WARN_ON(!client)) | ||
206 | return; | ||
207 | mutex_unlock(&client->ioctl_mutex); | ||
208 | /* The doubly unrefs below are intentional; the first one releases the | ||
209 | * leftover from snd_seq_client_ioctl_lock() above, and the second one | ||
210 | * is for releasing snd_seq_client_use_ptr() in this function | ||
211 | */ | ||
212 | snd_seq_client_unlock(client); | ||
213 | snd_seq_client_unlock(client); | ||
214 | } | ||
215 | EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_unlock); | ||
216 | |||
182 | static void usage_alloc(struct snd_seq_usage *res, int num) | 217 | static void usage_alloc(struct snd_seq_usage *res, int num) |
183 | { | 218 | { |
184 | res->cur += num; | 219 | res->cur += num; |
@@ -203,7 +238,6 @@ int __init client_init_data(void) | |||
203 | 238 | ||
204 | static struct snd_seq_client *seq_create_client1(int client_index, int poolsize) | 239 | static struct snd_seq_client *seq_create_client1(int client_index, int poolsize) |
205 | { | 240 | { |
206 | unsigned long flags; | ||
207 | int c; | 241 | int c; |
208 | struct snd_seq_client *client; | 242 | struct snd_seq_client *client; |
209 | 243 | ||
@@ -224,7 +258,7 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize) | |||
224 | mutex_init(&client->ioctl_mutex); | 258 | mutex_init(&client->ioctl_mutex); |
225 | 259 | ||
226 | /* find free slot in the client table */ | 260 | /* find free slot in the client table */ |
227 | spin_lock_irqsave(&clients_lock, flags); | 261 | spin_lock_irq(&clients_lock); |
228 | if (client_index < 0) { | 262 | if (client_index < 0) { |
229 | for (c = SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN; | 263 | for (c = SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN; |
230 | c < SNDRV_SEQ_MAX_CLIENTS; | 264 | c < SNDRV_SEQ_MAX_CLIENTS; |
@@ -232,17 +266,17 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize) | |||
232 | if (clienttab[c] || clienttablock[c]) | 266 | if (clienttab[c] || clienttablock[c]) |
233 | continue; | 267 | continue; |
234 | clienttab[client->number = c] = client; | 268 | clienttab[client->number = c] = client; |
235 | spin_unlock_irqrestore(&clients_lock, flags); | 269 | spin_unlock_irq(&clients_lock); |
236 | return client; | 270 | return client; |
237 | } | 271 | } |
238 | } else { | 272 | } else { |
239 | if (clienttab[client_index] == NULL && !clienttablock[client_index]) { | 273 | if (clienttab[client_index] == NULL && !clienttablock[client_index]) { |
240 | clienttab[client->number = client_index] = client; | 274 | clienttab[client->number = client_index] = client; |
241 | spin_unlock_irqrestore(&clients_lock, flags); | 275 | spin_unlock_irq(&clients_lock); |
242 | return client; | 276 | return client; |
243 | } | 277 | } |
244 | } | 278 | } |
245 | spin_unlock_irqrestore(&clients_lock, flags); | 279 | spin_unlock_irq(&clients_lock); |
246 | snd_seq_pool_delete(&client->pool); | 280 | snd_seq_pool_delete(&client->pool); |
247 | kfree(client); | 281 | kfree(client); |
248 | return NULL; /* no free slot found or busy, return failure code */ | 282 | return NULL; /* no free slot found or busy, return failure code */ |
@@ -251,23 +285,21 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize) | |||
251 | 285 | ||
252 | static int seq_free_client1(struct snd_seq_client *client) | 286 | static int seq_free_client1(struct snd_seq_client *client) |
253 | { | 287 | { |
254 | unsigned long flags; | ||
255 | |||
256 | if (!client) | 288 | if (!client) |
257 | return 0; | 289 | return 0; |
258 | spin_lock_irqsave(&clients_lock, flags); | 290 | spin_lock_irq(&clients_lock); |
259 | clienttablock[client->number] = 1; | 291 | clienttablock[client->number] = 1; |
260 | clienttab[client->number] = NULL; | 292 | clienttab[client->number] = NULL; |
261 | spin_unlock_irqrestore(&clients_lock, flags); | 293 | spin_unlock_irq(&clients_lock); |
262 | snd_seq_delete_all_ports(client); | 294 | snd_seq_delete_all_ports(client); |
263 | snd_seq_queue_client_leave(client->number); | 295 | snd_seq_queue_client_leave(client->number); |
264 | snd_use_lock_sync(&client->use_lock); | 296 | snd_use_lock_sync(&client->use_lock); |
265 | snd_seq_queue_client_termination(client->number); | 297 | snd_seq_queue_client_termination(client->number); |
266 | if (client->pool) | 298 | if (client->pool) |
267 | snd_seq_pool_delete(&client->pool); | 299 | snd_seq_pool_delete(&client->pool); |
268 | spin_lock_irqsave(&clients_lock, flags); | 300 | spin_lock_irq(&clients_lock); |
269 | clienttablock[client->number] = 0; | 301 | clienttablock[client->number] = 0; |
270 | spin_unlock_irqrestore(&clients_lock, flags); | 302 | spin_unlock_irq(&clients_lock); |
271 | return 0; | 303 | return 0; |
272 | } | 304 | } |
273 | 305 | ||
@@ -1252,7 +1284,7 @@ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client, | |||
1252 | 1284 | ||
1253 | /* fill the info fields */ | 1285 | /* fill the info fields */ |
1254 | if (client_info->name[0]) | 1286 | if (client_info->name[0]) |
1255 | strlcpy(client->name, client_info->name, sizeof(client->name)); | 1287 | strscpy(client->name, client_info->name, sizeof(client->name)); |
1256 | 1288 | ||
1257 | client->filter = client_info->filter; | 1289 | client->filter = client_info->filter; |
1258 | client->event_lost = client_info->event_lost; | 1290 | client->event_lost = client_info->event_lost; |
@@ -1530,7 +1562,7 @@ static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg) | |||
1530 | /* set queue name */ | 1562 | /* set queue name */ |
1531 | if (!info->name[0]) | 1563 | if (!info->name[0]) |
1532 | snprintf(info->name, sizeof(info->name), "Queue-%d", q->queue); | 1564 | snprintf(info->name, sizeof(info->name), "Queue-%d", q->queue); |
1533 | strlcpy(q->name, info->name, sizeof(q->name)); | 1565 | strscpy(q->name, info->name, sizeof(q->name)); |
1534 | snd_use_lock_free(&q->use_lock); | 1566 | snd_use_lock_free(&q->use_lock); |
1535 | 1567 | ||
1536 | return 0; | 1568 | return 0; |
@@ -1592,7 +1624,7 @@ static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client, | |||
1592 | queuefree(q); | 1624 | queuefree(q); |
1593 | return -EPERM; | 1625 | return -EPERM; |
1594 | } | 1626 | } |
1595 | strlcpy(q->name, info->name, sizeof(q->name)); | 1627 | strscpy(q->name, info->name, sizeof(q->name)); |
1596 | queuefree(q); | 1628 | queuefree(q); |
1597 | 1629 | ||
1598 | return 0; | 1630 | return 0; |
@@ -1900,20 +1932,14 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, | |||
1900 | int result; | 1932 | int result; |
1901 | struct snd_seq_client *sender = NULL; | 1933 | struct snd_seq_client *sender = NULL; |
1902 | struct snd_seq_client_port *sport = NULL; | 1934 | struct snd_seq_client_port *sport = NULL; |
1903 | struct snd_seq_subscribers *p; | ||
1904 | 1935 | ||
1905 | result = -EINVAL; | 1936 | result = -EINVAL; |
1906 | if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) | 1937 | if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) |
1907 | goto __end; | 1938 | goto __end; |
1908 | if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) | 1939 | if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) |
1909 | goto __end; | 1940 | goto __end; |
1910 | p = snd_seq_port_get_subscription(&sport->c_src, &subs->dest); | 1941 | result = snd_seq_port_get_subscription(&sport->c_src, &subs->dest, |
1911 | if (p) { | 1942 | subs); |
1912 | result = 0; | ||
1913 | *subs = p->info; | ||
1914 | } else | ||
1915 | result = -ENOENT; | ||
1916 | |||
1917 | __end: | 1943 | __end: |
1918 | if (sport) | 1944 | if (sport) |
1919 | snd_seq_port_unlock(sport); | 1945 | snd_seq_port_unlock(sport); |
@@ -2227,12 +2253,13 @@ int snd_seq_delete_kernel_client(int client) | |||
2227 | } | 2253 | } |
2228 | EXPORT_SYMBOL(snd_seq_delete_kernel_client); | 2254 | EXPORT_SYMBOL(snd_seq_delete_kernel_client); |
2229 | 2255 | ||
2230 | /* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue | 2256 | /* |
2231 | * and snd_seq_kernel_client_enqueue_blocking | 2257 | * exported, called by kernel clients to enqueue events (w/o blocking) |
2258 | * | ||
2259 | * RETURN VALUE: zero if succeed, negative if error | ||
2232 | */ | 2260 | */ |
2233 | static int kernel_client_enqueue(int client, struct snd_seq_event *ev, | 2261 | int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev, |
2234 | struct file *file, int blocking, | 2262 | struct file *file, bool blocking) |
2235 | int atomic, int hop) | ||
2236 | { | 2263 | { |
2237 | struct snd_seq_client *cptr; | 2264 | struct snd_seq_client *cptr; |
2238 | int result; | 2265 | int result; |
@@ -2255,41 +2282,21 @@ static int kernel_client_enqueue(int client, struct snd_seq_event *ev, | |||
2255 | if (cptr == NULL) | 2282 | if (cptr == NULL) |
2256 | return -EINVAL; | 2283 | return -EINVAL; |
2257 | 2284 | ||
2258 | if (! cptr->accept_output) | 2285 | if (!cptr->accept_output) { |
2259 | result = -EPERM; | 2286 | result = -EPERM; |
2260 | else /* send it */ | 2287 | } else { /* send it */ |
2288 | mutex_lock(&cptr->ioctl_mutex); | ||
2261 | result = snd_seq_client_enqueue_event(cptr, ev, file, blocking, | 2289 | result = snd_seq_client_enqueue_event(cptr, ev, file, blocking, |
2262 | atomic, hop, NULL); | 2290 | false, 0, |
2291 | &cptr->ioctl_mutex); | ||
2292 | mutex_unlock(&cptr->ioctl_mutex); | ||
2293 | } | ||
2263 | 2294 | ||
2264 | snd_seq_client_unlock(cptr); | 2295 | snd_seq_client_unlock(cptr); |
2265 | return result; | 2296 | return result; |
2266 | } | 2297 | } |
2267 | |||
2268 | /* | ||
2269 | * exported, called by kernel clients to enqueue events (w/o blocking) | ||
2270 | * | ||
2271 | * RETURN VALUE: zero if succeed, negative if error | ||
2272 | */ | ||
2273 | int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event * ev, | ||
2274 | int atomic, int hop) | ||
2275 | { | ||
2276 | return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop); | ||
2277 | } | ||
2278 | EXPORT_SYMBOL(snd_seq_kernel_client_enqueue); | 2298 | EXPORT_SYMBOL(snd_seq_kernel_client_enqueue); |
2279 | 2299 | ||
2280 | /* | ||
2281 | * exported, called by kernel clients to enqueue events (with blocking) | ||
2282 | * | ||
2283 | * RETURN VALUE: zero if succeed, negative if error | ||
2284 | */ | ||
2285 | int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev, | ||
2286 | struct file *file, | ||
2287 | int atomic, int hop) | ||
2288 | { | ||
2289 | return kernel_client_enqueue(client, ev, file, 1, atomic, hop); | ||
2290 | } | ||
2291 | EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking); | ||
2292 | |||
2293 | /* | 2300 | /* |
2294 | * exported, called by kernel clients to dispatch events directly to other | 2301 | * exported, called by kernel clients to dispatch events directly to other |
2295 | * clients, bypassing the queues. Event time-stamp will be updated. | 2302 | * clients, bypassing the queues. Event time-stamp will be updated. |
diff --git a/sound/core/seq/seq_clientmgr.h b/sound/core/seq/seq_clientmgr.h index 0611e1e0ed5b..28a51dcc0190 100644 --- a/sound/core/seq/seq_clientmgr.h +++ b/sound/core/seq/seq_clientmgr.h | |||
@@ -93,14 +93,14 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid); | |||
93 | /* dispatch event to client(s) */ | 93 | /* dispatch event to client(s) */ |
94 | int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop); | 94 | int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop); |
95 | 95 | ||
96 | /* exported to other modules */ | ||
97 | int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev, int atomic, int hop); | ||
98 | int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev, | ||
99 | struct file *file, int atomic, int hop); | ||
100 | int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait); | 96 | int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait); |
101 | int snd_seq_client_notify_subscription(int client, int port, | 97 | int snd_seq_client_notify_subscription(int client, int port, |
102 | struct snd_seq_port_subscribe *info, int evtype); | 98 | struct snd_seq_port_subscribe *info, int evtype); |
103 | 99 | ||
100 | /* only for OSS sequencer */ | ||
101 | bool snd_seq_client_ioctl_lock(int clientid); | ||
102 | void snd_seq_client_ioctl_unlock(int clientid); | ||
103 | |||
104 | extern int seq_client_load[15]; | 104 | extern int seq_client_load[15]; |
105 | 105 | ||
106 | #endif | 106 | #endif |
diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c index 72c0302a55d2..97ee89cb6426 100644 --- a/sound/core/seq/seq_fifo.c +++ b/sound/core/seq/seq_fifo.c | |||
@@ -98,18 +98,17 @@ static struct snd_seq_event_cell *fifo_cell_out(struct snd_seq_fifo *f); | |||
98 | void snd_seq_fifo_clear(struct snd_seq_fifo *f) | 98 | void snd_seq_fifo_clear(struct snd_seq_fifo *f) |
99 | { | 99 | { |
100 | struct snd_seq_event_cell *cell; | 100 | struct snd_seq_event_cell *cell; |
101 | unsigned long flags; | ||
102 | 101 | ||
103 | /* clear overflow flag */ | 102 | /* clear overflow flag */ |
104 | atomic_set(&f->overflow, 0); | 103 | atomic_set(&f->overflow, 0); |
105 | 104 | ||
106 | snd_use_lock_sync(&f->use_lock); | 105 | snd_use_lock_sync(&f->use_lock); |
107 | spin_lock_irqsave(&f->lock, flags); | 106 | spin_lock_irq(&f->lock); |
108 | /* drain the fifo */ | 107 | /* drain the fifo */ |
109 | while ((cell = fifo_cell_out(f)) != NULL) { | 108 | while ((cell = fifo_cell_out(f)) != NULL) { |
110 | snd_seq_cell_free(cell); | 109 | snd_seq_cell_free(cell); |
111 | } | 110 | } |
112 | spin_unlock_irqrestore(&f->lock, flags); | 111 | spin_unlock_irq(&f->lock); |
113 | } | 112 | } |
114 | 113 | ||
115 | 114 | ||
@@ -195,9 +194,9 @@ int snd_seq_fifo_cell_out(struct snd_seq_fifo *f, | |||
195 | } | 194 | } |
196 | set_current_state(TASK_INTERRUPTIBLE); | 195 | set_current_state(TASK_INTERRUPTIBLE); |
197 | add_wait_queue(&f->input_sleep, &wait); | 196 | add_wait_queue(&f->input_sleep, &wait); |
198 | spin_unlock_irq(&f->lock); | 197 | spin_unlock_irqrestore(&f->lock, flags); |
199 | schedule(); | 198 | schedule(); |
200 | spin_lock_irq(&f->lock); | 199 | spin_lock_irqsave(&f->lock, flags); |
201 | remove_wait_queue(&f->input_sleep, &wait); | 200 | remove_wait_queue(&f->input_sleep, &wait); |
202 | if (signal_pending(current)) { | 201 | if (signal_pending(current)) { |
203 | spin_unlock_irqrestore(&f->lock, flags); | 202 | spin_unlock_irqrestore(&f->lock, flags); |
@@ -239,7 +238,6 @@ int snd_seq_fifo_poll_wait(struct snd_seq_fifo *f, struct file *file, | |||
239 | /* change the size of pool; all old events are removed */ | 238 | /* change the size of pool; all old events are removed */ |
240 | int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize) | 239 | int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize) |
241 | { | 240 | { |
242 | unsigned long flags; | ||
243 | struct snd_seq_pool *newpool, *oldpool; | 241 | struct snd_seq_pool *newpool, *oldpool; |
244 | struct snd_seq_event_cell *cell, *next, *oldhead; | 242 | struct snd_seq_event_cell *cell, *next, *oldhead; |
245 | 243 | ||
@@ -255,7 +253,7 @@ int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize) | |||
255 | return -ENOMEM; | 253 | return -ENOMEM; |
256 | } | 254 | } |
257 | 255 | ||
258 | spin_lock_irqsave(&f->lock, flags); | 256 | spin_lock_irq(&f->lock); |
259 | /* remember old pool */ | 257 | /* remember old pool */ |
260 | oldpool = f->pool; | 258 | oldpool = f->pool; |
261 | oldhead = f->head; | 259 | oldhead = f->head; |
@@ -265,7 +263,7 @@ int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize) | |||
265 | f->tail = NULL; | 263 | f->tail = NULL; |
266 | f->cells = 0; | 264 | f->cells = 0; |
267 | /* NOTE: overflow flag is not cleared */ | 265 | /* NOTE: overflow flag is not cleared */ |
268 | spin_unlock_irqrestore(&f->lock, flags); | 266 | spin_unlock_irq(&f->lock); |
269 | 267 | ||
270 | /* close the old pool and wait until all users are gone */ | 268 | /* close the old pool and wait until all users are gone */ |
271 | snd_seq_pool_mark_closing(oldpool); | 269 | snd_seq_pool_mark_closing(oldpool); |
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index 5b0388202bac..19b718e871c5 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/export.h> | 24 | #include <linux/export.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/sched/signal.h> | 26 | #include <linux/sched/signal.h> |
27 | #include <linux/vmalloc.h> | 27 | #include <linux/mm.h> |
28 | #include <sound/core.h> | 28 | #include <sound/core.h> |
29 | 29 | ||
30 | #include <sound/seq_kernel.h> | 30 | #include <sound/seq_kernel.h> |
@@ -244,13 +244,13 @@ static int snd_seq_cell_alloc(struct snd_seq_pool *pool, | |||
244 | 244 | ||
245 | set_current_state(TASK_INTERRUPTIBLE); | 245 | set_current_state(TASK_INTERRUPTIBLE); |
246 | add_wait_queue(&pool->output_sleep, &wait); | 246 | add_wait_queue(&pool->output_sleep, &wait); |
247 | spin_unlock_irq(&pool->lock); | 247 | spin_unlock_irqrestore(&pool->lock, flags); |
248 | if (mutexp) | 248 | if (mutexp) |
249 | mutex_unlock(mutexp); | 249 | mutex_unlock(mutexp); |
250 | schedule(); | 250 | schedule(); |
251 | if (mutexp) | 251 | if (mutexp) |
252 | mutex_lock(mutexp); | 252 | mutex_lock(mutexp); |
253 | spin_lock_irq(&pool->lock); | 253 | spin_lock_irqsave(&pool->lock, flags); |
254 | remove_wait_queue(&pool->output_sleep, &wait); | 254 | remove_wait_queue(&pool->output_sleep, &wait); |
255 | /* interrupted? */ | 255 | /* interrupted? */ |
256 | if (signal_pending(current)) { | 256 | if (signal_pending(current)) { |
@@ -384,21 +384,20 @@ int snd_seq_pool_init(struct snd_seq_pool *pool) | |||
384 | { | 384 | { |
385 | int cell; | 385 | int cell; |
386 | struct snd_seq_event_cell *cellptr; | 386 | struct snd_seq_event_cell *cellptr; |
387 | unsigned long flags; | ||
388 | 387 | ||
389 | if (snd_BUG_ON(!pool)) | 388 | if (snd_BUG_ON(!pool)) |
390 | return -EINVAL; | 389 | return -EINVAL; |
391 | 390 | ||
392 | cellptr = vmalloc(array_size(sizeof(struct snd_seq_event_cell), | 391 | cellptr = kvmalloc_array(sizeof(struct snd_seq_event_cell), pool->size, |
393 | pool->size)); | 392 | GFP_KERNEL); |
394 | if (!cellptr) | 393 | if (!cellptr) |
395 | return -ENOMEM; | 394 | return -ENOMEM; |
396 | 395 | ||
397 | /* add new cells to the free cell list */ | 396 | /* add new cells to the free cell list */ |
398 | spin_lock_irqsave(&pool->lock, flags); | 397 | spin_lock_irq(&pool->lock); |
399 | if (pool->ptr) { | 398 | if (pool->ptr) { |
400 | spin_unlock_irqrestore(&pool->lock, flags); | 399 | spin_unlock_irq(&pool->lock); |
401 | vfree(cellptr); | 400 | kvfree(cellptr); |
402 | return 0; | 401 | return 0; |
403 | } | 402 | } |
404 | 403 | ||
@@ -416,7 +415,7 @@ int snd_seq_pool_init(struct snd_seq_pool *pool) | |||
416 | /* init statistics */ | 415 | /* init statistics */ |
417 | pool->max_used = 0; | 416 | pool->max_used = 0; |
418 | pool->total_elements = pool->size; | 417 | pool->total_elements = pool->size; |
419 | spin_unlock_irqrestore(&pool->lock, flags); | 418 | spin_unlock_irq(&pool->lock); |
420 | return 0; | 419 | return 0; |
421 | } | 420 | } |
422 | 421 | ||
@@ -435,7 +434,6 @@ void snd_seq_pool_mark_closing(struct snd_seq_pool *pool) | |||
435 | /* remove events */ | 434 | /* remove events */ |
436 | int snd_seq_pool_done(struct snd_seq_pool *pool) | 435 | int snd_seq_pool_done(struct snd_seq_pool *pool) |
437 | { | 436 | { |
438 | unsigned long flags; | ||
439 | struct snd_seq_event_cell *ptr; | 437 | struct snd_seq_event_cell *ptr; |
440 | 438 | ||
441 | if (snd_BUG_ON(!pool)) | 439 | if (snd_BUG_ON(!pool)) |
@@ -449,18 +447,18 @@ int snd_seq_pool_done(struct snd_seq_pool *pool) | |||
449 | schedule_timeout_uninterruptible(1); | 447 | schedule_timeout_uninterruptible(1); |
450 | 448 | ||
451 | /* release all resources */ | 449 | /* release all resources */ |
452 | spin_lock_irqsave(&pool->lock, flags); | 450 | spin_lock_irq(&pool->lock); |
453 | ptr = pool->ptr; | 451 | ptr = pool->ptr; |
454 | pool->ptr = NULL; | 452 | pool->ptr = NULL; |
455 | pool->free = NULL; | 453 | pool->free = NULL; |
456 | pool->total_elements = 0; | 454 | pool->total_elements = 0; |
457 | spin_unlock_irqrestore(&pool->lock, flags); | 455 | spin_unlock_irq(&pool->lock); |
458 | 456 | ||
459 | vfree(ptr); | 457 | kvfree(ptr); |
460 | 458 | ||
461 | spin_lock_irqsave(&pool->lock, flags); | 459 | spin_lock_irq(&pool->lock); |
462 | pool->closing = 0; | 460 | pool->closing = 0; |
463 | spin_unlock_irqrestore(&pool->lock, flags); | 461 | spin_unlock_irq(&pool->lock); |
464 | 462 | ||
465 | return 0; | 463 | return 0; |
466 | } | 464 | } |
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 24d90abfc64d..ac7556ab531c 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c | |||
@@ -128,7 +128,6 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp) | |||
128 | struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, | 128 | struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, |
129 | int port) | 129 | int port) |
130 | { | 130 | { |
131 | unsigned long flags; | ||
132 | struct snd_seq_client_port *new_port, *p; | 131 | struct snd_seq_client_port *new_port, *p; |
133 | int num = -1; | 132 | int num = -1; |
134 | 133 | ||
@@ -157,7 +156,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, | |||
157 | 156 | ||
158 | num = port >= 0 ? port : 0; | 157 | num = port >= 0 ? port : 0; |
159 | mutex_lock(&client->ports_mutex); | 158 | mutex_lock(&client->ports_mutex); |
160 | write_lock_irqsave(&client->ports_lock, flags); | 159 | write_lock_irq(&client->ports_lock); |
161 | list_for_each_entry(p, &client->ports_list_head, list) { | 160 | list_for_each_entry(p, &client->ports_list_head, list) { |
162 | if (p->addr.port > num) | 161 | if (p->addr.port > num) |
163 | break; | 162 | break; |
@@ -169,7 +168,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, | |||
169 | client->num_ports++; | 168 | client->num_ports++; |
170 | new_port->addr.port = num; /* store the port number in the port */ | 169 | new_port->addr.port = num; /* store the port number in the port */ |
171 | sprintf(new_port->name, "port-%d", num); | 170 | sprintf(new_port->name, "port-%d", num); |
172 | write_unlock_irqrestore(&client->ports_lock, flags); | 171 | write_unlock_irq(&client->ports_lock); |
173 | mutex_unlock(&client->ports_mutex); | 172 | mutex_unlock(&client->ports_mutex); |
174 | 173 | ||
175 | return new_port; | 174 | return new_port; |
@@ -283,11 +282,10 @@ static int port_delete(struct snd_seq_client *client, | |||
283 | /* delete a port with the given port id */ | 282 | /* delete a port with the given port id */ |
284 | int snd_seq_delete_port(struct snd_seq_client *client, int port) | 283 | int snd_seq_delete_port(struct snd_seq_client *client, int port) |
285 | { | 284 | { |
286 | unsigned long flags; | ||
287 | struct snd_seq_client_port *found = NULL, *p; | 285 | struct snd_seq_client_port *found = NULL, *p; |
288 | 286 | ||
289 | mutex_lock(&client->ports_mutex); | 287 | mutex_lock(&client->ports_mutex); |
290 | write_lock_irqsave(&client->ports_lock, flags); | 288 | write_lock_irq(&client->ports_lock); |
291 | list_for_each_entry(p, &client->ports_list_head, list) { | 289 | list_for_each_entry(p, &client->ports_list_head, list) { |
292 | if (p->addr.port == port) { | 290 | if (p->addr.port == port) { |
293 | /* ok found. delete from the list at first */ | 291 | /* ok found. delete from the list at first */ |
@@ -297,7 +295,7 @@ int snd_seq_delete_port(struct snd_seq_client *client, int port) | |||
297 | break; | 295 | break; |
298 | } | 296 | } |
299 | } | 297 | } |
300 | write_unlock_irqrestore(&client->ports_lock, flags); | 298 | write_unlock_irq(&client->ports_lock); |
301 | mutex_unlock(&client->ports_mutex); | 299 | mutex_unlock(&client->ports_mutex); |
302 | if (found) | 300 | if (found) |
303 | return port_delete(client, found); | 301 | return port_delete(client, found); |
@@ -308,7 +306,6 @@ int snd_seq_delete_port(struct snd_seq_client *client, int port) | |||
308 | /* delete the all ports belonging to the given client */ | 306 | /* delete the all ports belonging to the given client */ |
309 | int snd_seq_delete_all_ports(struct snd_seq_client *client) | 307 | int snd_seq_delete_all_ports(struct snd_seq_client *client) |
310 | { | 308 | { |
311 | unsigned long flags; | ||
312 | struct list_head deleted_list; | 309 | struct list_head deleted_list; |
313 | struct snd_seq_client_port *port, *tmp; | 310 | struct snd_seq_client_port *port, *tmp; |
314 | 311 | ||
@@ -316,7 +313,7 @@ int snd_seq_delete_all_ports(struct snd_seq_client *client) | |||
316 | * clear the port list in the client data. | 313 | * clear the port list in the client data. |
317 | */ | 314 | */ |
318 | mutex_lock(&client->ports_mutex); | 315 | mutex_lock(&client->ports_mutex); |
319 | write_lock_irqsave(&client->ports_lock, flags); | 316 | write_lock_irq(&client->ports_lock); |
320 | if (! list_empty(&client->ports_list_head)) { | 317 | if (! list_empty(&client->ports_list_head)) { |
321 | list_add(&deleted_list, &client->ports_list_head); | 318 | list_add(&deleted_list, &client->ports_list_head); |
322 | list_del_init(&client->ports_list_head); | 319 | list_del_init(&client->ports_list_head); |
@@ -324,7 +321,7 @@ int snd_seq_delete_all_ports(struct snd_seq_client *client) | |||
324 | INIT_LIST_HEAD(&deleted_list); | 321 | INIT_LIST_HEAD(&deleted_list); |
325 | } | 322 | } |
326 | client->num_ports = 0; | 323 | client->num_ports = 0; |
327 | write_unlock_irqrestore(&client->ports_lock, flags); | 324 | write_unlock_irq(&client->ports_lock); |
328 | 325 | ||
329 | /* remove each port in deleted_list */ | 326 | /* remove each port in deleted_list */ |
330 | list_for_each_entry_safe(port, tmp, &deleted_list, list) { | 327 | list_for_each_entry_safe(port, tmp, &deleted_list, list) { |
@@ -550,10 +547,10 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client, | |||
550 | list_del_init(list); | 547 | list_del_init(list); |
551 | grp->exclusive = 0; | 548 | grp->exclusive = 0; |
552 | write_unlock_irq(&grp->list_lock); | 549 | write_unlock_irq(&grp->list_lock); |
553 | up_write(&grp->list_mutex); | ||
554 | 550 | ||
555 | if (!empty) | 551 | if (!empty) |
556 | unsubscribe_port(client, port, grp, &subs->info, ack); | 552 | unsubscribe_port(client, port, grp, &subs->info, ack); |
553 | up_write(&grp->list_mutex); | ||
557 | } | 554 | } |
558 | 555 | ||
559 | /* connect two ports */ | 556 | /* connect two ports */ |
@@ -635,20 +632,23 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector, | |||
635 | 632 | ||
636 | 633 | ||
637 | /* get matched subscriber */ | 634 | /* get matched subscriber */ |
638 | struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp, | 635 | int snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp, |
639 | struct snd_seq_addr *dest_addr) | 636 | struct snd_seq_addr *dest_addr, |
637 | struct snd_seq_port_subscribe *subs) | ||
640 | { | 638 | { |
641 | struct snd_seq_subscribers *s, *found = NULL; | 639 | struct snd_seq_subscribers *s; |
640 | int err = -ENOENT; | ||
642 | 641 | ||
643 | down_read(&src_grp->list_mutex); | 642 | down_read(&src_grp->list_mutex); |
644 | list_for_each_entry(s, &src_grp->list_head, src_list) { | 643 | list_for_each_entry(s, &src_grp->list_head, src_list) { |
645 | if (addr_match(dest_addr, &s->info.dest)) { | 644 | if (addr_match(dest_addr, &s->info.dest)) { |
646 | found = s; | 645 | *subs = s->info; |
646 | err = 0; | ||
647 | break; | 647 | break; |
648 | } | 648 | } |
649 | } | 649 | } |
650 | up_read(&src_grp->list_mutex); | 650 | up_read(&src_grp->list_mutex); |
651 | return found; | 651 | return err; |
652 | } | 652 | } |
653 | 653 | ||
654 | /* | 654 | /* |
diff --git a/sound/core/seq/seq_ports.h b/sound/core/seq/seq_ports.h index 26bd71f36c41..06003b36652e 100644 --- a/sound/core/seq/seq_ports.h +++ b/sound/core/seq/seq_ports.h | |||
@@ -135,7 +135,8 @@ int snd_seq_port_subscribe(struct snd_seq_client_port *port, | |||
135 | struct snd_seq_port_subscribe *info); | 135 | struct snd_seq_port_subscribe *info); |
136 | 136 | ||
137 | /* get matched subscriber */ | 137 | /* get matched subscriber */ |
138 | struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp, | 138 | int snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp, |
139 | struct snd_seq_addr *dest_addr); | 139 | struct snd_seq_addr *dest_addr, |
140 | struct snd_seq_port_subscribe *subs); | ||
140 | 141 | ||
141 | #endif | 142 | #endif |
diff --git a/sound/core/sound.c b/sound/core/sound.c index b30f027eb0fe..a9ad4379523b 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c | |||
@@ -134,8 +134,11 @@ static struct snd_minor *autoload_device(unsigned int minor) | |||
134 | if (dev == SNDRV_MINOR_CONTROL) { | 134 | if (dev == SNDRV_MINOR_CONTROL) { |
135 | /* /dev/aloadC? */ | 135 | /* /dev/aloadC? */ |
136 | int card = SNDRV_MINOR_CARD(minor); | 136 | int card = SNDRV_MINOR_CARD(minor); |
137 | if (snd_cards[card] == NULL) | 137 | struct snd_card *ref = snd_card_ref(card); |
138 | if (!ref) | ||
138 | snd_request_card(card); | 139 | snd_request_card(card); |
140 | else | ||
141 | snd_card_unref(ref); | ||
139 | } else if (dev == SNDRV_MINOR_GLOBAL) { | 142 | } else if (dev == SNDRV_MINOR_GLOBAL) { |
140 | /* /dev/aloadSEQ */ | 143 | /* /dev/aloadSEQ */ |
141 | snd_request_other(minor); | 144 | snd_request_other(minor); |
diff --git a/sound/core/timer.c b/sound/core/timer.c index 61a0cec6e1f6..d23efec35660 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -38,6 +38,7 @@ | |||
38 | 38 | ||
39 | /* internal flags */ | 39 | /* internal flags */ |
40 | #define SNDRV_TIMER_IFLG_PAUSED 0x00010000 | 40 | #define SNDRV_TIMER_IFLG_PAUSED 0x00010000 |
41 | #define SNDRV_TIMER_IFLG_DEAD 0x00020000 | ||
41 | 42 | ||
42 | #if IS_ENABLED(CONFIG_SND_HRTIMER) | 43 | #if IS_ENABLED(CONFIG_SND_HRTIMER) |
43 | #define DEFAULT_TIMER_LIMIT 4 | 44 | #define DEFAULT_TIMER_LIMIT 4 |
@@ -254,19 +255,20 @@ int snd_timer_open(struct snd_timer_instance **ti, | |||
254 | struct snd_timer_instance *timeri = NULL; | 255 | struct snd_timer_instance *timeri = NULL; |
255 | int err; | 256 | int err; |
256 | 257 | ||
258 | mutex_lock(®ister_mutex); | ||
257 | if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) { | 259 | if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) { |
258 | /* open a slave instance */ | 260 | /* open a slave instance */ |
259 | if (tid->dev_sclass <= SNDRV_TIMER_SCLASS_NONE || | 261 | if (tid->dev_sclass <= SNDRV_TIMER_SCLASS_NONE || |
260 | tid->dev_sclass > SNDRV_TIMER_SCLASS_OSS_SEQUENCER) { | 262 | tid->dev_sclass > SNDRV_TIMER_SCLASS_OSS_SEQUENCER) { |
261 | pr_debug("ALSA: timer: invalid slave class %i\n", | 263 | pr_debug("ALSA: timer: invalid slave class %i\n", |
262 | tid->dev_sclass); | 264 | tid->dev_sclass); |
263 | return -EINVAL; | 265 | err = -EINVAL; |
266 | goto unlock; | ||
264 | } | 267 | } |
265 | mutex_lock(®ister_mutex); | ||
266 | timeri = snd_timer_instance_new(owner, NULL); | 268 | timeri = snd_timer_instance_new(owner, NULL); |
267 | if (!timeri) { | 269 | if (!timeri) { |
268 | mutex_unlock(®ister_mutex); | 270 | err = -ENOMEM; |
269 | return -ENOMEM; | 271 | goto unlock; |
270 | } | 272 | } |
271 | timeri->slave_class = tid->dev_sclass; | 273 | timeri->slave_class = tid->dev_sclass; |
272 | timeri->slave_id = tid->device; | 274 | timeri->slave_id = tid->device; |
@@ -277,13 +279,10 @@ int snd_timer_open(struct snd_timer_instance **ti, | |||
277 | snd_timer_close_locked(timeri); | 279 | snd_timer_close_locked(timeri); |
278 | timeri = NULL; | 280 | timeri = NULL; |
279 | } | 281 | } |
280 | mutex_unlock(®ister_mutex); | 282 | goto unlock; |
281 | *ti = timeri; | ||
282 | return err; | ||
283 | } | 283 | } |
284 | 284 | ||
285 | /* open a master instance */ | 285 | /* open a master instance */ |
286 | mutex_lock(®ister_mutex); | ||
287 | timer = snd_timer_find(tid); | 286 | timer = snd_timer_find(tid); |
288 | #ifdef CONFIG_MODULES | 287 | #ifdef CONFIG_MODULES |
289 | if (!timer) { | 288 | if (!timer) { |
@@ -294,25 +293,26 @@ int snd_timer_open(struct snd_timer_instance **ti, | |||
294 | } | 293 | } |
295 | #endif | 294 | #endif |
296 | if (!timer) { | 295 | if (!timer) { |
297 | mutex_unlock(®ister_mutex); | 296 | err = -ENODEV; |
298 | return -ENODEV; | 297 | goto unlock; |
299 | } | 298 | } |
300 | if (!list_empty(&timer->open_list_head)) { | 299 | if (!list_empty(&timer->open_list_head)) { |
301 | timeri = list_entry(timer->open_list_head.next, | 300 | timeri = list_entry(timer->open_list_head.next, |
302 | struct snd_timer_instance, open_list); | 301 | struct snd_timer_instance, open_list); |
303 | if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) { | 302 | if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) { |
304 | mutex_unlock(®ister_mutex); | 303 | err = -EBUSY; |
305 | return -EBUSY; | 304 | timeri = NULL; |
305 | goto unlock; | ||
306 | } | 306 | } |
307 | } | 307 | } |
308 | if (timer->num_instances >= timer->max_instances) { | 308 | if (timer->num_instances >= timer->max_instances) { |
309 | mutex_unlock(®ister_mutex); | 309 | err = -EBUSY; |
310 | return -EBUSY; | 310 | goto unlock; |
311 | } | 311 | } |
312 | timeri = snd_timer_instance_new(owner, timer); | 312 | timeri = snd_timer_instance_new(owner, timer); |
313 | if (!timeri) { | 313 | if (!timeri) { |
314 | mutex_unlock(®ister_mutex); | 314 | err = -ENOMEM; |
315 | return -ENOMEM; | 315 | goto unlock; |
316 | } | 316 | } |
317 | /* take a card refcount for safe disconnection */ | 317 | /* take a card refcount for safe disconnection */ |
318 | if (timer->card) | 318 | if (timer->card) |
@@ -321,16 +321,16 @@ int snd_timer_open(struct snd_timer_instance **ti, | |||
321 | timeri->slave_id = slave_id; | 321 | timeri->slave_id = slave_id; |
322 | 322 | ||
323 | if (list_empty(&timer->open_list_head) && timer->hw.open) { | 323 | if (list_empty(&timer->open_list_head) && timer->hw.open) { |
324 | int err = timer->hw.open(timer); | 324 | err = timer->hw.open(timer); |
325 | if (err) { | 325 | if (err) { |
326 | kfree(timeri->owner); | 326 | kfree(timeri->owner); |
327 | kfree(timeri); | 327 | kfree(timeri); |
328 | timeri = NULL; | ||
328 | 329 | ||
329 | if (timer->card) | 330 | if (timer->card) |
330 | put_device(&timer->card->card_dev); | 331 | put_device(&timer->card->card_dev); |
331 | module_put(timer->module); | 332 | module_put(timer->module); |
332 | mutex_unlock(®ister_mutex); | 333 | goto unlock; |
333 | return err; | ||
334 | } | 334 | } |
335 | } | 335 | } |
336 | 336 | ||
@@ -341,6 +341,8 @@ int snd_timer_open(struct snd_timer_instance **ti, | |||
341 | snd_timer_close_locked(timeri); | 341 | snd_timer_close_locked(timeri); |
342 | timeri = NULL; | 342 | timeri = NULL; |
343 | } | 343 | } |
344 | |||
345 | unlock: | ||
344 | mutex_unlock(®ister_mutex); | 346 | mutex_unlock(®ister_mutex); |
345 | *ti = timeri; | 347 | *ti = timeri; |
346 | return err; | 348 | return err; |
@@ -353,15 +355,20 @@ EXPORT_SYMBOL(snd_timer_open); | |||
353 | */ | 355 | */ |
354 | static int snd_timer_close_locked(struct snd_timer_instance *timeri) | 356 | static int snd_timer_close_locked(struct snd_timer_instance *timeri) |
355 | { | 357 | { |
356 | struct snd_timer *timer = NULL; | 358 | struct snd_timer *timer = timeri->timer; |
357 | struct snd_timer_instance *slave, *tmp; | 359 | struct snd_timer_instance *slave, *tmp; |
358 | 360 | ||
361 | if (timer) { | ||
362 | spin_lock_irq(&timer->lock); | ||
363 | timeri->flags |= SNDRV_TIMER_IFLG_DEAD; | ||
364 | spin_unlock_irq(&timer->lock); | ||
365 | } | ||
366 | |||
359 | list_del(&timeri->open_list); | 367 | list_del(&timeri->open_list); |
360 | 368 | ||
361 | /* force to stop the timer */ | 369 | /* force to stop the timer */ |
362 | snd_timer_stop(timeri); | 370 | snd_timer_stop(timeri); |
363 | 371 | ||
364 | timer = timeri->timer; | ||
365 | if (timer) { | 372 | if (timer) { |
366 | timer->num_instances--; | 373 | timer->num_instances--; |
367 | /* wait, until the active callback is finished */ | 374 | /* wait, until the active callback is finished */ |
@@ -497,6 +504,10 @@ static int snd_timer_start1(struct snd_timer_instance *timeri, | |||
497 | return -EINVAL; | 504 | return -EINVAL; |
498 | 505 | ||
499 | spin_lock_irqsave(&timer->lock, flags); | 506 | spin_lock_irqsave(&timer->lock, flags); |
507 | if (timeri->flags & SNDRV_TIMER_IFLG_DEAD) { | ||
508 | result = -EINVAL; | ||
509 | goto unlock; | ||
510 | } | ||
500 | if (timer->card && timer->card->shutdown) { | 511 | if (timer->card && timer->card->shutdown) { |
501 | result = -ENODEV; | 512 | result = -ENODEV; |
502 | goto unlock; | 513 | goto unlock; |
@@ -541,11 +552,16 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri, | |||
541 | bool start) | 552 | bool start) |
542 | { | 553 | { |
543 | unsigned long flags; | 554 | unsigned long flags; |
555 | int err; | ||
544 | 556 | ||
545 | spin_lock_irqsave(&slave_active_lock, flags); | 557 | spin_lock_irqsave(&slave_active_lock, flags); |
558 | if (timeri->flags & SNDRV_TIMER_IFLG_DEAD) { | ||
559 | err = -EINVAL; | ||
560 | goto unlock; | ||
561 | } | ||
546 | if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) { | 562 | if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) { |
547 | spin_unlock_irqrestore(&slave_active_lock, flags); | 563 | err = -EBUSY; |
548 | return -EBUSY; | 564 | goto unlock; |
549 | } | 565 | } |
550 | timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; | 566 | timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; |
551 | if (timeri->master && timeri->timer) { | 567 | if (timeri->master && timeri->timer) { |
@@ -556,8 +572,10 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri, | |||
556 | SNDRV_TIMER_EVENT_CONTINUE); | 572 | SNDRV_TIMER_EVENT_CONTINUE); |
557 | spin_unlock(&timeri->timer->lock); | 573 | spin_unlock(&timeri->timer->lock); |
558 | } | 574 | } |
575 | err = 1; /* delayed start */ | ||
576 | unlock: | ||
559 | spin_unlock_irqrestore(&slave_active_lock, flags); | 577 | spin_unlock_irqrestore(&slave_active_lock, flags); |
560 | return 1; /* delayed start */ | 578 | return err; |
561 | } | 579 | } |
562 | 580 | ||
563 | /* stop/pause a master timer */ | 581 | /* stop/pause a master timer */ |
@@ -720,6 +738,46 @@ static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_l | |||
720 | timer->sticks = ticks; | 738 | timer->sticks = ticks; |
721 | } | 739 | } |
722 | 740 | ||
741 | /* call callbacks in timer ack list */ | ||
742 | static void snd_timer_process_callbacks(struct snd_timer *timer, | ||
743 | struct list_head *head) | ||
744 | { | ||
745 | struct snd_timer_instance *ti; | ||
746 | unsigned long resolution, ticks; | ||
747 | |||
748 | while (!list_empty(head)) { | ||
749 | ti = list_first_entry(head, struct snd_timer_instance, | ||
750 | ack_list); | ||
751 | |||
752 | /* remove from ack_list and make empty */ | ||
753 | list_del_init(&ti->ack_list); | ||
754 | |||
755 | if (!(ti->flags & SNDRV_TIMER_IFLG_DEAD)) { | ||
756 | ticks = ti->pticks; | ||
757 | ti->pticks = 0; | ||
758 | resolution = ti->resolution; | ||
759 | ti->flags |= SNDRV_TIMER_IFLG_CALLBACK; | ||
760 | spin_unlock(&timer->lock); | ||
761 | if (ti->callback) | ||
762 | ti->callback(ti, resolution, ticks); | ||
763 | spin_lock(&timer->lock); | ||
764 | ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK; | ||
765 | } | ||
766 | } | ||
767 | } | ||
768 | |||
769 | /* clear pending instances from ack list */ | ||
770 | static void snd_timer_clear_callbacks(struct snd_timer *timer, | ||
771 | struct list_head *head) | ||
772 | { | ||
773 | unsigned long flags; | ||
774 | |||
775 | spin_lock_irqsave(&timer->lock, flags); | ||
776 | while (!list_empty(head)) | ||
777 | list_del_init(head->next); | ||
778 | spin_unlock_irqrestore(&timer->lock, flags); | ||
779 | } | ||
780 | |||
723 | /* | 781 | /* |
724 | * timer tasklet | 782 | * timer tasklet |
725 | * | 783 | * |
@@ -727,34 +785,15 @@ static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_l | |||
727 | static void snd_timer_tasklet(unsigned long arg) | 785 | static void snd_timer_tasklet(unsigned long arg) |
728 | { | 786 | { |
729 | struct snd_timer *timer = (struct snd_timer *) arg; | 787 | struct snd_timer *timer = (struct snd_timer *) arg; |
730 | struct snd_timer_instance *ti; | ||
731 | struct list_head *p; | ||
732 | unsigned long resolution, ticks; | ||
733 | unsigned long flags; | 788 | unsigned long flags; |
734 | 789 | ||
735 | if (timer->card && timer->card->shutdown) | 790 | if (timer->card && timer->card->shutdown) { |
791 | snd_timer_clear_callbacks(timer, &timer->sack_list_head); | ||
736 | return; | 792 | return; |
793 | } | ||
737 | 794 | ||
738 | spin_lock_irqsave(&timer->lock, flags); | 795 | spin_lock_irqsave(&timer->lock, flags); |
739 | /* now process all callbacks */ | 796 | snd_timer_process_callbacks(timer, &timer->sack_list_head); |
740 | while (!list_empty(&timer->sack_list_head)) { | ||
741 | p = timer->sack_list_head.next; /* get first item */ | ||
742 | ti = list_entry(p, struct snd_timer_instance, ack_list); | ||
743 | |||
744 | /* remove from ack_list and make empty */ | ||
745 | list_del_init(p); | ||
746 | |||
747 | ticks = ti->pticks; | ||
748 | ti->pticks = 0; | ||
749 | resolution = ti->resolution; | ||
750 | |||
751 | ti->flags |= SNDRV_TIMER_IFLG_CALLBACK; | ||
752 | spin_unlock(&timer->lock); | ||
753 | if (ti->callback) | ||
754 | ti->callback(ti, resolution, ticks); | ||
755 | spin_lock(&timer->lock); | ||
756 | ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK; | ||
757 | } | ||
758 | spin_unlock_irqrestore(&timer->lock, flags); | 797 | spin_unlock_irqrestore(&timer->lock, flags); |
759 | } | 798 | } |
760 | 799 | ||
@@ -767,16 +806,18 @@ static void snd_timer_tasklet(unsigned long arg) | |||
767 | void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) | 806 | void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) |
768 | { | 807 | { |
769 | struct snd_timer_instance *ti, *ts, *tmp; | 808 | struct snd_timer_instance *ti, *ts, *tmp; |
770 | unsigned long resolution, ticks; | 809 | unsigned long resolution; |
771 | struct list_head *p, *ack_list_head; | 810 | struct list_head *ack_list_head; |
772 | unsigned long flags; | 811 | unsigned long flags; |
773 | int use_tasklet = 0; | 812 | int use_tasklet = 0; |
774 | 813 | ||
775 | if (timer == NULL) | 814 | if (timer == NULL) |
776 | return; | 815 | return; |
777 | 816 | ||
778 | if (timer->card && timer->card->shutdown) | 817 | if (timer->card && timer->card->shutdown) { |
818 | snd_timer_clear_callbacks(timer, &timer->ack_list_head); | ||
779 | return; | 819 | return; |
820 | } | ||
780 | 821 | ||
781 | spin_lock_irqsave(&timer->lock, flags); | 822 | spin_lock_irqsave(&timer->lock, flags); |
782 | 823 | ||
@@ -790,6 +831,8 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) | |||
790 | */ | 831 | */ |
791 | list_for_each_entry_safe(ti, tmp, &timer->active_list_head, | 832 | list_for_each_entry_safe(ti, tmp, &timer->active_list_head, |
792 | active_list) { | 833 | active_list) { |
834 | if (ti->flags & SNDRV_TIMER_IFLG_DEAD) | ||
835 | continue; | ||
793 | if (!(ti->flags & SNDRV_TIMER_IFLG_RUNNING)) | 836 | if (!(ti->flags & SNDRV_TIMER_IFLG_RUNNING)) |
794 | continue; | 837 | continue; |
795 | ti->pticks += ticks_left; | 838 | ti->pticks += ticks_left; |
@@ -839,23 +882,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) | |||
839 | } | 882 | } |
840 | 883 | ||
841 | /* now process all fast callbacks */ | 884 | /* now process all fast callbacks */ |
842 | while (!list_empty(&timer->ack_list_head)) { | 885 | snd_timer_process_callbacks(timer, &timer->ack_list_head); |
843 | p = timer->ack_list_head.next; /* get first item */ | ||
844 | ti = list_entry(p, struct snd_timer_instance, ack_list); | ||
845 | |||
846 | /* remove from ack_list and make empty */ | ||
847 | list_del_init(p); | ||
848 | |||
849 | ticks = ti->pticks; | ||
850 | ti->pticks = 0; | ||
851 | |||
852 | ti->flags |= SNDRV_TIMER_IFLG_CALLBACK; | ||
853 | spin_unlock(&timer->lock); | ||
854 | if (ti->callback) | ||
855 | ti->callback(ti, resolution, ticks); | ||
856 | spin_lock(&timer->lock); | ||
857 | ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK; | ||
858 | } | ||
859 | 886 | ||
860 | /* do we have any slow callbacks? */ | 887 | /* do we have any slow callbacks? */ |
861 | use_tasklet = !list_empty(&timer->sack_list_head); | 888 | use_tasklet = !list_empty(&timer->sack_list_head); |
@@ -1882,7 +1909,10 @@ static int snd_timer_user_start(struct file *file) | |||
1882 | snd_timer_stop(tu->timeri); | 1909 | snd_timer_stop(tu->timeri); |
1883 | tu->timeri->lost = 0; | 1910 | tu->timeri->lost = 0; |
1884 | tu->last_resolution = 0; | 1911 | tu->last_resolution = 0; |
1885 | return (err = snd_timer_start(tu->timeri, tu->ticks)) < 0 ? err : 0; | 1912 | err = snd_timer_start(tu->timeri, tu->ticks); |
1913 | if (err < 0) | ||
1914 | return err; | ||
1915 | return 0; | ||
1886 | } | 1916 | } |
1887 | 1917 | ||
1888 | static int snd_timer_user_stop(struct file *file) | 1918 | static int snd_timer_user_stop(struct file *file) |
@@ -1893,7 +1923,10 @@ static int snd_timer_user_stop(struct file *file) | |||
1893 | tu = file->private_data; | 1923 | tu = file->private_data; |
1894 | if (!tu->timeri) | 1924 | if (!tu->timeri) |
1895 | return -EBADFD; | 1925 | return -EBADFD; |
1896 | return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0; | 1926 | err = snd_timer_stop(tu->timeri); |
1927 | if (err < 0) | ||
1928 | return err; | ||
1929 | return 0; | ||
1897 | } | 1930 | } |
1898 | 1931 | ||
1899 | static int snd_timer_user_continue(struct file *file) | 1932 | static int snd_timer_user_continue(struct file *file) |
@@ -1908,7 +1941,10 @@ static int snd_timer_user_continue(struct file *file) | |||
1908 | if (!(tu->timeri->flags & SNDRV_TIMER_IFLG_PAUSED)) | 1941 | if (!(tu->timeri->flags & SNDRV_TIMER_IFLG_PAUSED)) |
1909 | return snd_timer_user_start(file); | 1942 | return snd_timer_user_start(file); |
1910 | tu->timeri->lost = 0; | 1943 | tu->timeri->lost = 0; |
1911 | return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; | 1944 | err = snd_timer_continue(tu->timeri); |
1945 | if (err < 0) | ||
1946 | return err; | ||
1947 | return 0; | ||
1912 | } | 1948 | } |
1913 | 1949 | ||
1914 | static int snd_timer_user_pause(struct file *file) | 1950 | static int snd_timer_user_pause(struct file *file) |
@@ -1919,7 +1955,10 @@ static int snd_timer_user_pause(struct file *file) | |||
1919 | tu = file->private_data; | 1955 | tu = file->private_data; |
1920 | if (!tu->timeri) | 1956 | if (!tu->timeri) |
1921 | return -EBADFD; | 1957 | return -EBADFD; |
1922 | return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0; | 1958 | err = snd_timer_pause(tu->timeri); |
1959 | if (err < 0) | ||
1960 | return err; | ||
1961 | return 0; | ||
1923 | } | 1962 | } |
1924 | 1963 | ||
1925 | enum { | 1964 | enum { |
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 8c3fbe1276be..c14e57b2a135 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c | |||
@@ -337,7 +337,7 @@ static int loopback_prepare(struct snd_pcm_substream *substream) | |||
337 | 337 | ||
338 | loopback_timer_stop_sync(dpcm); | 338 | loopback_timer_stop_sync(dpcm); |
339 | 339 | ||
340 | salign = (snd_pcm_format_width(runtime->format) * | 340 | salign = (snd_pcm_format_physical_width(runtime->format) * |
341 | runtime->channels) / 8; | 341 | runtime->channels) / 8; |
342 | bps = salign * runtime->rate; | 342 | bps = salign * runtime->rate; |
343 | if (bps <= 0 || salign <= 0) | 343 | if (bps <= 0 || salign <= 0) |
@@ -562,6 +562,8 @@ static const struct snd_pcm_hardware loopback_pcm_hardware = | |||
562 | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | | 562 | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | |
563 | SNDRV_PCM_INFO_RESUME), | 563 | SNDRV_PCM_INFO_RESUME), |
564 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | | 564 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | |
565 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | | ||
566 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | | ||
565 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | | 567 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | |
566 | SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE), | 568 | SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE), |
567 | .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000, | 569 | .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000, |
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 3ada55ed5381..43f28b813386 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c | |||
@@ -56,8 +56,9 @@ | |||
56 | #define INTERRUPT_INTERVAL 16 | 56 | #define INTERRUPT_INTERVAL 16 |
57 | #define QUEUE_LENGTH 48 | 57 | #define QUEUE_LENGTH 48 |
58 | 58 | ||
59 | #define IN_PACKET_HEADER_SIZE 4 | 59 | #define IR_HEADER_SIZE 8 // For header and timestamp. |
60 | #define OUT_PACKET_HEADER_SIZE 0 | 60 | #define OUT_PACKET_HEADER_SIZE 0 |
61 | #define HEADER_TSTAMP_MASK 0x0000ffff | ||
61 | 62 | ||
62 | static void pcm_period_tasklet(unsigned long data); | 63 | static void pcm_period_tasklet(unsigned long data); |
63 | 64 | ||
@@ -456,7 +457,7 @@ static inline int queue_out_packet(struct amdtp_stream *s, | |||
456 | 457 | ||
457 | static inline int queue_in_packet(struct amdtp_stream *s) | 458 | static inline int queue_in_packet(struct amdtp_stream *s) |
458 | { | 459 | { |
459 | return queue_packet(s, IN_PACKET_HEADER_SIZE, s->max_payload_length); | 460 | return queue_packet(s, IR_HEADER_SIZE, s->max_payload_length); |
460 | } | 461 | } |
461 | 462 | ||
462 | static int handle_out_packet(struct amdtp_stream *s, | 463 | static int handle_out_packet(struct amdtp_stream *s, |
@@ -701,13 +702,6 @@ static inline u32 increment_cycle_count(u32 cycle, unsigned int addend) | |||
701 | return cycle; | 702 | return cycle; |
702 | } | 703 | } |
703 | 704 | ||
704 | static inline u32 decrement_cycle_count(u32 cycle, unsigned int subtrahend) | ||
705 | { | ||
706 | if (cycle < subtrahend) | ||
707 | cycle += 8 * CYCLES_PER_SECOND; | ||
708 | return cycle - subtrahend; | ||
709 | } | ||
710 | |||
711 | static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, | 705 | static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, |
712 | size_t header_length, void *header, | 706 | size_t header_length, void *header, |
713 | void *private_data) | 707 | void *private_data) |
@@ -745,29 +739,26 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, | |||
745 | struct amdtp_stream *s = private_data; | 739 | struct amdtp_stream *s = private_data; |
746 | unsigned int i, packets; | 740 | unsigned int i, packets; |
747 | unsigned int payload_length, max_payload_length; | 741 | unsigned int payload_length, max_payload_length; |
748 | __be32 *headers = header; | 742 | __be32 *ctx_header = header; |
749 | u32 cycle; | ||
750 | 743 | ||
751 | if (s->packet_index < 0) | 744 | if (s->packet_index < 0) |
752 | return; | 745 | return; |
753 | 746 | ||
754 | /* The number of packets in buffer */ | 747 | /* The number of packets in buffer */ |
755 | packets = header_length / IN_PACKET_HEADER_SIZE; | 748 | packets = header_length / IR_HEADER_SIZE; |
756 | |||
757 | cycle = compute_cycle_count(tstamp); | ||
758 | |||
759 | /* Align to actual cycle count for the last packet. */ | ||
760 | cycle = decrement_cycle_count(cycle, packets); | ||
761 | 749 | ||
762 | /* For buffer-over-run prevention. */ | 750 | /* For buffer-over-run prevention. */ |
763 | max_payload_length = s->max_payload_length; | 751 | max_payload_length = s->max_payload_length; |
764 | 752 | ||
765 | for (i = 0; i < packets; i++) { | 753 | for (i = 0; i < packets; i++) { |
766 | cycle = increment_cycle_count(cycle, 1); | 754 | u32 iso_header = be32_to_cpu(ctx_header[0]); |
755 | unsigned int cycle; | ||
756 | |||
757 | tstamp = be32_to_cpu(ctx_header[1]) & HEADER_TSTAMP_MASK; | ||
758 | cycle = compute_cycle_count(tstamp); | ||
767 | 759 | ||
768 | /* The number of bytes in this packet */ | 760 | /* The number of bytes in this packet */ |
769 | payload_length = | 761 | payload_length = iso_header >> ISO_DATA_LENGTH_SHIFT; |
770 | (be32_to_cpu(headers[i]) >> ISO_DATA_LENGTH_SHIFT); | ||
771 | if (payload_length > max_payload_length) { | 762 | if (payload_length > max_payload_length) { |
772 | dev_err(&s->unit->device, | 763 | dev_err(&s->unit->device, |
773 | "Detect jumbo payload: %04x %04x\n", | 764 | "Detect jumbo payload: %04x %04x\n", |
@@ -777,6 +768,8 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, | |||
777 | 768 | ||
778 | if (s->handle_packet(s, payload_length, cycle, i) < 0) | 769 | if (s->handle_packet(s, payload_length, cycle, i) < 0) |
779 | break; | 770 | break; |
771 | |||
772 | ctx_header += IR_HEADER_SIZE / sizeof(__be32); | ||
780 | } | 773 | } |
781 | 774 | ||
782 | /* Queueing error or detecting invalid payload. */ | 775 | /* Queueing error or detecting invalid payload. */ |
@@ -797,6 +790,7 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, | |||
797 | void *header, void *private_data) | 790 | void *header, void *private_data) |
798 | { | 791 | { |
799 | struct amdtp_stream *s = private_data; | 792 | struct amdtp_stream *s = private_data; |
793 | __be32 *ctx_header = header; | ||
800 | u32 cycle; | 794 | u32 cycle; |
801 | unsigned int packets; | 795 | unsigned int packets; |
802 | 796 | ||
@@ -807,11 +801,10 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, | |||
807 | s->callbacked = true; | 801 | s->callbacked = true; |
808 | wake_up(&s->callback_wait); | 802 | wake_up(&s->callback_wait); |
809 | 803 | ||
810 | cycle = compute_cycle_count(tstamp); | ||
811 | |||
812 | if (s->direction == AMDTP_IN_STREAM) { | 804 | if (s->direction == AMDTP_IN_STREAM) { |
813 | packets = header_length / IN_PACKET_HEADER_SIZE; | 805 | tstamp = be32_to_cpu(ctx_header[1]) & HEADER_TSTAMP_MASK; |
814 | cycle = decrement_cycle_count(cycle, packets); | 806 | cycle = compute_cycle_count(tstamp); |
807 | |||
815 | context->callback.sc = in_stream_callback; | 808 | context->callback.sc = in_stream_callback; |
816 | if (s->flags & CIP_NO_HEADER) | 809 | if (s->flags & CIP_NO_HEADER) |
817 | s->handle_packet = handle_in_packet_without_header; | 810 | s->handle_packet = handle_in_packet_without_header; |
@@ -819,6 +812,7 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, | |||
819 | s->handle_packet = handle_in_packet; | 812 | s->handle_packet = handle_in_packet; |
820 | } else { | 813 | } else { |
821 | packets = header_length / 4; | 814 | packets = header_length / 4; |
815 | cycle = compute_cycle_count(tstamp); | ||
822 | cycle = increment_cycle_count(cycle, QUEUE_LENGTH - packets); | 816 | cycle = increment_cycle_count(cycle, QUEUE_LENGTH - packets); |
823 | context->callback.sc = out_stream_callback; | 817 | context->callback.sc = out_stream_callback; |
824 | if (s->flags & CIP_NO_HEADER) | 818 | if (s->flags & CIP_NO_HEADER) |
@@ -880,7 +874,7 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) | |||
880 | if (s->direction == AMDTP_IN_STREAM) { | 874 | if (s->direction == AMDTP_IN_STREAM) { |
881 | dir = DMA_FROM_DEVICE; | 875 | dir = DMA_FROM_DEVICE; |
882 | type = FW_ISO_CONTEXT_RECEIVE; | 876 | type = FW_ISO_CONTEXT_RECEIVE; |
883 | header_size = IN_PACKET_HEADER_SIZE; | 877 | header_size = IR_HEADER_SIZE; |
884 | } else { | 878 | } else { |
885 | dir = DMA_TO_DEVICE; | 879 | dir = DMA_TO_DEVICE; |
886 | type = FW_ISO_CONTEXT_TRANSMIT; | 880 | type = FW_ISO_CONTEXT_TRANSMIT; |
diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c index 6c9b743ea74b..cb0c967dea63 100644 --- a/sound/firewire/motu/amdtp-motu.c +++ b/sound/firewire/motu/amdtp-motu.c | |||
@@ -412,6 +412,12 @@ int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, | |||
412 | CIP_HEADER_WITHOUT_EOH; | 412 | CIP_HEADER_WITHOUT_EOH; |
413 | fmt = CIP_FMT_MOTU_TX_V3; | 413 | fmt = CIP_FMT_MOTU_TX_V3; |
414 | } | 414 | } |
415 | |||
416 | if (protocol == &snd_motu_protocol_v2) { | ||
417 | // 8pre has some quirks. | ||
418 | flags |= CIP_WRONG_DBS | | ||
419 | CIP_SKIP_DBC_ZERO_CHECK; | ||
420 | } | ||
415 | } else { | 421 | } else { |
416 | process_data_blocks = process_rx_data_blocks; | 422 | process_data_blocks = process_rx_data_blocks; |
417 | flags |= CIP_DBC_IS_END_EVENT; | 423 | flags |= CIP_DBC_IS_END_EVENT; |
diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index 453fc29fade7..848fffe7387e 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #define V2_CLOCK_SRC_SHIFT 0 | 15 | #define V2_CLOCK_SRC_SHIFT 0 |
16 | #define V2_CLOCK_TRAVELER_FETCH_DISABLE 0x04000000 | 16 | #define V2_CLOCK_TRAVELER_FETCH_DISABLE 0x04000000 |
17 | #define V2_CLOCK_TRAVELER_FETCH_ENABLE 0x03000000 | 17 | #define V2_CLOCK_TRAVELER_FETCH_ENABLE 0x03000000 |
18 | #define V2_CLOCK_8PRE_FETCH_DISABLE 0x02000000 | ||
19 | #define V2_CLOCK_8PRE_FETCH_ENABLE 0x00000000 | ||
18 | 20 | ||
19 | #define V2_IN_OUT_CONF_OFFSET 0x0c04 | 21 | #define V2_IN_OUT_CONF_OFFSET 0x0c04 |
20 | #define V2_OPT_OUT_IFACE_MASK 0x00000c00 | 22 | #define V2_OPT_OUT_IFACE_MASK 0x00000c00 |
@@ -132,20 +134,31 @@ static int v2_switch_fetching_mode(struct snd_motu *motu, bool enable) | |||
132 | u32 data; | 134 | u32 data; |
133 | int err = 0; | 135 | int err = 0; |
134 | 136 | ||
135 | if (motu->spec == &snd_motu_spec_traveler) { | 137 | if (motu->spec == &snd_motu_spec_traveler || |
138 | motu->spec == &snd_motu_spec_8pre) { | ||
136 | err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, | 139 | err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, |
137 | ®, sizeof(reg)); | 140 | ®, sizeof(reg)); |
138 | if (err < 0) | 141 | if (err < 0) |
139 | return err; | 142 | return err; |
140 | data = be32_to_cpu(reg); | 143 | data = be32_to_cpu(reg); |
141 | 144 | ||
142 | data &= ~(V2_CLOCK_TRAVELER_FETCH_DISABLE | | 145 | if (motu->spec == &snd_motu_spec_traveler) { |
143 | V2_CLOCK_TRAVELER_FETCH_ENABLE); | 146 | data &= ~(V2_CLOCK_TRAVELER_FETCH_DISABLE | |
144 | 147 | V2_CLOCK_TRAVELER_FETCH_ENABLE); | |
145 | if (enable) | 148 | |
146 | data |= V2_CLOCK_TRAVELER_FETCH_ENABLE; | 149 | if (enable) |
147 | else | 150 | data |= V2_CLOCK_TRAVELER_FETCH_ENABLE; |
148 | data |= V2_CLOCK_TRAVELER_FETCH_DISABLE; | 151 | else |
152 | data |= V2_CLOCK_TRAVELER_FETCH_DISABLE; | ||
153 | } else if (motu->spec == &snd_motu_spec_8pre) { | ||
154 | data &= ~(V2_CLOCK_8PRE_FETCH_DISABLE | | ||
155 | V2_CLOCK_8PRE_FETCH_ENABLE); | ||
156 | |||
157 | if (enable) | ||
158 | data |= V2_CLOCK_8PRE_FETCH_DISABLE; | ||
159 | else | ||
160 | data |= V2_CLOCK_8PRE_FETCH_ENABLE; | ||
161 | } | ||
149 | 162 | ||
150 | reg = cpu_to_be32(data); | 163 | reg = cpu_to_be32(data); |
151 | err = snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET, | 164 | err = snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET, |
@@ -220,10 +233,16 @@ static void calculate_differed_part(struct snd_motu_packet_format *formats, | |||
220 | * interfaces. | 233 | * interfaces. |
221 | */ | 234 | */ |
222 | data = (data & mask) >> shift; | 235 | data = (data & mask) >> shift; |
223 | if ((flags & SND_MOTU_SPEC_HAS_OPT_IFACE_A) && | 236 | if (data == V2_OPT_IFACE_MODE_ADAT) { |
224 | data == V2_OPT_IFACE_MODE_ADAT) { | 237 | if (flags & SND_MOTU_SPEC_HAS_OPT_IFACE_A) { |
225 | pcm_chunks[0] += 8; | 238 | pcm_chunks[0] += 8; |
226 | pcm_chunks[1] += 4; | 239 | pcm_chunks[1] += 4; |
240 | } | ||
241 | // 8pre has two sets of optical interface and doesn't reduce | ||
242 | // chunks for ADAT signals. | ||
243 | if (flags & SND_MOTU_SPEC_HAS_OPT_IFACE_B) { | ||
244 | pcm_chunks[1] += 4; | ||
245 | } | ||
227 | } | 246 | } |
228 | 247 | ||
229 | /* At mode x4, no data chunks are supported in this part. */ | 248 | /* At mode x4, no data chunks are supported in this part. */ |
diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c index 513291ba0ab0..201539d4488c 100644 --- a/sound/firewire/motu/motu.c +++ b/sound/firewire/motu/motu.c | |||
@@ -203,6 +203,20 @@ const struct snd_motu_spec snd_motu_spec_traveler = { | |||
203 | .analog_out_ports = 8, | 203 | .analog_out_ports = 8, |
204 | }; | 204 | }; |
205 | 205 | ||
206 | const struct snd_motu_spec snd_motu_spec_8pre = { | ||
207 | .name = "8pre", | ||
208 | .protocol = &snd_motu_protocol_v2, | ||
209 | // In tx, use coax chunks for mix-return 1/2. In rx, use coax chunks for | ||
210 | // dummy 1/2. | ||
211 | .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | | ||
212 | SND_MOTU_SPEC_HAS_OPT_IFACE_A | | ||
213 | SND_MOTU_SPEC_HAS_OPT_IFACE_B | | ||
214 | SND_MOTU_SPEC_RX_MIDI_2ND_Q | | ||
215 | SND_MOTU_SPEC_TX_MIDI_2ND_Q, | ||
216 | .analog_in_ports = 8, | ||
217 | .analog_out_ports = 2, | ||
218 | }; | ||
219 | |||
206 | static const struct snd_motu_spec motu_828mk3 = { | 220 | static const struct snd_motu_spec motu_828mk3 = { |
207 | .name = "828mk3", | 221 | .name = "828mk3", |
208 | .protocol = &snd_motu_protocol_v3, | 222 | .protocol = &snd_motu_protocol_v3, |
@@ -248,6 +262,7 @@ static const struct snd_motu_spec motu_audio_express = { | |||
248 | static const struct ieee1394_device_id motu_id_table[] = { | 262 | static const struct ieee1394_device_id motu_id_table[] = { |
249 | SND_MOTU_DEV_ENTRY(0x000003, &motu_828mk2), | 263 | SND_MOTU_DEV_ENTRY(0x000003, &motu_828mk2), |
250 | SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler), | 264 | SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler), |
265 | SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre), | ||
251 | SND_MOTU_DEV_ENTRY(0x000015, &motu_828mk3), /* FireWire only. */ | 266 | SND_MOTU_DEV_ENTRY(0x000015, &motu_828mk3), /* FireWire only. */ |
252 | SND_MOTU_DEV_ENTRY(0x000035, &motu_828mk3), /* Hybrid. */ | 267 | SND_MOTU_DEV_ENTRY(0x000035, &motu_828mk3), /* Hybrid. */ |
253 | SND_MOTU_DEV_ENTRY(0x000033, &motu_audio_express), | 268 | SND_MOTU_DEV_ENTRY(0x000033, &motu_audio_express), |
diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index fd5327d30ab1..1cd112be7dad 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h | |||
@@ -130,6 +130,7 @@ extern const struct snd_motu_protocol snd_motu_protocol_v2; | |||
130 | extern const struct snd_motu_protocol snd_motu_protocol_v3; | 130 | extern const struct snd_motu_protocol snd_motu_protocol_v3; |
131 | 131 | ||
132 | extern const struct snd_motu_spec snd_motu_spec_traveler; | 132 | extern const struct snd_motu_spec snd_motu_spec_traveler; |
133 | extern const struct snd_motu_spec snd_motu_spec_8pre; | ||
133 | 134 | ||
134 | int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, | 135 | int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, |
135 | enum amdtp_stream_direction dir, | 136 | enum amdtp_stream_direction dir, |
diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 9c37d9af3023..c203af71a099 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c | |||
@@ -104,10 +104,7 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, | |||
104 | return ret; | 104 | return ret; |
105 | 105 | ||
106 | bus->ext_ops = ext_ops; | 106 | bus->ext_ops = ext_ops; |
107 | INIT_LIST_HEAD(&bus->hlink_list); | ||
108 | bus->idx = idx++; | 107 | bus->idx = idx++; |
109 | |||
110 | mutex_init(&bus->lock); | ||
111 | bus->cmd_dma_state = true; | 108 | bus->cmd_dma_state = true; |
112 | 109 | ||
113 | return 0; | 110 | return 0; |
diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index 012305177f68..10e5d261fde1 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c | |||
@@ -38,6 +38,8 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, | |||
38 | INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events); | 38 | INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events); |
39 | spin_lock_init(&bus->reg_lock); | 39 | spin_lock_init(&bus->reg_lock); |
40 | mutex_init(&bus->cmd_mutex); | 40 | mutex_init(&bus->cmd_mutex); |
41 | mutex_init(&bus->lock); | ||
42 | INIT_LIST_HEAD(&bus->hlink_list); | ||
41 | bus->irq = -1; | 43 | bus->irq = -1; |
42 | return 0; | 44 | return 0; |
43 | } | 45 | } |
diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c index 5c95933e739a..1ea51e3b942a 100644 --- a/sound/hda/hdac_component.c +++ b/sound/hda/hdac_component.c | |||
@@ -69,13 +69,15 @@ void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable) | |||
69 | 69 | ||
70 | dev_dbg(bus->dev, "display power %s\n", | 70 | dev_dbg(bus->dev, "display power %s\n", |
71 | enable ? "enable" : "disable"); | 71 | enable ? "enable" : "disable"); |
72 | |||
73 | mutex_lock(&bus->lock); | ||
72 | if (enable) | 74 | if (enable) |
73 | set_bit(idx, &bus->display_power_status); | 75 | set_bit(idx, &bus->display_power_status); |
74 | else | 76 | else |
75 | clear_bit(idx, &bus->display_power_status); | 77 | clear_bit(idx, &bus->display_power_status); |
76 | 78 | ||
77 | if (!acomp || !acomp->ops) | 79 | if (!acomp || !acomp->ops) |
78 | return; | 80 | goto unlock; |
79 | 81 | ||
80 | if (bus->display_power_status) { | 82 | if (bus->display_power_status) { |
81 | if (!bus->display_power_active) { | 83 | if (!bus->display_power_active) { |
@@ -92,6 +94,8 @@ void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable) | |||
92 | bus->display_power_active = false; | 94 | bus->display_power_active = false; |
93 | } | 95 | } |
94 | } | 96 | } |
97 | unlock: | ||
98 | mutex_unlock(&bus->lock); | ||
95 | } | 99 | } |
96 | EXPORT_SYMBOL_GPL(snd_hdac_display_power); | 100 | EXPORT_SYMBOL_GPL(snd_hdac_display_power); |
97 | 101 | ||
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c index 4ac76f46dd76..d708ae1525e4 100644 --- a/sound/isa/gus/gus_mem.c +++ b/sound/isa/gus/gus_mem.c | |||
@@ -306,7 +306,7 @@ static void snd_gf1_mem_info_read(struct snd_info_entry *entry, | |||
306 | used = 0; | 306 | used = 0; |
307 | for (block = alloc->first, i = 0; block; block = block->next, i++) { | 307 | for (block = alloc->first, i = 0; block; block = block->next, i++) { |
308 | used += block->size; | 308 | used += block->size; |
309 | snd_iprintf(buffer, "Block %i at 0x%lx onboard 0x%x size %i (0x%x):\n", i, (long) block, block->ptr, block->size, block->size); | 309 | snd_iprintf(buffer, "Block %i onboard 0x%x size %i (0x%x):\n", i, block->ptr, block->size, block->size); |
310 | if (block->share || | 310 | if (block->share || |
311 | block->share_id[0] || block->share_id[1] || | 311 | block->share_id[0] || block->share_id[1] || |
312 | block->share_id[2] || block->share_id[3]) | 312 | block->share_id[2] || block->share_id[3]) |
diff --git a/sound/last.c b/sound/last.c index 43f222825038..4f5a624ab438 100644 --- a/sound/last.c +++ b/sound/last.c | |||
@@ -24,14 +24,18 @@ | |||
24 | 24 | ||
25 | static int __init alsa_sound_last_init(void) | 25 | static int __init alsa_sound_last_init(void) |
26 | { | 26 | { |
27 | struct snd_card *card; | ||
27 | int idx, ok = 0; | 28 | int idx, ok = 0; |
28 | 29 | ||
29 | printk(KERN_INFO "ALSA device list:\n"); | 30 | printk(KERN_INFO "ALSA device list:\n"); |
30 | for (idx = 0; idx < SNDRV_CARDS; idx++) | 31 | for (idx = 0; idx < SNDRV_CARDS; idx++) { |
31 | if (snd_cards[idx] != NULL) { | 32 | card = snd_card_ref(idx); |
32 | printk(KERN_INFO " #%i: %s\n", idx, snd_cards[idx]->longname); | 33 | if (card) { |
34 | printk(KERN_INFO " #%i: %s\n", idx, card->longname); | ||
35 | snd_card_unref(card); | ||
33 | ok++; | 36 | ok++; |
34 | } | 37 | } |
38 | } | ||
35 | if (ok == 0) | 39 | if (ok == 0) |
36 | printk(KERN_INFO " No soundcards found.\n"); | 40 | printk(KERN_INFO " No soundcards found.\n"); |
37 | return 0; | 41 | return 0; |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 61f85ff91cd9..0419c75bdf5a 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -1882,22 +1882,8 @@ int snd_emu10k1_create(struct snd_card *card, | |||
1882 | c->name, pci->vendor, pci->device, | 1882 | c->name, pci->vendor, pci->device, |
1883 | emu->serial); | 1883 | emu->serial); |
1884 | 1884 | ||
1885 | if (!*card->id && c->id) { | 1885 | if (!*card->id && c->id) |
1886 | int i, n = 0; | ||
1887 | strlcpy(card->id, c->id, sizeof(card->id)); | 1886 | strlcpy(card->id, c->id, sizeof(card->id)); |
1888 | for (;;) { | ||
1889 | for (i = 0; i < snd_ecards_limit; i++) { | ||
1890 | if (snd_cards[i] && !strcmp(snd_cards[i]->id, card->id)) | ||
1891 | break; | ||
1892 | } | ||
1893 | if (i >= snd_ecards_limit) | ||
1894 | break; | ||
1895 | n++; | ||
1896 | if (n >= SNDRV_CARDS) | ||
1897 | break; | ||
1898 | snprintf(card->id, sizeof(card->id), "%s_%d", c->id, n); | ||
1899 | } | ||
1900 | } | ||
1901 | 1887 | ||
1902 | is_audigy = emu->audigy = c->emu10k2_chip; | 1888 | is_audigy = emu->audigy = c->emu10k2_chip; |
1903 | 1889 | ||
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index ec0b8595eb4d..b20eb7fc83eb 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -832,7 +832,13 @@ static int snd_hda_codec_dev_free(struct snd_device *device) | |||
832 | struct hda_codec *codec = device->device_data; | 832 | struct hda_codec *codec = device->device_data; |
833 | 833 | ||
834 | codec->in_freeing = 1; | 834 | codec->in_freeing = 1; |
835 | snd_hdac_device_unregister(&codec->core); | 835 | /* |
836 | * snd_hda_codec_device_new() is used by legacy HDA and ASoC driver. | ||
837 | * We can't unregister ASoC device since it will be unregistered in | ||
838 | * snd_hdac_ext_bus_device_remove(). | ||
839 | */ | ||
840 | if (codec->core.type == HDA_DEV_LEGACY) | ||
841 | snd_hdac_device_unregister(&codec->core); | ||
836 | codec_display_power(codec, false); | 842 | codec_display_power(codec, false); |
837 | put_device(hda_codec_dev(codec)); | 843 | put_device(hda_codec_dev(codec)); |
838 | return 0; | 844 | return 0; |
@@ -969,6 +975,7 @@ int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card, | |||
969 | 975 | ||
970 | /* power-up all before initialization */ | 976 | /* power-up all before initialization */ |
971 | hda_set_power_state(codec, AC_PWRST_D0); | 977 | hda_set_power_state(codec, AC_PWRST_D0); |
978 | codec->core.dev.power.power_state = PMSG_ON; | ||
972 | 979 | ||
973 | snd_hda_codec_proc_new(codec); | 980 | snd_hda_codec_proc_new(codec); |
974 | 981 | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index ece256a3b48f..0741eae23f10 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -1788,9 +1788,6 @@ static int azx_first_init(struct azx *chip) | |||
1788 | chip->msi = 0; | 1788 | chip->msi = 0; |
1789 | } | 1789 | } |
1790 | 1790 | ||
1791 | if (azx_acquire_irq(chip, 0) < 0) | ||
1792 | return -EBUSY; | ||
1793 | |||
1794 | pci_set_master(pci); | 1791 | pci_set_master(pci); |
1795 | synchronize_irq(bus->irq); | 1792 | synchronize_irq(bus->irq); |
1796 | 1793 | ||
@@ -1904,6 +1901,9 @@ static int azx_first_init(struct azx *chip) | |||
1904 | return -ENODEV; | 1901 | return -ENODEV; |
1905 | } | 1902 | } |
1906 | 1903 | ||
1904 | if (azx_acquire_irq(chip, 0) < 0) | ||
1905 | return -EBUSY; | ||
1906 | |||
1907 | strcpy(card->driver, "HDA-Intel"); | 1907 | strcpy(card->driver, "HDA-Intel"); |
1908 | strlcpy(card->shortname, driver_short_names[chip->driver_type], | 1908 | strlcpy(card->shortname, driver_short_names[chip->driver_type], |
1909 | sizeof(card->shortname)); | 1909 | sizeof(card->shortname)); |
@@ -2142,6 +2142,8 @@ static struct snd_pci_quirk power_save_blacklist[] = { | |||
2142 | SND_PCI_QUIRK(0x8086, 0x2040, "Intel DZ77BH-55K", 0), | 2142 | SND_PCI_QUIRK(0x8086, 0x2040, "Intel DZ77BH-55K", 0), |
2143 | /* https://bugzilla.kernel.org/show_bug.cgi?id=199607 */ | 2143 | /* https://bugzilla.kernel.org/show_bug.cgi?id=199607 */ |
2144 | SND_PCI_QUIRK(0x8086, 0x2057, "Intel NUC5i7RYB", 0), | 2144 | SND_PCI_QUIRK(0x8086, 0x2057, "Intel NUC5i7RYB", 0), |
2145 | /* https://bugs.launchpad.net/bugs/1821663 */ | ||
2146 | SND_PCI_QUIRK(0x8086, 0x2064, "Intel SDP 8086:2064", 0), | ||
2145 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1520902 */ | 2147 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1520902 */ |
2146 | SND_PCI_QUIRK(0x8086, 0x2068, "Intel NUC7i3BNB", 0), | 2148 | SND_PCI_QUIRK(0x8086, 0x2068, "Intel NUC7i3BNB", 0), |
2147 | /* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */ | 2149 | /* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */ |
@@ -2150,6 +2152,8 @@ static struct snd_pci_quirk power_save_blacklist[] = { | |||
2150 | SND_PCI_QUIRK(0x17aa, 0x367b, "Lenovo IdeaCentre B550", 0), | 2152 | SND_PCI_QUIRK(0x17aa, 0x367b, "Lenovo IdeaCentre B550", 0), |
2151 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1572975 */ | 2153 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1572975 */ |
2152 | SND_PCI_QUIRK(0x17aa, 0x36a7, "Lenovo C50 All in one", 0), | 2154 | SND_PCI_QUIRK(0x17aa, 0x36a7, "Lenovo C50 All in one", 0), |
2155 | /* https://bugs.launchpad.net/bugs/1821663 */ | ||
2156 | SND_PCI_QUIRK(0x1631, 0xe017, "Packard Bell NEC IMEDIA 5204", 0), | ||
2153 | {} | 2157 | {} |
2154 | }; | 2158 | }; |
2155 | #endif /* CONFIG_PM */ | 2159 | #endif /* CONFIG_PM */ |
@@ -2374,6 +2378,12 @@ static const struct pci_device_id azx_ids[] = { | |||
2374 | /* Cannonlake */ | 2378 | /* Cannonlake */ |
2375 | { PCI_DEVICE(0x8086, 0x9dc8), | 2379 | { PCI_DEVICE(0x8086, 0x9dc8), |
2376 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | 2380 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, |
2381 | /* CometLake-LP */ | ||
2382 | { PCI_DEVICE(0x8086, 0x02C8), | ||
2383 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | ||
2384 | /* CometLake-H */ | ||
2385 | { PCI_DEVICE(0x8086, 0x06C8), | ||
2386 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | ||
2377 | /* Icelake */ | 2387 | /* Icelake */ |
2378 | { PCI_DEVICE(0x8086, 0x34c8), | 2388 | { PCI_DEVICE(0x8086, 0x34c8), |
2379 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | 2389 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 8b3ac690efa3..0c61c05503f5 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -1551,9 +1551,11 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, | |||
1551 | ret = !repoll || !eld->monitor_present || eld->eld_valid; | 1551 | ret = !repoll || !eld->monitor_present || eld->eld_valid; |
1552 | 1552 | ||
1553 | jack = snd_hda_jack_tbl_get(codec, pin_nid); | 1553 | jack = snd_hda_jack_tbl_get(codec, pin_nid); |
1554 | if (jack) | 1554 | if (jack) { |
1555 | jack->block_report = !ret; | 1555 | jack->block_report = !ret; |
1556 | 1556 | jack->pin_sense = (eld->monitor_present && eld->eld_valid) ? | |
1557 | AC_PINSENSE_PRESENCE : 0; | ||
1558 | } | ||
1557 | mutex_unlock(&per_pin->lock); | 1559 | mutex_unlock(&per_pin->lock); |
1558 | return ret; | 1560 | return ret; |
1559 | } | 1561 | } |
@@ -1663,6 +1665,11 @@ static void hdmi_repoll_eld(struct work_struct *work) | |||
1663 | container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work); | 1665 | container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work); |
1664 | struct hda_codec *codec = per_pin->codec; | 1666 | struct hda_codec *codec = per_pin->codec; |
1665 | struct hdmi_spec *spec = codec->spec; | 1667 | struct hdmi_spec *spec = codec->spec; |
1668 | struct hda_jack_tbl *jack; | ||
1669 | |||
1670 | jack = snd_hda_jack_tbl_get(codec, per_pin->pin_nid); | ||
1671 | if (jack) | ||
1672 | jack->jack_dirty = 1; | ||
1666 | 1673 | ||
1667 | if (per_pin->repoll_count++ > 6) | 1674 | if (per_pin->repoll_count++ > 6) |
1668 | per_pin->repoll_count = 0; | 1675 | per_pin->repoll_count = 0; |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a3fb3d4c5730..c53ca589c930 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -119,6 +119,7 @@ struct alc_spec { | |||
119 | unsigned int no_depop_delay:1; | 119 | unsigned int no_depop_delay:1; |
120 | unsigned int done_hp_init:1; | 120 | unsigned int done_hp_init:1; |
121 | unsigned int no_shutup_pins:1; | 121 | unsigned int no_shutup_pins:1; |
122 | unsigned int ultra_low_power:1; | ||
122 | 123 | ||
123 | /* for PLL fix */ | 124 | /* for PLL fix */ |
124 | hda_nid_t pll_nid; | 125 | hda_nid_t pll_nid; |
@@ -803,11 +804,10 @@ static int alc_init(struct hda_codec *codec) | |||
803 | if (spec->init_hook) | 804 | if (spec->init_hook) |
804 | spec->init_hook(codec); | 805 | spec->init_hook(codec); |
805 | 806 | ||
807 | snd_hda_gen_init(codec); | ||
806 | alc_fix_pll(codec); | 808 | alc_fix_pll(codec); |
807 | alc_auto_init_amp(codec, spec->init_amp); | 809 | alc_auto_init_amp(codec, spec->init_amp); |
808 | 810 | ||
809 | snd_hda_gen_init(codec); | ||
810 | |||
811 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT); | 811 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT); |
812 | 812 | ||
813 | return 0; | 813 | return 0; |
@@ -1864,8 +1864,8 @@ enum { | |||
1864 | ALC887_FIXUP_BASS_CHMAP, | 1864 | ALC887_FIXUP_BASS_CHMAP, |
1865 | ALC1220_FIXUP_GB_DUAL_CODECS, | 1865 | ALC1220_FIXUP_GB_DUAL_CODECS, |
1866 | ALC1220_FIXUP_CLEVO_P950, | 1866 | ALC1220_FIXUP_CLEVO_P950, |
1867 | ALC1220_FIXUP_SYSTEM76_ORYP5, | 1867 | ALC1220_FIXUP_CLEVO_PB51ED, |
1868 | ALC1220_FIXUP_SYSTEM76_ORYP5_PINS, | 1868 | ALC1220_FIXUP_CLEVO_PB51ED_PINS, |
1869 | }; | 1869 | }; |
1870 | 1870 | ||
1871 | static void alc889_fixup_coef(struct hda_codec *codec, | 1871 | static void alc889_fixup_coef(struct hda_codec *codec, |
@@ -2070,7 +2070,7 @@ static void alc1220_fixup_clevo_p950(struct hda_codec *codec, | |||
2070 | static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec, | 2070 | static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec, |
2071 | const struct hda_fixup *fix, int action); | 2071 | const struct hda_fixup *fix, int action); |
2072 | 2072 | ||
2073 | static void alc1220_fixup_system76_oryp5(struct hda_codec *codec, | 2073 | static void alc1220_fixup_clevo_pb51ed(struct hda_codec *codec, |
2074 | const struct hda_fixup *fix, | 2074 | const struct hda_fixup *fix, |
2075 | int action) | 2075 | int action) |
2076 | { | 2076 | { |
@@ -2322,18 +2322,18 @@ static const struct hda_fixup alc882_fixups[] = { | |||
2322 | .type = HDA_FIXUP_FUNC, | 2322 | .type = HDA_FIXUP_FUNC, |
2323 | .v.func = alc1220_fixup_clevo_p950, | 2323 | .v.func = alc1220_fixup_clevo_p950, |
2324 | }, | 2324 | }, |
2325 | [ALC1220_FIXUP_SYSTEM76_ORYP5] = { | 2325 | [ALC1220_FIXUP_CLEVO_PB51ED] = { |
2326 | .type = HDA_FIXUP_FUNC, | 2326 | .type = HDA_FIXUP_FUNC, |
2327 | .v.func = alc1220_fixup_system76_oryp5, | 2327 | .v.func = alc1220_fixup_clevo_pb51ed, |
2328 | }, | 2328 | }, |
2329 | [ALC1220_FIXUP_SYSTEM76_ORYP5_PINS] = { | 2329 | [ALC1220_FIXUP_CLEVO_PB51ED_PINS] = { |
2330 | .type = HDA_FIXUP_PINS, | 2330 | .type = HDA_FIXUP_PINS, |
2331 | .v.pins = (const struct hda_pintbl[]) { | 2331 | .v.pins = (const struct hda_pintbl[]) { |
2332 | { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */ | 2332 | { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */ |
2333 | {} | 2333 | {} |
2334 | }, | 2334 | }, |
2335 | .chained = true, | 2335 | .chained = true, |
2336 | .chain_id = ALC1220_FIXUP_SYSTEM76_ORYP5, | 2336 | .chain_id = ALC1220_FIXUP_CLEVO_PB51ED, |
2337 | }, | 2337 | }, |
2338 | }; | 2338 | }; |
2339 | 2339 | ||
@@ -2411,8 +2411,9 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { | |||
2411 | SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950), | 2411 | SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950), |
2412 | SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950), | 2412 | SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950), |
2413 | SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950), | 2413 | SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950), |
2414 | SND_PCI_QUIRK(0x1558, 0x96e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_SYSTEM76_ORYP5_PINS), | 2414 | SND_PCI_QUIRK(0x1558, 0x96e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_CLEVO_PB51ED_PINS), |
2415 | SND_PCI_QUIRK(0x1558, 0x97e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_SYSTEM76_ORYP5_PINS), | 2415 | SND_PCI_QUIRK(0x1558, 0x97e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_CLEVO_PB51ED_PINS), |
2416 | SND_PCI_QUIRK(0x1558, 0x65d1, "Tuxedo Book XC1509", ALC1220_FIXUP_CLEVO_PB51ED_PINS), | ||
2416 | SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD), | 2417 | SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD), |
2417 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD), | 2418 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD), |
2418 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530), | 2419 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530), |
@@ -3196,7 +3197,7 @@ static void alc256_init(struct hda_codec *codec) | |||
3196 | bool hp_pin_sense; | 3197 | bool hp_pin_sense; |
3197 | 3198 | ||
3198 | if (!hp_pin) | 3199 | if (!hp_pin) |
3199 | return; | 3200 | hp_pin = 0x21; |
3200 | 3201 | ||
3201 | msleep(30); | 3202 | msleep(30); |
3202 | 3203 | ||
@@ -3206,17 +3207,25 @@ static void alc256_init(struct hda_codec *codec) | |||
3206 | msleep(2); | 3207 | msleep(2); |
3207 | 3208 | ||
3208 | alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ | 3209 | alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ |
3210 | if (spec->ultra_low_power) { | ||
3211 | alc_update_coef_idx(codec, 0x03, 1<<1, 1<<1); | ||
3212 | alc_update_coef_idx(codec, 0x08, 3<<2, 3<<2); | ||
3213 | alc_update_coef_idx(codec, 0x08, 7<<4, 0); | ||
3214 | alc_update_coef_idx(codec, 0x3b, 1<<15, 0); | ||
3215 | alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6); | ||
3216 | msleep(30); | ||
3217 | } | ||
3209 | 3218 | ||
3210 | snd_hda_codec_write(codec, hp_pin, 0, | 3219 | snd_hda_codec_write(codec, hp_pin, 0, |
3211 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | 3220 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); |
3212 | 3221 | ||
3213 | if (hp_pin_sense) | 3222 | if (hp_pin_sense || spec->ultra_low_power) |
3214 | msleep(85); | 3223 | msleep(85); |
3215 | 3224 | ||
3216 | snd_hda_codec_write(codec, hp_pin, 0, | 3225 | snd_hda_codec_write(codec, hp_pin, 0, |
3217 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | 3226 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); |
3218 | 3227 | ||
3219 | if (hp_pin_sense) | 3228 | if (hp_pin_sense || spec->ultra_low_power) |
3220 | msleep(100); | 3229 | msleep(100); |
3221 | 3230 | ||
3222 | alc_update_coef_idx(codec, 0x46, 3 << 12, 0); | 3231 | alc_update_coef_idx(codec, 0x46, 3 << 12, 0); |
@@ -3231,10 +3240,8 @@ static void alc256_shutup(struct hda_codec *codec) | |||
3231 | hda_nid_t hp_pin = alc_get_hp_pin(spec); | 3240 | hda_nid_t hp_pin = alc_get_hp_pin(spec); |
3232 | bool hp_pin_sense; | 3241 | bool hp_pin_sense; |
3233 | 3242 | ||
3234 | if (!hp_pin) { | 3243 | if (!hp_pin) |
3235 | alc269_shutup(codec); | 3244 | hp_pin = 0x21; |
3236 | return; | ||
3237 | } | ||
3238 | 3245 | ||
3239 | hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); | 3246 | hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); |
3240 | 3247 | ||
@@ -3244,7 +3251,7 @@ static void alc256_shutup(struct hda_codec *codec) | |||
3244 | snd_hda_codec_write(codec, hp_pin, 0, | 3251 | snd_hda_codec_write(codec, hp_pin, 0, |
3245 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | 3252 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); |
3246 | 3253 | ||
3247 | if (hp_pin_sense) | 3254 | if (hp_pin_sense || spec->ultra_low_power) |
3248 | msleep(85); | 3255 | msleep(85); |
3249 | 3256 | ||
3250 | /* 3k pull low control for Headset jack. */ | 3257 | /* 3k pull low control for Headset jack. */ |
@@ -3255,11 +3262,20 @@ static void alc256_shutup(struct hda_codec *codec) | |||
3255 | snd_hda_codec_write(codec, hp_pin, 0, | 3262 | snd_hda_codec_write(codec, hp_pin, 0, |
3256 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); | 3263 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); |
3257 | 3264 | ||
3258 | if (hp_pin_sense) | 3265 | if (hp_pin_sense || spec->ultra_low_power) |
3259 | msleep(100); | 3266 | msleep(100); |
3260 | 3267 | ||
3261 | alc_auto_setup_eapd(codec, false); | 3268 | alc_auto_setup_eapd(codec, false); |
3262 | alc_shutup_pins(codec); | 3269 | alc_shutup_pins(codec); |
3270 | if (spec->ultra_low_power) { | ||
3271 | msleep(50); | ||
3272 | alc_update_coef_idx(codec, 0x03, 1<<1, 0); | ||
3273 | alc_update_coef_idx(codec, 0x08, 7<<4, 7<<4); | ||
3274 | alc_update_coef_idx(codec, 0x08, 3<<2, 0); | ||
3275 | alc_update_coef_idx(codec, 0x3b, 1<<15, 1<<15); | ||
3276 | alc_update_coef_idx(codec, 0x0e, 7<<6, 0); | ||
3277 | msleep(30); | ||
3278 | } | ||
3263 | } | 3279 | } |
3264 | 3280 | ||
3265 | static void alc225_init(struct hda_codec *codec) | 3281 | static void alc225_init(struct hda_codec *codec) |
@@ -3269,8 +3285,7 @@ static void alc225_init(struct hda_codec *codec) | |||
3269 | bool hp1_pin_sense, hp2_pin_sense; | 3285 | bool hp1_pin_sense, hp2_pin_sense; |
3270 | 3286 | ||
3271 | if (!hp_pin) | 3287 | if (!hp_pin) |
3272 | return; | 3288 | hp_pin = 0x21; |
3273 | |||
3274 | msleep(30); | 3289 | msleep(30); |
3275 | 3290 | ||
3276 | hp1_pin_sense = snd_hda_jack_detect(codec, hp_pin); | 3291 | hp1_pin_sense = snd_hda_jack_detect(codec, hp_pin); |
@@ -3280,25 +3295,31 @@ static void alc225_init(struct hda_codec *codec) | |||
3280 | msleep(2); | 3295 | msleep(2); |
3281 | 3296 | ||
3282 | alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ | 3297 | alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ |
3298 | if (spec->ultra_low_power) { | ||
3299 | alc_update_coef_idx(codec, 0x08, 0x0f << 2, 3<<2); | ||
3300 | alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6); | ||
3301 | alc_update_coef_idx(codec, 0x33, 1<<11, 0); | ||
3302 | msleep(30); | ||
3303 | } | ||
3283 | 3304 | ||
3284 | if (hp1_pin_sense) | 3305 | if (hp1_pin_sense || spec->ultra_low_power) |
3285 | snd_hda_codec_write(codec, hp_pin, 0, | 3306 | snd_hda_codec_write(codec, hp_pin, 0, |
3286 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | 3307 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); |
3287 | if (hp2_pin_sense) | 3308 | if (hp2_pin_sense) |
3288 | snd_hda_codec_write(codec, 0x16, 0, | 3309 | snd_hda_codec_write(codec, 0x16, 0, |
3289 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | 3310 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); |
3290 | 3311 | ||
3291 | if (hp1_pin_sense || hp2_pin_sense) | 3312 | if (hp1_pin_sense || hp2_pin_sense || spec->ultra_low_power) |
3292 | msleep(85); | 3313 | msleep(85); |
3293 | 3314 | ||
3294 | if (hp1_pin_sense) | 3315 | if (hp1_pin_sense || spec->ultra_low_power) |
3295 | snd_hda_codec_write(codec, hp_pin, 0, | 3316 | snd_hda_codec_write(codec, hp_pin, 0, |
3296 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | 3317 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); |
3297 | if (hp2_pin_sense) | 3318 | if (hp2_pin_sense) |
3298 | snd_hda_codec_write(codec, 0x16, 0, | 3319 | snd_hda_codec_write(codec, 0x16, 0, |
3299 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | 3320 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); |
3300 | 3321 | ||
3301 | if (hp1_pin_sense || hp2_pin_sense) | 3322 | if (hp1_pin_sense || hp2_pin_sense || spec->ultra_low_power) |
3302 | msleep(100); | 3323 | msleep(100); |
3303 | 3324 | ||
3304 | alc_update_coef_idx(codec, 0x4a, 3 << 10, 0); | 3325 | alc_update_coef_idx(codec, 0x4a, 3 << 10, 0); |
@@ -3311,11 +3332,8 @@ static void alc225_shutup(struct hda_codec *codec) | |||
3311 | hda_nid_t hp_pin = alc_get_hp_pin(spec); | 3332 | hda_nid_t hp_pin = alc_get_hp_pin(spec); |
3312 | bool hp1_pin_sense, hp2_pin_sense; | 3333 | bool hp1_pin_sense, hp2_pin_sense; |
3313 | 3334 | ||
3314 | if (!hp_pin) { | 3335 | if (!hp_pin) |
3315 | alc269_shutup(codec); | 3336 | hp_pin = 0x21; |
3316 | return; | ||
3317 | } | ||
3318 | |||
3319 | /* 3k pull low control for Headset jack. */ | 3337 | /* 3k pull low control for Headset jack. */ |
3320 | alc_update_coef_idx(codec, 0x4a, 0, 3 << 10); | 3338 | alc_update_coef_idx(codec, 0x4a, 0, 3 << 10); |
3321 | 3339 | ||
@@ -3325,28 +3343,36 @@ static void alc225_shutup(struct hda_codec *codec) | |||
3325 | if (hp1_pin_sense || hp2_pin_sense) | 3343 | if (hp1_pin_sense || hp2_pin_sense) |
3326 | msleep(2); | 3344 | msleep(2); |
3327 | 3345 | ||
3328 | if (hp1_pin_sense) | 3346 | if (hp1_pin_sense || spec->ultra_low_power) |
3329 | snd_hda_codec_write(codec, hp_pin, 0, | 3347 | snd_hda_codec_write(codec, hp_pin, 0, |
3330 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | 3348 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); |
3331 | if (hp2_pin_sense) | 3349 | if (hp2_pin_sense) |
3332 | snd_hda_codec_write(codec, 0x16, 0, | 3350 | snd_hda_codec_write(codec, 0x16, 0, |
3333 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | 3351 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); |
3334 | 3352 | ||
3335 | if (hp1_pin_sense || hp2_pin_sense) | 3353 | if (hp1_pin_sense || hp2_pin_sense || spec->ultra_low_power) |
3336 | msleep(85); | 3354 | msleep(85); |
3337 | 3355 | ||
3338 | if (hp1_pin_sense) | 3356 | if (hp1_pin_sense || spec->ultra_low_power) |
3339 | snd_hda_codec_write(codec, hp_pin, 0, | 3357 | snd_hda_codec_write(codec, hp_pin, 0, |
3340 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); | 3358 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); |
3341 | if (hp2_pin_sense) | 3359 | if (hp2_pin_sense) |
3342 | snd_hda_codec_write(codec, 0x16, 0, | 3360 | snd_hda_codec_write(codec, 0x16, 0, |
3343 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); | 3361 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); |
3344 | 3362 | ||
3345 | if (hp1_pin_sense || hp2_pin_sense) | 3363 | if (hp1_pin_sense || hp2_pin_sense || spec->ultra_low_power) |
3346 | msleep(100); | 3364 | msleep(100); |
3347 | 3365 | ||
3348 | alc_auto_setup_eapd(codec, false); | 3366 | alc_auto_setup_eapd(codec, false); |
3349 | alc_shutup_pins(codec); | 3367 | alc_shutup_pins(codec); |
3368 | if (spec->ultra_low_power) { | ||
3369 | msleep(50); | ||
3370 | alc_update_coef_idx(codec, 0x08, 0x0f << 2, 0x0c << 2); | ||
3371 | alc_update_coef_idx(codec, 0x0e, 7<<6, 0); | ||
3372 | alc_update_coef_idx(codec, 0x33, 1<<11, 1<<11); | ||
3373 | alc_update_coef_idx(codec, 0x4a, 3<<4, 2<<4); | ||
3374 | msleep(30); | ||
3375 | } | ||
3350 | } | 3376 | } |
3351 | 3377 | ||
3352 | static void alc_default_init(struct hda_codec *codec) | 3378 | static void alc_default_init(struct hda_codec *codec) |
@@ -5449,6 +5475,8 @@ static void alc274_fixup_bind_dacs(struct hda_codec *codec, | |||
5449 | return; | 5475 | return; |
5450 | 5476 | ||
5451 | spec->gen.preferred_dacs = preferred_pairs; | 5477 | spec->gen.preferred_dacs = preferred_pairs; |
5478 | spec->gen.auto_mute_via_amp = 1; | ||
5479 | codec->power_save_node = 0; | ||
5452 | } | 5480 | } |
5453 | 5481 | ||
5454 | /* The DAC of NID 0x3 will introduce click/pop noise on headphones, so invalidate it */ | 5482 | /* The DAC of NID 0x3 will introduce click/pop noise on headphones, so invalidate it */ |
@@ -5491,7 +5519,7 @@ static void alc_headset_btn_callback(struct hda_codec *codec, | |||
5491 | jack->jack->button_state = report; | 5519 | jack->jack->button_state = report; |
5492 | } | 5520 | } |
5493 | 5521 | ||
5494 | static void alc295_fixup_chromebook(struct hda_codec *codec, | 5522 | static void alc_fixup_headset_jack(struct hda_codec *codec, |
5495 | const struct hda_fixup *fix, int action) | 5523 | const struct hda_fixup *fix, int action) |
5496 | { | 5524 | { |
5497 | 5525 | ||
@@ -5501,16 +5529,6 @@ static void alc295_fixup_chromebook(struct hda_codec *codec, | |||
5501 | alc_headset_btn_callback); | 5529 | alc_headset_btn_callback); |
5502 | snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack", false, | 5530 | snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack", false, |
5503 | SND_JACK_HEADSET, alc_headset_btn_keymap); | 5531 | SND_JACK_HEADSET, alc_headset_btn_keymap); |
5504 | switch (codec->core.vendor_id) { | ||
5505 | case 0x10ec0295: | ||
5506 | alc_update_coef_idx(codec, 0x4a, 0x8000, 1 << 15); /* Reset HP JD */ | ||
5507 | alc_update_coef_idx(codec, 0x4a, 0x8000, 0 << 15); | ||
5508 | break; | ||
5509 | case 0x10ec0236: | ||
5510 | alc_update_coef_idx(codec, 0x1b, 0x8000, 1 << 15); /* Reset HP JD */ | ||
5511 | alc_update_coef_idx(codec, 0x1b, 0x8000, 0 << 15); | ||
5512 | break; | ||
5513 | } | ||
5514 | break; | 5532 | break; |
5515 | case HDA_FIXUP_ACT_INIT: | 5533 | case HDA_FIXUP_ACT_INIT: |
5516 | switch (codec->core.vendor_id) { | 5534 | switch (codec->core.vendor_id) { |
@@ -5531,6 +5549,30 @@ static void alc295_fixup_chromebook(struct hda_codec *codec, | |||
5531 | } | 5549 | } |
5532 | } | 5550 | } |
5533 | 5551 | ||
5552 | static void alc295_fixup_chromebook(struct hda_codec *codec, | ||
5553 | const struct hda_fixup *fix, int action) | ||
5554 | { | ||
5555 | struct alc_spec *spec = codec->spec; | ||
5556 | |||
5557 | switch (action) { | ||
5558 | case HDA_FIXUP_ACT_PRE_PROBE: | ||
5559 | spec->ultra_low_power = true; | ||
5560 | break; | ||
5561 | case HDA_FIXUP_ACT_INIT: | ||
5562 | switch (codec->core.vendor_id) { | ||
5563 | case 0x10ec0295: | ||
5564 | alc_update_coef_idx(codec, 0x4a, 0x8000, 1 << 15); /* Reset HP JD */ | ||
5565 | alc_update_coef_idx(codec, 0x4a, 0x8000, 0 << 15); | ||
5566 | break; | ||
5567 | case 0x10ec0236: | ||
5568 | alc_update_coef_idx(codec, 0x1b, 0x8000, 1 << 15); /* Reset HP JD */ | ||
5569 | alc_update_coef_idx(codec, 0x1b, 0x8000, 0 << 15); | ||
5570 | break; | ||
5571 | } | ||
5572 | break; | ||
5573 | } | ||
5574 | } | ||
5575 | |||
5534 | static void alc_fixup_disable_mic_vref(struct hda_codec *codec, | 5576 | static void alc_fixup_disable_mic_vref(struct hda_codec *codec, |
5535 | const struct hda_fixup *fix, int action) | 5577 | const struct hda_fixup *fix, int action) |
5536 | { | 5578 | { |
@@ -5663,6 +5705,7 @@ enum { | |||
5663 | ALC233_FIXUP_ASUS_MIC_NO_PRESENCE, | 5705 | ALC233_FIXUP_ASUS_MIC_NO_PRESENCE, |
5664 | ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE, | 5706 | ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE, |
5665 | ALC233_FIXUP_LENOVO_MULTI_CODECS, | 5707 | ALC233_FIXUP_LENOVO_MULTI_CODECS, |
5708 | ALC233_FIXUP_ACER_HEADSET_MIC, | ||
5666 | ALC294_FIXUP_LENOVO_MIC_LOCATION, | 5709 | ALC294_FIXUP_LENOVO_MIC_LOCATION, |
5667 | ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE, | 5710 | ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE, |
5668 | ALC700_FIXUP_INTEL_REFERENCE, | 5711 | ALC700_FIXUP_INTEL_REFERENCE, |
@@ -5684,6 +5727,7 @@ enum { | |||
5684 | ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE, | 5727 | ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE, |
5685 | ALC255_FIXUP_ACER_HEADSET_MIC, | 5728 | ALC255_FIXUP_ACER_HEADSET_MIC, |
5686 | ALC295_FIXUP_CHROME_BOOK, | 5729 | ALC295_FIXUP_CHROME_BOOK, |
5730 | ALC225_FIXUP_HEADSET_JACK, | ||
5687 | ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE, | 5731 | ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE, |
5688 | ALC225_FIXUP_WYSE_AUTO_MUTE, | 5732 | ALC225_FIXUP_WYSE_AUTO_MUTE, |
5689 | ALC225_FIXUP_WYSE_DISABLE_MIC_VREF, | 5733 | ALC225_FIXUP_WYSE_DISABLE_MIC_VREF, |
@@ -6490,6 +6534,16 @@ static const struct hda_fixup alc269_fixups[] = { | |||
6490 | .type = HDA_FIXUP_FUNC, | 6534 | .type = HDA_FIXUP_FUNC, |
6491 | .v.func = alc233_alc662_fixup_lenovo_dual_codecs, | 6535 | .v.func = alc233_alc662_fixup_lenovo_dual_codecs, |
6492 | }, | 6536 | }, |
6537 | [ALC233_FIXUP_ACER_HEADSET_MIC] = { | ||
6538 | .type = HDA_FIXUP_VERBS, | ||
6539 | .v.verbs = (const struct hda_verb[]) { | ||
6540 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x45 }, | ||
6541 | { 0x20, AC_VERB_SET_PROC_COEF, 0x5089 }, | ||
6542 | { } | ||
6543 | }, | ||
6544 | .chained = true, | ||
6545 | .chain_id = ALC233_FIXUP_ASUS_MIC_NO_PRESENCE | ||
6546 | }, | ||
6493 | [ALC294_FIXUP_LENOVO_MIC_LOCATION] = { | 6547 | [ALC294_FIXUP_LENOVO_MIC_LOCATION] = { |
6494 | .type = HDA_FIXUP_PINS, | 6548 | .type = HDA_FIXUP_PINS, |
6495 | .v.pins = (const struct hda_pintbl[]) { | 6549 | .v.pins = (const struct hda_pintbl[]) { |
@@ -6635,6 +6689,12 @@ static const struct hda_fixup alc269_fixups[] = { | |||
6635 | [ALC295_FIXUP_CHROME_BOOK] = { | 6689 | [ALC295_FIXUP_CHROME_BOOK] = { |
6636 | .type = HDA_FIXUP_FUNC, | 6690 | .type = HDA_FIXUP_FUNC, |
6637 | .v.func = alc295_fixup_chromebook, | 6691 | .v.func = alc295_fixup_chromebook, |
6692 | .chained = true, | ||
6693 | .chain_id = ALC225_FIXUP_HEADSET_JACK | ||
6694 | }, | ||
6695 | [ALC225_FIXUP_HEADSET_JACK] = { | ||
6696 | .type = HDA_FIXUP_FUNC, | ||
6697 | .v.func = alc_fixup_headset_jack, | ||
6638 | }, | 6698 | }, |
6639 | [ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE] = { | 6699 | [ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE] = { |
6640 | .type = HDA_FIXUP_PINS, | 6700 | .type = HDA_FIXUP_PINS, |
@@ -6737,6 +6797,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
6737 | SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), | 6797 | SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), |
6738 | SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), | 6798 | SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), |
6739 | SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), | 6799 | SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), |
6800 | SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC), | ||
6740 | SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC), | 6801 | SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC), |
6741 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), | 6802 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), |
6742 | SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS), | 6803 | SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS), |
@@ -6902,6 +6963,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
6902 | SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC), | 6963 | SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC), |
6903 | SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), | 6964 | SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), |
6904 | SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | 6965 | SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), |
6966 | SND_PCI_QUIRK(0x1558, 0x8550, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | ||
6967 | SND_PCI_QUIRK(0x1558, 0x8560, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | ||
6905 | SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS), | 6968 | SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS), |
6906 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), | 6969 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), |
6907 | SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), | 6970 | SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), |
@@ -7132,7 +7195,8 @@ static const struct hda_model_fixup alc269_fixup_models[] = { | |||
7132 | {.id = ALC255_FIXUP_DUMMY_LINEOUT_VERB, .name = "alc255-dummy-lineout"}, | 7195 | {.id = ALC255_FIXUP_DUMMY_LINEOUT_VERB, .name = "alc255-dummy-lineout"}, |
7133 | {.id = ALC255_FIXUP_DELL_HEADSET_MIC, .name = "alc255-dell-headset"}, | 7196 | {.id = ALC255_FIXUP_DELL_HEADSET_MIC, .name = "alc255-dell-headset"}, |
7134 | {.id = ALC295_FIXUP_HP_X360, .name = "alc295-hp-x360"}, | 7197 | {.id = ALC295_FIXUP_HP_X360, .name = "alc295-hp-x360"}, |
7135 | {.id = ALC295_FIXUP_CHROME_BOOK, .name = "alc-sense-combo"}, | 7198 | {.id = ALC225_FIXUP_HEADSET_JACK, .name = "alc-headset-jack"}, |
7199 | {.id = ALC295_FIXUP_CHROME_BOOK, .name = "alc-chrome-book"}, | ||
7136 | {.id = ALC299_FIXUP_PREDATOR_SPK, .name = "predator-spk"}, | 7200 | {.id = ALC299_FIXUP_PREDATOR_SPK, .name = "predator-spk"}, |
7137 | {} | 7201 | {} |
7138 | }; | 7202 | }; |
@@ -7236,6 +7300,12 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { | |||
7236 | {0x12, 0x90a60140}, | 7300 | {0x12, 0x90a60140}, |
7237 | {0x14, 0x90170150}, | 7301 | {0x14, 0x90170150}, |
7238 | {0x21, 0x02211020}), | 7302 | {0x21, 0x02211020}), |
7303 | SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
7304 | {0x21, 0x02211020}), | ||
7305 | SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
7306 | {0x12, 0x40000000}, | ||
7307 | {0x14, 0x90170110}, | ||
7308 | {0x21, 0x02211020}), | ||
7239 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, | 7309 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, |
7240 | {0x14, 0x90170110}, | 7310 | {0x14, 0x90170110}, |
7241 | {0x21, 0x02211020}), | 7311 | {0x21, 0x02211020}), |
@@ -7346,6 +7416,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { | |||
7346 | {0x21, 0x0221101f}), | 7416 | {0x21, 0x0221101f}), |
7347 | SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | 7417 | SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, |
7348 | ALC256_STANDARD_PINS), | 7418 | ALC256_STANDARD_PINS), |
7419 | SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
7420 | {0x14, 0x90170110}, | ||
7421 | {0x1b, 0x01011020}, | ||
7422 | {0x21, 0x0221101f}), | ||
7349 | SND_HDA_PIN_QUIRK(0x10ec0256, 0x1043, "ASUS", ALC256_FIXUP_ASUS_MIC, | 7423 | SND_HDA_PIN_QUIRK(0x10ec0256, 0x1043, "ASUS", ALC256_FIXUP_ASUS_MIC, |
7350 | {0x14, 0x90170110}, | 7424 | {0x14, 0x90170110}, |
7351 | {0x1b, 0x90a70130}, | 7425 | {0x1b, 0x90a70130}, |
@@ -7505,6 +7579,13 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { | |||
7505 | {0x12, 0x90a60130}, | 7579 | {0x12, 0x90a60130}, |
7506 | {0x17, 0x90170110}, | 7580 | {0x17, 0x90170110}, |
7507 | {0x21, 0x04211020}), | 7581 | {0x21, 0x04211020}), |
7582 | SND_HDA_PIN_QUIRK(0x10ec0295, 0x1043, "ASUS", ALC294_FIXUP_ASUS_SPK, | ||
7583 | {0x12, 0x90a60130}, | ||
7584 | {0x17, 0x90170110}, | ||
7585 | {0x21, 0x03211020}), | ||
7586 | SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
7587 | {0x14, 0x90170110}, | ||
7588 | {0x21, 0x04211020}), | ||
7508 | SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, | 7589 | SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, |
7509 | ALC295_STANDARD_PINS, | 7590 | ALC295_STANDARD_PINS, |
7510 | {0x17, 0x21014020}, | 7591 | {0x17, 0x21014020}, |
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index 521236efcc4d..f77a0d5c0385 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c | |||
@@ -233,7 +233,6 @@ static int snd_ps3_program_dma(struct snd_ps3_card_info *card, | |||
233 | int fill_stages, dma_ch, stage; | 233 | int fill_stages, dma_ch, stage; |
234 | enum snd_ps3_ch ch; | 234 | enum snd_ps3_ch ch; |
235 | uint32_t ch0_kick_event = 0; /* initialize to mute gcc */ | 235 | uint32_t ch0_kick_event = 0; /* initialize to mute gcc */ |
236 | void *start_vaddr; | ||
237 | unsigned long irqsave; | 236 | unsigned long irqsave; |
238 | int silent = 0; | 237 | int silent = 0; |
239 | 238 | ||
@@ -257,7 +256,6 @@ static int snd_ps3_program_dma(struct snd_ps3_card_info *card, | |||
257 | fill_stages = 4; | 256 | fill_stages = 4; |
258 | spin_lock_irqsave(&card->dma_lock, irqsave); | 257 | spin_lock_irqsave(&card->dma_lock, irqsave); |
259 | for (ch = 0; ch < 2; ch++) { | 258 | for (ch = 0; ch < 2; ch++) { |
260 | start_vaddr = card->dma_next_transfer_vaddr[0]; | ||
261 | for (stage = 0; stage < fill_stages; stage++) { | 259 | for (stage = 0; stage < fill_stages; stage++) { |
262 | dma_ch = stage * 2 + ch; | 260 | dma_ch = stage * 2 + ch; |
263 | if (silent) | 261 | if (silent) |
@@ -526,9 +524,7 @@ static int snd_ps3_pcm_open(struct snd_pcm_substream *substream) | |||
526 | { | 524 | { |
527 | struct snd_pcm_runtime *runtime = substream->runtime; | 525 | struct snd_pcm_runtime *runtime = substream->runtime; |
528 | struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); | 526 | struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); |
529 | int pcm_index; | ||
530 | 527 | ||
531 | pcm_index = substream->pcm->device; | ||
532 | /* to retrieve substream/runtime in interrupt handler */ | 528 | /* to retrieve substream/runtime in interrupt handler */ |
533 | card->substream = substream; | 529 | card->substream = substream; |
534 | 530 | ||
diff --git a/sound/sh/aica.c b/sound/sh/aica.c index e7fef3fce44a..a24e486d9d83 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c | |||
@@ -303,7 +303,7 @@ static void aica_period_elapsed(struct timer_list *t) | |||
303 | { | 303 | { |
304 | struct snd_card_aica *dreamcastcard = from_timer(dreamcastcard, | 304 | struct snd_card_aica *dreamcastcard = from_timer(dreamcastcard, |
305 | t, timer); | 305 | t, timer); |
306 | struct snd_pcm_substream *substream = dreamcastcard->timer_substream; | 306 | struct snd_pcm_substream *substream = dreamcastcard->substream; |
307 | /*timer function - so cannot sleep */ | 307 | /*timer function - so cannot sleep */ |
308 | int play_period; | 308 | int play_period; |
309 | struct snd_pcm_runtime *runtime; | 309 | struct snd_pcm_runtime *runtime; |
@@ -335,13 +335,6 @@ static void spu_begin_dma(struct snd_pcm_substream *substream) | |||
335 | dreamcastcard = substream->pcm->private_data; | 335 | dreamcastcard = substream->pcm->private_data; |
336 | /*get the queue to do the work */ | 336 | /*get the queue to do the work */ |
337 | schedule_work(&(dreamcastcard->spu_dma_work)); | 337 | schedule_work(&(dreamcastcard->spu_dma_work)); |
338 | /* Timer may already be running */ | ||
339 | if (unlikely(dreamcastcard->timer_substream)) { | ||
340 | mod_timer(&dreamcastcard->timer, jiffies + 4); | ||
341 | return; | ||
342 | } | ||
343 | timer_setup(&dreamcastcard->timer, aica_period_elapsed, 0); | ||
344 | dreamcastcard->timer_substream = substream; | ||
345 | mod_timer(&dreamcastcard->timer, jiffies + 4); | 338 | mod_timer(&dreamcastcard->timer, jiffies + 4); |
346 | } | 339 | } |
347 | 340 | ||
@@ -379,8 +372,8 @@ static int snd_aicapcm_pcm_close(struct snd_pcm_substream | |||
379 | { | 372 | { |
380 | struct snd_card_aica *dreamcastcard = substream->pcm->private_data; | 373 | struct snd_card_aica *dreamcastcard = substream->pcm->private_data; |
381 | flush_work(&(dreamcastcard->spu_dma_work)); | 374 | flush_work(&(dreamcastcard->spu_dma_work)); |
382 | if (dreamcastcard->timer_substream) | 375 | del_timer(&dreamcastcard->timer); |
383 | del_timer(&dreamcastcard->timer); | 376 | dreamcastcard->substream = NULL; |
384 | kfree(dreamcastcard->channel); | 377 | kfree(dreamcastcard->channel); |
385 | spu_disable(); | 378 | spu_disable(); |
386 | return 0; | 379 | return 0; |
@@ -613,6 +606,7 @@ static int snd_aica_probe(struct platform_device *devptr) | |||
613 | "Yamaha AICA Super Intelligent Sound Processor for SEGA Dreamcast"); | 606 | "Yamaha AICA Super Intelligent Sound Processor for SEGA Dreamcast"); |
614 | /* Prepare to use the queue */ | 607 | /* Prepare to use the queue */ |
615 | INIT_WORK(&(dreamcastcard->spu_dma_work), run_spu_dma); | 608 | INIT_WORK(&(dreamcastcard->spu_dma_work), run_spu_dma); |
609 | timer_setup(&dreamcastcard->timer, aica_period_elapsed, 0); | ||
616 | /* Load the PCM 'chip' */ | 610 | /* Load the PCM 'chip' */ |
617 | err = snd_aicapcmchip(dreamcastcard, 0); | 611 | err = snd_aicapcmchip(dreamcastcard, 0); |
618 | if (unlikely(err < 0)) | 612 | if (unlikely(err < 0)) |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9981d40ef45b..8f577258080b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -1162,6 +1162,7 @@ config SND_SOC_WCD9335 | |||
1162 | tristate "WCD9335 Codec" | 1162 | tristate "WCD9335 Codec" |
1163 | depends on SLIMBUS | 1163 | depends on SLIMBUS |
1164 | select REGMAP_SLIMBUS | 1164 | select REGMAP_SLIMBUS |
1165 | select REGMAP_IRQ | ||
1165 | help | 1166 | help |
1166 | The WCD9335 is a standalone Hi-Fi audio CODEC IC, supports | 1167 | The WCD9335 is a standalone Hi-Fi audio CODEC IC, supports |
1167 | Qualcomm Technologies, Inc. (QTI) multimedia solutions, | 1168 | Qualcomm Technologies, Inc. (QTI) multimedia solutions, |
diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 92d006a5283e..425c11d63e49 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c | |||
@@ -1305,7 +1305,10 @@ static int da7213_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | |||
1305 | /* By default only 64 BCLK per WCLK is supported */ | 1305 | /* By default only 64 BCLK per WCLK is supported */ |
1306 | dai_clk_mode |= DA7213_DAI_BCLKS_PER_WCLK_64; | 1306 | dai_clk_mode |= DA7213_DAI_BCLKS_PER_WCLK_64; |
1307 | 1307 | ||
1308 | snd_soc_component_write(component, DA7213_DAI_CLK_MODE, dai_clk_mode); | 1308 | snd_soc_component_update_bits(component, DA7213_DAI_CLK_MODE, |
1309 | DA7213_DAI_BCLKS_PER_WCLK_MASK | | ||
1310 | DA7213_DAI_CLK_POL_MASK | DA7213_DAI_WCLK_POL_MASK, | ||
1311 | dai_clk_mode); | ||
1309 | snd_soc_component_update_bits(component, DA7213_DAI_CTRL, DA7213_DAI_FORMAT_MASK, | 1312 | snd_soc_component_update_bits(component, DA7213_DAI_CTRL, DA7213_DAI_FORMAT_MASK, |
1310 | dai_ctrl); | 1313 | dai_ctrl); |
1311 | snd_soc_component_write(component, DA7213_DAI_OFFSET, dai_offset); | 1314 | snd_soc_component_write(component, DA7213_DAI_OFFSET, dai_offset); |
diff --git a/sound/soc/codecs/da7213.h b/sound/soc/codecs/da7213.h index 5a78dba1dcb5..9d31efc3cfe5 100644 --- a/sound/soc/codecs/da7213.h +++ b/sound/soc/codecs/da7213.h | |||
@@ -181,7 +181,9 @@ | |||
181 | #define DA7213_DAI_BCLKS_PER_WCLK_256 (0x3 << 0) | 181 | #define DA7213_DAI_BCLKS_PER_WCLK_256 (0x3 << 0) |
182 | #define DA7213_DAI_BCLKS_PER_WCLK_MASK (0x3 << 0) | 182 | #define DA7213_DAI_BCLKS_PER_WCLK_MASK (0x3 << 0) |
183 | #define DA7213_DAI_CLK_POL_INV (0x1 << 2) | 183 | #define DA7213_DAI_CLK_POL_INV (0x1 << 2) |
184 | #define DA7213_DAI_CLK_POL_MASK (0x1 << 2) | ||
184 | #define DA7213_DAI_WCLK_POL_INV (0x1 << 3) | 185 | #define DA7213_DAI_WCLK_POL_INV (0x1 << 3) |
186 | #define DA7213_DAI_WCLK_POL_MASK (0x1 << 3) | ||
185 | #define DA7213_DAI_CLK_EN_MASK (0x1 << 7) | 187 | #define DA7213_DAI_CLK_EN_MASK (0x1 << 7) |
186 | 188 | ||
187 | /* DA7213_DAI_CTRL = 0x29 */ | 189 | /* DA7213_DAI_CTRL = 0x29 */ |
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 43c03e7b2f0e..7d9d1f84eed8 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c | |||
@@ -1673,20 +1673,26 @@ static const struct snd_soc_dai_ops da7219_dai_ops = { | |||
1673 | #define DA7219_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 1673 | #define DA7219_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
1674 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | 1674 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
1675 | 1675 | ||
1676 | #define DA7219_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | ||
1677 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ | ||
1678 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ | ||
1679 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ | ||
1680 | SNDRV_PCM_RATE_96000) | ||
1681 | |||
1676 | static struct snd_soc_dai_driver da7219_dai = { | 1682 | static struct snd_soc_dai_driver da7219_dai = { |
1677 | .name = "da7219-hifi", | 1683 | .name = "da7219-hifi", |
1678 | .playback = { | 1684 | .playback = { |
1679 | .stream_name = "Playback", | 1685 | .stream_name = "Playback", |
1680 | .channels_min = 1, | 1686 | .channels_min = 1, |
1681 | .channels_max = DA7219_DAI_CH_NUM_MAX, | 1687 | .channels_max = DA7219_DAI_CH_NUM_MAX, |
1682 | .rates = SNDRV_PCM_RATE_8000_96000, | 1688 | .rates = DA7219_RATES, |
1683 | .formats = DA7219_FORMATS, | 1689 | .formats = DA7219_FORMATS, |
1684 | }, | 1690 | }, |
1685 | .capture = { | 1691 | .capture = { |
1686 | .stream_name = "Capture", | 1692 | .stream_name = "Capture", |
1687 | .channels_min = 1, | 1693 | .channels_min = 1, |
1688 | .channels_max = DA7219_DAI_CH_NUM_MAX, | 1694 | .channels_max = DA7219_DAI_CH_NUM_MAX, |
1689 | .rates = SNDRV_PCM_RATE_8000_96000, | 1695 | .rates = DA7219_RATES, |
1690 | .formats = DA7219_FORMATS, | 1696 | .formats = DA7219_FORMATS, |
1691 | }, | 1697 | }, |
1692 | .ops = &da7219_dai_ops, | 1698 | .ops = &da7219_dai_ops, |
diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c index f889d94c8e3c..7d4940256914 100644 --- a/sound/soc/codecs/hdac_hda.c +++ b/sound/soc/codecs/hdac_hda.c | |||
@@ -328,6 +328,12 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) | |||
328 | dev_err(&hdev->dev, "failed to create hda codec %d\n", ret); | 328 | dev_err(&hdev->dev, "failed to create hda codec %d\n", ret); |
329 | goto error_no_pm; | 329 | goto error_no_pm; |
330 | } | 330 | } |
331 | /* | ||
332 | * Overwrite type to HDA_DEV_ASOC since it is a ASoC driver | ||
333 | * hda_codec.c will check this flag to determine if unregister | ||
334 | * device is needed. | ||
335 | */ | ||
336 | hdev->type = HDA_DEV_ASOC; | ||
331 | 337 | ||
332 | /* | 338 | /* |
333 | * snd_hda_codec_device_new decrements the usage count so call get pm | 339 | * snd_hda_codec_device_new decrements the usage count so call get pm |
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index ef6d6959ecc5..39caf19abb0b 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c | |||
@@ -439,8 +439,12 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream, | |||
439 | if (!ret) { | 439 | if (!ret) { |
440 | ret = snd_pcm_hw_constraint_eld(substream->runtime, | 440 | ret = snd_pcm_hw_constraint_eld(substream->runtime, |
441 | hcp->eld); | 441 | hcp->eld); |
442 | if (ret) | 442 | if (ret) { |
443 | mutex_lock(&hcp->current_stream_lock); | ||
444 | hcp->current_stream = NULL; | ||
445 | mutex_unlock(&hcp->current_stream_lock); | ||
443 | return ret; | 446 | return ret; |
447 | } | ||
444 | } | 448 | } |
445 | /* Select chmap supported */ | 449 | /* Select chmap supported */ |
446 | hdmi_codec_eld_chmap(hcp); | 450 | hdmi_codec_eld_chmap(hcp); |
diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index 7044d8c2b187..879f14257a3e 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | |||
@@ -405,7 +405,7 @@ static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { | |||
405 | }; | 405 | }; |
406 | 406 | ||
407 | static const unsigned int dmic_2ch[] = { | 407 | static const unsigned int dmic_2ch[] = { |
408 | 4, | 408 | 2, |
409 | }; | 409 | }; |
410 | 410 | ||
411 | static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = { | 411 | static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = { |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 65ee0bb5dd0b..81a7a12196ff 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -883,6 +883,7 @@ static int dapm_create_or_share_kcontrol(struct snd_soc_dapm_widget *w, | |||
883 | case snd_soc_dapm_switch: | 883 | case snd_soc_dapm_switch: |
884 | case snd_soc_dapm_mixer: | 884 | case snd_soc_dapm_mixer: |
885 | case snd_soc_dapm_pga: | 885 | case snd_soc_dapm_pga: |
886 | case snd_soc_dapm_effect: | ||
886 | case snd_soc_dapm_out_drv: | 887 | case snd_soc_dapm_out_drv: |
887 | wname_in_long_name = true; | 888 | wname_in_long_name = true; |
888 | kcname_in_long_name = true; | 889 | kcname_in_long_name = true; |
@@ -2370,6 +2371,7 @@ static ssize_t dapm_widget_show_component(struct snd_soc_component *cmpnt, | |||
2370 | case snd_soc_dapm_dac: | 2371 | case snd_soc_dapm_dac: |
2371 | case snd_soc_dapm_adc: | 2372 | case snd_soc_dapm_adc: |
2372 | case snd_soc_dapm_pga: | 2373 | case snd_soc_dapm_pga: |
2374 | case snd_soc_dapm_effect: | ||
2373 | case snd_soc_dapm_out_drv: | 2375 | case snd_soc_dapm_out_drv: |
2374 | case snd_soc_dapm_mixer: | 2376 | case snd_soc_dapm_mixer: |
2375 | case snd_soc_dapm_mixer_named_ctl: | 2377 | case snd_soc_dapm_mixer_named_ctl: |
@@ -3197,6 +3199,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) | |||
3197 | dapm_new_mux(w); | 3199 | dapm_new_mux(w); |
3198 | break; | 3200 | break; |
3199 | case snd_soc_dapm_pga: | 3201 | case snd_soc_dapm_pga: |
3202 | case snd_soc_dapm_effect: | ||
3200 | case snd_soc_dapm_out_drv: | 3203 | case snd_soc_dapm_out_drv: |
3201 | dapm_new_pga(w); | 3204 | dapm_new_pga(w); |
3202 | break; | 3205 | break; |
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 74695355c1f8..0a4f60c7a188 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -43,8 +43,8 @@ static bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream) | |||
43 | else | 43 | else |
44 | codec_stream = &dai->driver->capture; | 44 | codec_stream = &dai->driver->capture; |
45 | 45 | ||
46 | /* If the codec specifies any rate at all, it supports the stream. */ | 46 | /* If the codec specifies any channels at all, it supports the stream */ |
47 | return codec_stream->rates; | 47 | return codec_stream->channels_min; |
48 | } | 48 | } |
49 | 49 | ||
50 | /** | 50 | /** |
@@ -518,8 +518,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
518 | continue; | 518 | continue; |
519 | 519 | ||
520 | if (component->driver->module_get_upon_open && | 520 | if (component->driver->module_get_upon_open && |
521 | !try_module_get(component->dev->driver->owner)) | 521 | !try_module_get(component->dev->driver->owner)) { |
522 | return -ENODEV; | 522 | ret = -ENODEV; |
523 | goto module_err; | ||
524 | } | ||
523 | 525 | ||
524 | ret = component->driver->ops->open(substream); | 526 | ret = component->driver->ops->open(substream); |
525 | if (ret < 0) { | 527 | if (ret < 0) { |
@@ -636,7 +638,7 @@ codec_dai_err: | |||
636 | 638 | ||
637 | component_err: | 639 | component_err: |
638 | soc_pcm_components_close(substream, component); | 640 | soc_pcm_components_close(substream, component); |
639 | 641 | module_err: | |
640 | if (cpu_dai->driver->ops->shutdown) | 642 | if (cpu_dai->driver->ops->shutdown) |
641 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | 643 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); |
642 | out: | 644 | out: |
@@ -1031,6 +1033,9 @@ interface_err: | |||
1031 | 1033 | ||
1032 | codec_err: | 1034 | codec_err: |
1033 | for_each_rtd_codec_dai_rollback(rtd, i, codec_dai) { | 1035 | for_each_rtd_codec_dai_rollback(rtd, i, codec_dai) { |
1036 | if (!snd_soc_dai_stream_valid(codec_dai, substream->stream)) | ||
1037 | continue; | ||
1038 | |||
1034 | if (codec_dai->driver->ops->hw_free) | 1039 | if (codec_dai->driver->ops->hw_free) |
1035 | codec_dai->driver->ops->hw_free(substream, codec_dai); | 1040 | codec_dai->driver->ops->hw_free(substream, codec_dai); |
1036 | codec_dai->rate = 0; | 1041 | codec_dai->rate = 0; |
@@ -1088,6 +1093,9 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
1088 | 1093 | ||
1089 | /* now free hw params for the DAIs */ | 1094 | /* now free hw params for the DAIs */ |
1090 | for_each_rtd_codec_dai(rtd, i, codec_dai) { | 1095 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
1096 | if (!snd_soc_dai_stream_valid(codec_dai, substream->stream)) | ||
1097 | continue; | ||
1098 | |||
1091 | if (codec_dai->driver->ops->hw_free) | 1099 | if (codec_dai->driver->ops->hw_free) |
1092 | codec_dai->driver->ops->hw_free(substream, codec_dai); | 1100 | codec_dai->driver->ops->hw_free(substream, codec_dai); |
1093 | } | 1101 | } |
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index e3b021c9e8d0..2a74ce7c9440 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c | |||
@@ -70,6 +70,7 @@ | |||
70 | #define SAI_IEC60958_STATUS_BYTES 24 | 70 | #define SAI_IEC60958_STATUS_BYTES 24 |
71 | 71 | ||
72 | #define SAI_MCLK_NAME_LEN 32 | 72 | #define SAI_MCLK_NAME_LEN 32 |
73 | #define SAI_RATE_11K 11025 | ||
73 | 74 | ||
74 | /** | 75 | /** |
75 | * struct stm32_sai_sub_data - private data of SAI sub block (block A or B) | 76 | * struct stm32_sai_sub_data - private data of SAI sub block (block A or B) |
@@ -311,6 +312,25 @@ static int stm32_sai_set_clk_div(struct stm32_sai_sub_data *sai, | |||
311 | return ret; | 312 | return ret; |
312 | } | 313 | } |
313 | 314 | ||
315 | static int stm32_sai_set_parent_clock(struct stm32_sai_sub_data *sai, | ||
316 | unsigned int rate) | ||
317 | { | ||
318 | struct platform_device *pdev = sai->pdev; | ||
319 | struct clk *parent_clk = sai->pdata->clk_x8k; | ||
320 | int ret; | ||
321 | |||
322 | if (!(rate % SAI_RATE_11K)) | ||
323 | parent_clk = sai->pdata->clk_x11k; | ||
324 | |||
325 | ret = clk_set_parent(sai->sai_ck, parent_clk); | ||
326 | if (ret) | ||
327 | dev_err(&pdev->dev, " Error %d setting sai_ck parent clock. %s", | ||
328 | ret, ret == -EBUSY ? | ||
329 | "Active stream rates conflict\n" : "\n"); | ||
330 | |||
331 | return ret; | ||
332 | } | ||
333 | |||
314 | static long stm32_sai_mclk_round_rate(struct clk_hw *hw, unsigned long rate, | 334 | static long stm32_sai_mclk_round_rate(struct clk_hw *hw, unsigned long rate, |
315 | unsigned long *prate) | 335 | unsigned long *prate) |
316 | { | 336 | { |
@@ -492,25 +512,29 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai, | |||
492 | struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); | 512 | struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); |
493 | int ret; | 513 | int ret; |
494 | 514 | ||
495 | if (dir == SND_SOC_CLOCK_OUT) { | 515 | if (dir == SND_SOC_CLOCK_OUT && sai->sai_mclk) { |
496 | ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, | 516 | ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, |
497 | SAI_XCR1_NODIV, | 517 | SAI_XCR1_NODIV, |
498 | (unsigned int)~SAI_XCR1_NODIV); | 518 | (unsigned int)~SAI_XCR1_NODIV); |
499 | if (ret < 0) | 519 | if (ret < 0) |
500 | return ret; | 520 | return ret; |
501 | 521 | ||
502 | dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq); | 522 | /* If master clock is used, set parent clock now */ |
503 | sai->mclk_rate = freq; | 523 | ret = stm32_sai_set_parent_clock(sai, freq); |
524 | if (ret) | ||
525 | return ret; | ||
504 | 526 | ||
505 | if (sai->sai_mclk) { | 527 | ret = clk_set_rate_exclusive(sai->sai_mclk, freq); |
506 | ret = clk_set_rate_exclusive(sai->sai_mclk, | 528 | if (ret) { |
507 | sai->mclk_rate); | 529 | dev_err(cpu_dai->dev, |
508 | if (ret) { | 530 | ret == -EBUSY ? |
509 | dev_err(cpu_dai->dev, | 531 | "Active streams have incompatible rates" : |
510 | "Could not set mclk rate\n"); | 532 | "Could not set mclk rate\n"); |
511 | return ret; | 533 | return ret; |
512 | } | ||
513 | } | 534 | } |
535 | |||
536 | dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq); | ||
537 | sai->mclk_rate = freq; | ||
514 | } | 538 | } |
515 | 539 | ||
516 | return 0; | 540 | return 0; |
@@ -917,11 +941,13 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai, | |||
917 | int div = 0, cr1 = 0; | 941 | int div = 0, cr1 = 0; |
918 | int sai_clk_rate, mclk_ratio, den; | 942 | int sai_clk_rate, mclk_ratio, den; |
919 | unsigned int rate = params_rate(params); | 943 | unsigned int rate = params_rate(params); |
944 | int ret; | ||
920 | 945 | ||
921 | if (!(rate % 11025)) | 946 | if (!sai->sai_mclk) { |
922 | clk_set_parent(sai->sai_ck, sai->pdata->clk_x11k); | 947 | ret = stm32_sai_set_parent_clock(sai, rate); |
923 | else | 948 | if (ret) |
924 | clk_set_parent(sai->sai_ck, sai->pdata->clk_x8k); | 949 | return ret; |
950 | } | ||
925 | sai_clk_rate = clk_get_rate(sai->sai_ck); | 951 | sai_clk_rate = clk_get_rate(sai->sai_ck); |
926 | 952 | ||
927 | if (STM_SAI_IS_F4(sai->pdata)) { | 953 | if (STM_SAI_IS_F4(sai->pdata)) { |
@@ -1080,9 +1106,13 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream, | |||
1080 | regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, SAI_XCR1_NODIV, | 1106 | regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, SAI_XCR1_NODIV, |
1081 | SAI_XCR1_NODIV); | 1107 | SAI_XCR1_NODIV); |
1082 | 1108 | ||
1083 | clk_disable_unprepare(sai->sai_ck); | 1109 | /* Release mclk rate only if rate was actually set */ |
1110 | if (sai->mclk_rate) { | ||
1111 | clk_rate_exclusive_put(sai->sai_mclk); | ||
1112 | sai->mclk_rate = 0; | ||
1113 | } | ||
1084 | 1114 | ||
1085 | clk_rate_exclusive_put(sai->sai_mclk); | 1115 | clk_disable_unprepare(sai->sai_ck); |
1086 | 1116 | ||
1087 | spin_lock_irqsave(&sai->irq_lock, flags); | 1117 | spin_lock_irqsave(&sai->irq_lock, flags); |
1088 | sai->substream = NULL; | 1118 | sai->substream = NULL; |
diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c index d9fcae071b47..fae48d108b97 100644 --- a/sound/synth/emux/emux_hwdep.c +++ b/sound/synth/emux/emux_hwdep.c | |||
@@ -39,6 +39,11 @@ snd_emux_hwdep_load_patch(struct snd_emux *emu, void __user *arg) | |||
39 | if (copy_from_user(&patch, arg, sizeof(patch))) | 39 | if (copy_from_user(&patch, arg, sizeof(patch))) |
40 | return -EFAULT; | 40 | return -EFAULT; |
41 | 41 | ||
42 | if (patch.key == GUS_PATCH) | ||
43 | return snd_soundfont_load_guspatch(emu->sflist, arg, | ||
44 | patch.len + sizeof(patch), | ||
45 | TMP_CLIENT_ID); | ||
46 | |||
42 | if (patch.type >= SNDRV_SFNT_LOAD_INFO && | 47 | if (patch.type >= SNDRV_SFNT_LOAD_INFO && |
43 | patch.type <= SNDRV_SFNT_PROBE_DATA) { | 48 | patch.type <= SNDRV_SFNT_PROBE_DATA) { |
44 | err = snd_soundfont_load(emu->sflist, arg, patch.len + sizeof(patch), TMP_CLIENT_ID); | 49 | err = snd_soundfont_load(emu->sflist, arg, patch.len + sizeof(patch), TMP_CLIENT_ID); |
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c index 31a4ea94830e..9b5d70104489 100644 --- a/sound/synth/emux/soundfont.c +++ b/sound/synth/emux/soundfont.c | |||
@@ -856,6 +856,8 @@ calc_gus_envelope_time(int rate, int start, int end) | |||
856 | int r, p, t; | 856 | int r, p, t; |
857 | r = (3 - ((rate >> 6) & 3)) * 3; | 857 | r = (3 - ((rate >> 6) & 3)) * 3; |
858 | p = rate & 0x3f; | 858 | p = rate & 0x3f; |
859 | if (!p) | ||
860 | p = 1; | ||
859 | t = end - start; | 861 | t = end - start; |
860 | if (t < 0) t = -t; | 862 | if (t < 0) t = -t; |
861 | if (13 > r) | 863 | if (13 > r) |
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 7afe8fae4939..b61f65bed4e4 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c | |||
@@ -351,12 +351,16 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, | |||
351 | { | 351 | { |
352 | struct usb_device *usbdev = line6->usbdev; | 352 | struct usb_device *usbdev = line6->usbdev; |
353 | int ret; | 353 | int ret; |
354 | unsigned char len; | 354 | unsigned char *len; |
355 | unsigned count; | 355 | unsigned count; |
356 | 356 | ||
357 | if (address > 0xffff || datalen > 0xff) | 357 | if (address > 0xffff || datalen > 0xff) |
358 | return -EINVAL; | 358 | return -EINVAL; |
359 | 359 | ||
360 | len = kmalloc(sizeof(*len), GFP_KERNEL); | ||
361 | if (!len) | ||
362 | return -ENOMEM; | ||
363 | |||
360 | /* query the serial number: */ | 364 | /* query the serial number: */ |
361 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, | 365 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, |
362 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | 366 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, |
@@ -365,7 +369,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, | |||
365 | 369 | ||
366 | if (ret < 0) { | 370 | if (ret < 0) { |
367 | dev_err(line6->ifcdev, "read request failed (error %d)\n", ret); | 371 | dev_err(line6->ifcdev, "read request failed (error %d)\n", ret); |
368 | return ret; | 372 | goto exit; |
369 | } | 373 | } |
370 | 374 | ||
371 | /* Wait for data length. We'll get 0xff until length arrives. */ | 375 | /* Wait for data length. We'll get 0xff until length arrives. */ |
@@ -375,28 +379,29 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, | |||
375 | ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, | 379 | ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, |
376 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | | 380 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | |
377 | USB_DIR_IN, | 381 | USB_DIR_IN, |
378 | 0x0012, 0x0000, &len, 1, | 382 | 0x0012, 0x0000, len, 1, |
379 | LINE6_TIMEOUT * HZ); | 383 | LINE6_TIMEOUT * HZ); |
380 | if (ret < 0) { | 384 | if (ret < 0) { |
381 | dev_err(line6->ifcdev, | 385 | dev_err(line6->ifcdev, |
382 | "receive length failed (error %d)\n", ret); | 386 | "receive length failed (error %d)\n", ret); |
383 | return ret; | 387 | goto exit; |
384 | } | 388 | } |
385 | 389 | ||
386 | if (len != 0xff) | 390 | if (*len != 0xff) |
387 | break; | 391 | break; |
388 | } | 392 | } |
389 | 393 | ||
390 | if (len == 0xff) { | 394 | ret = -EIO; |
395 | if (*len == 0xff) { | ||
391 | dev_err(line6->ifcdev, "read failed after %d retries\n", | 396 | dev_err(line6->ifcdev, "read failed after %d retries\n", |
392 | count); | 397 | count); |
393 | return -EIO; | 398 | goto exit; |
394 | } else if (len != datalen) { | 399 | } else if (*len != datalen) { |
395 | /* should be equal or something went wrong */ | 400 | /* should be equal or something went wrong */ |
396 | dev_err(line6->ifcdev, | 401 | dev_err(line6->ifcdev, |
397 | "length mismatch (expected %d, got %d)\n", | 402 | "length mismatch (expected %d, got %d)\n", |
398 | (int)datalen, (int)len); | 403 | (int)datalen, (int)*len); |
399 | return -EIO; | 404 | goto exit; |
400 | } | 405 | } |
401 | 406 | ||
402 | /* receive the result: */ | 407 | /* receive the result: */ |
@@ -405,12 +410,12 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, | |||
405 | 0x0013, 0x0000, data, datalen, | 410 | 0x0013, 0x0000, data, datalen, |
406 | LINE6_TIMEOUT * HZ); | 411 | LINE6_TIMEOUT * HZ); |
407 | 412 | ||
408 | if (ret < 0) { | 413 | if (ret < 0) |
409 | dev_err(line6->ifcdev, "read failed (error %d)\n", ret); | 414 | dev_err(line6->ifcdev, "read failed (error %d)\n", ret); |
410 | return ret; | ||
411 | } | ||
412 | 415 | ||
413 | return 0; | 416 | exit: |
417 | kfree(len); | ||
418 | return ret; | ||
414 | } | 419 | } |
415 | EXPORT_SYMBOL_GPL(line6_read_data); | 420 | EXPORT_SYMBOL_GPL(line6_read_data); |
416 | 421 | ||
@@ -422,12 +427,16 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, | |||
422 | { | 427 | { |
423 | struct usb_device *usbdev = line6->usbdev; | 428 | struct usb_device *usbdev = line6->usbdev; |
424 | int ret; | 429 | int ret; |
425 | unsigned char status; | 430 | unsigned char *status; |
426 | int count; | 431 | int count; |
427 | 432 | ||
428 | if (address > 0xffff || datalen > 0xffff) | 433 | if (address > 0xffff || datalen > 0xffff) |
429 | return -EINVAL; | 434 | return -EINVAL; |
430 | 435 | ||
436 | status = kmalloc(sizeof(*status), GFP_KERNEL); | ||
437 | if (!status) | ||
438 | return -ENOMEM; | ||
439 | |||
431 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, | 440 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, |
432 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | 441 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, |
433 | 0x0022, address, data, datalen, | 442 | 0x0022, address, data, datalen, |
@@ -436,7 +445,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, | |||
436 | if (ret < 0) { | 445 | if (ret < 0) { |
437 | dev_err(line6->ifcdev, | 446 | dev_err(line6->ifcdev, |
438 | "write request failed (error %d)\n", ret); | 447 | "write request failed (error %d)\n", ret); |
439 | return ret; | 448 | goto exit; |
440 | } | 449 | } |
441 | 450 | ||
442 | for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) { | 451 | for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) { |
@@ -447,28 +456,29 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, | |||
447 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | | 456 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | |
448 | USB_DIR_IN, | 457 | USB_DIR_IN, |
449 | 0x0012, 0x0000, | 458 | 0x0012, 0x0000, |
450 | &status, 1, LINE6_TIMEOUT * HZ); | 459 | status, 1, LINE6_TIMEOUT * HZ); |
451 | 460 | ||
452 | if (ret < 0) { | 461 | if (ret < 0) { |
453 | dev_err(line6->ifcdev, | 462 | dev_err(line6->ifcdev, |
454 | "receiving status failed (error %d)\n", ret); | 463 | "receiving status failed (error %d)\n", ret); |
455 | return ret; | 464 | goto exit; |
456 | } | 465 | } |
457 | 466 | ||
458 | if (status != 0xff) | 467 | if (*status != 0xff) |
459 | break; | 468 | break; |
460 | } | 469 | } |
461 | 470 | ||
462 | if (status == 0xff) { | 471 | if (*status == 0xff) { |
463 | dev_err(line6->ifcdev, "write failed after %d retries\n", | 472 | dev_err(line6->ifcdev, "write failed after %d retries\n", |
464 | count); | 473 | count); |
465 | return -EIO; | 474 | ret = -EIO; |
466 | } else if (status != 0) { | 475 | } else if (*status != 0) { |
467 | dev_err(line6->ifcdev, "write failed (error %d)\n", ret); | 476 | dev_err(line6->ifcdev, "write failed (error %d)\n", ret); |
468 | return -EIO; | 477 | ret = -EIO; |
469 | } | 478 | } |
470 | 479 | exit: | |
471 | return 0; | 480 | kfree(status); |
481 | return ret; | ||
472 | } | 482 | } |
473 | EXPORT_SYMBOL_GPL(line6_write_data); | 483 | EXPORT_SYMBOL_GPL(line6_write_data); |
474 | 484 | ||
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index 36ed9c85c0eb..5f3c87264e66 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c | |||
@@ -225,28 +225,32 @@ static void podhd_startup_start_workqueue(struct timer_list *t) | |||
225 | static int podhd_dev_start(struct usb_line6_podhd *pod) | 225 | static int podhd_dev_start(struct usb_line6_podhd *pod) |
226 | { | 226 | { |
227 | int ret; | 227 | int ret; |
228 | u8 init_bytes[8]; | 228 | u8 *init_bytes; |
229 | int i; | 229 | int i; |
230 | struct usb_device *usbdev = pod->line6.usbdev; | 230 | struct usb_device *usbdev = pod->line6.usbdev; |
231 | 231 | ||
232 | init_bytes = kmalloc(8, GFP_KERNEL); | ||
233 | if (!init_bytes) | ||
234 | return -ENOMEM; | ||
235 | |||
232 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), | 236 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), |
233 | 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | 237 | 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, |
234 | 0x11, 0, | 238 | 0x11, 0, |
235 | NULL, 0, LINE6_TIMEOUT * HZ); | 239 | NULL, 0, LINE6_TIMEOUT * HZ); |
236 | if (ret < 0) { | 240 | if (ret < 0) { |
237 | dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret); | 241 | dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret); |
238 | return ret; | 242 | goto exit; |
239 | } | 243 | } |
240 | 244 | ||
241 | /* NOTE: looks like some kind of ping message */ | 245 | /* NOTE: looks like some kind of ping message */ |
242 | ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, | 246 | ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, |
243 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | 247 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, |
244 | 0x11, 0x0, | 248 | 0x11, 0x0, |
245 | &init_bytes, 3, LINE6_TIMEOUT * HZ); | 249 | init_bytes, 3, LINE6_TIMEOUT * HZ); |
246 | if (ret < 0) { | 250 | if (ret < 0) { |
247 | dev_err(pod->line6.ifcdev, | 251 | dev_err(pod->line6.ifcdev, |
248 | "receive length failed (error %d)\n", ret); | 252 | "receive length failed (error %d)\n", ret); |
249 | return ret; | 253 | goto exit; |
250 | } | 254 | } |
251 | 255 | ||
252 | pod->firmware_version = | 256 | pod->firmware_version = |
@@ -255,7 +259,7 @@ static int podhd_dev_start(struct usb_line6_podhd *pod) | |||
255 | for (i = 0; i <= 16; i++) { | 259 | for (i = 0; i <= 16; i++) { |
256 | ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8); | 260 | ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8); |
257 | if (ret < 0) | 261 | if (ret < 0) |
258 | return ret; | 262 | goto exit; |
259 | } | 263 | } |
260 | 264 | ||
261 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), | 265 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), |
@@ -263,10 +267,9 @@ static int podhd_dev_start(struct usb_line6_podhd *pod) | |||
263 | USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT, | 267 | USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT, |
264 | 1, 0, | 268 | 1, 0, |
265 | NULL, 0, LINE6_TIMEOUT * HZ); | 269 | NULL, 0, LINE6_TIMEOUT * HZ); |
266 | if (ret < 0) | 270 | exit: |
267 | return ret; | 271 | kfree(init_bytes); |
268 | 272 | return ret; | |
269 | return 0; | ||
270 | } | 273 | } |
271 | 274 | ||
272 | static void podhd_startup_workqueue(struct work_struct *work) | 275 | static void podhd_startup_workqueue(struct work_struct *work) |
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c index f47ba94e6f4a..325b07b98b3c 100644 --- a/sound/usb/line6/toneport.c +++ b/sound/usb/line6/toneport.c | |||
@@ -54,8 +54,8 @@ struct usb_line6_toneport { | |||
54 | /* Firmware version (x 100) */ | 54 | /* Firmware version (x 100) */ |
55 | u8 firmware_version; | 55 | u8 firmware_version; |
56 | 56 | ||
57 | /* Timer for delayed PCM startup */ | 57 | /* Work for delayed PCM startup */ |
58 | struct timer_list timer; | 58 | struct delayed_work pcm_work; |
59 | 59 | ||
60 | /* Device type */ | 60 | /* Device type */ |
61 | enum line6_device_type type; | 61 | enum line6_device_type type; |
@@ -241,9 +241,10 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol, | |||
241 | return 1; | 241 | return 1; |
242 | } | 242 | } |
243 | 243 | ||
244 | static void toneport_start_pcm(struct timer_list *t) | 244 | static void toneport_start_pcm(struct work_struct *work) |
245 | { | 245 | { |
246 | struct usb_line6_toneport *toneport = from_timer(toneport, t, timer); | 246 | struct usb_line6_toneport *toneport = |
247 | container_of(work, struct usb_line6_toneport, pcm_work.work); | ||
247 | struct usb_line6 *line6 = &toneport->line6; | 248 | struct usb_line6 *line6 = &toneport->line6; |
248 | 249 | ||
249 | line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR, true); | 250 | line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR, true); |
@@ -365,16 +366,21 @@ static bool toneport_has_source_select(struct usb_line6_toneport *toneport) | |||
365 | /* | 366 | /* |
366 | Setup Toneport device. | 367 | Setup Toneport device. |
367 | */ | 368 | */ |
368 | static void toneport_setup(struct usb_line6_toneport *toneport) | 369 | static int toneport_setup(struct usb_line6_toneport *toneport) |
369 | { | 370 | { |
370 | u32 ticks; | 371 | u32 *ticks; |
371 | struct usb_line6 *line6 = &toneport->line6; | 372 | struct usb_line6 *line6 = &toneport->line6; |
372 | struct usb_device *usbdev = line6->usbdev; | 373 | struct usb_device *usbdev = line6->usbdev; |
373 | 374 | ||
375 | ticks = kmalloc(sizeof(*ticks), GFP_KERNEL); | ||
376 | if (!ticks) | ||
377 | return -ENOMEM; | ||
378 | |||
374 | /* sync time on device with host: */ | 379 | /* sync time on device with host: */ |
375 | /* note: 32-bit timestamps overflow in year 2106 */ | 380 | /* note: 32-bit timestamps overflow in year 2106 */ |
376 | ticks = (u32)ktime_get_real_seconds(); | 381 | *ticks = (u32)ktime_get_real_seconds(); |
377 | line6_write_data(line6, 0x80c6, &ticks, 4); | 382 | line6_write_data(line6, 0x80c6, ticks, 4); |
383 | kfree(ticks); | ||
378 | 384 | ||
379 | /* enable device: */ | 385 | /* enable device: */ |
380 | toneport_send_cmd(usbdev, 0x0301, 0x0000); | 386 | toneport_send_cmd(usbdev, 0x0301, 0x0000); |
@@ -388,7 +394,9 @@ static void toneport_setup(struct usb_line6_toneport *toneport) | |||
388 | if (toneport_has_led(toneport)) | 394 | if (toneport_has_led(toneport)) |
389 | toneport_update_led(toneport); | 395 | toneport_update_led(toneport); |
390 | 396 | ||
391 | mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ); | 397 | schedule_delayed_work(&toneport->pcm_work, |
398 | msecs_to_jiffies(TONEPORT_PCM_DELAY * 1000)); | ||
399 | return 0; | ||
392 | } | 400 | } |
393 | 401 | ||
394 | /* | 402 | /* |
@@ -399,7 +407,7 @@ static void line6_toneport_disconnect(struct usb_line6 *line6) | |||
399 | struct usb_line6_toneport *toneport = | 407 | struct usb_line6_toneport *toneport = |
400 | (struct usb_line6_toneport *)line6; | 408 | (struct usb_line6_toneport *)line6; |
401 | 409 | ||
402 | del_timer_sync(&toneport->timer); | 410 | cancel_delayed_work_sync(&toneport->pcm_work); |
403 | 411 | ||
404 | if (toneport_has_led(toneport)) | 412 | if (toneport_has_led(toneport)) |
405 | toneport_remove_leds(toneport); | 413 | toneport_remove_leds(toneport); |
@@ -416,7 +424,7 @@ static int toneport_init(struct usb_line6 *line6, | |||
416 | struct usb_line6_toneport *toneport = (struct usb_line6_toneport *) line6; | 424 | struct usb_line6_toneport *toneport = (struct usb_line6_toneport *) line6; |
417 | 425 | ||
418 | toneport->type = id->driver_info; | 426 | toneport->type = id->driver_info; |
419 | timer_setup(&toneport->timer, toneport_start_pcm, 0); | 427 | INIT_DELAYED_WORK(&toneport->pcm_work, toneport_start_pcm); |
420 | 428 | ||
421 | line6->disconnect = line6_toneport_disconnect; | 429 | line6->disconnect = line6_toneport_disconnect; |
422 | 430 | ||
@@ -451,7 +459,9 @@ static int toneport_init(struct usb_line6 *line6, | |||
451 | return err; | 459 | return err; |
452 | } | 460 | } |
453 | 461 | ||
454 | toneport_setup(toneport); | 462 | err = toneport_setup(toneport); |
463 | if (err) | ||
464 | return err; | ||
455 | 465 | ||
456 | /* register audio system: */ | 466 | /* register audio system: */ |
457 | return snd_card_register(line6->card); | 467 | return snd_card_register(line6->card); |
@@ -463,7 +473,11 @@ static int toneport_init(struct usb_line6 *line6, | |||
463 | */ | 473 | */ |
464 | static int toneport_reset_resume(struct usb_interface *interface) | 474 | static int toneport_reset_resume(struct usb_interface *interface) |
465 | { | 475 | { |
466 | toneport_setup(usb_get_intfdata(interface)); | 476 | int err; |
477 | |||
478 | err = toneport_setup(usb_get_intfdata(interface)); | ||
479 | if (err) | ||
480 | return err; | ||
467 | return line6_resume(interface); | 481 | return line6_resume(interface); |
468 | } | 482 | } |
469 | #endif | 483 | #endif |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 73d7dff425c1..e003b5e7b01a 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -2675,6 +2675,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, | |||
2675 | kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval); | 2675 | kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval); |
2676 | if (! kctl) { | 2676 | if (! kctl) { |
2677 | usb_audio_err(state->chip, "cannot malloc kcontrol\n"); | 2677 | usb_audio_err(state->chip, "cannot malloc kcontrol\n"); |
2678 | for (i = 0; i < desc->bNrInPins; i++) | ||
2679 | kfree(namelist[i]); | ||
2678 | kfree(namelist); | 2680 | kfree(namelist); |
2679 | kfree(cval); | 2681 | kfree(cval); |
2680 | return -ENOMEM; | 2682 | return -ENOMEM; |
@@ -3490,7 +3492,9 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, | |||
3490 | if (err < 0) | 3492 | if (err < 0) |
3491 | goto _error; | 3493 | goto _error; |
3492 | 3494 | ||
3493 | snd_usb_mixer_apply_create_quirk(mixer); | 3495 | err = snd_usb_mixer_apply_create_quirk(mixer); |
3496 | if (err < 0) | ||
3497 | goto _error; | ||
3494 | 3498 | ||
3495 | err = snd_device_new(chip->card, SNDRV_DEV_CODEC, mixer, &dev_ops); | 3499 | err = snd_device_new(chip->card, SNDRV_DEV_CODEC, mixer, &dev_ops); |
3496 | if (err < 0) | 3500 | if (err < 0) |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 86e80916a029..629b84532648 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -2770,6 +2770,90 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2770 | .type = QUIRK_MIDI_NOVATION | 2770 | .type = QUIRK_MIDI_NOVATION |
2771 | } | 2771 | } |
2772 | }, | 2772 | }, |
2773 | { | ||
2774 | /* | ||
2775 | * Focusrite Scarlett Solo 2nd generation | ||
2776 | * Reports that playback should use Synch: Synchronous | ||
2777 | * while still providing a feedback endpoint. Synchronous causes | ||
2778 | * snapping on some sample rates. | ||
2779 | * Force it to use Synch: Asynchronous. | ||
2780 | */ | ||
2781 | USB_DEVICE(0x1235, 0x8205), | ||
2782 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
2783 | .ifnum = QUIRK_ANY_INTERFACE, | ||
2784 | .type = QUIRK_COMPOSITE, | ||
2785 | .data = (const struct snd_usb_audio_quirk[]) { | ||
2786 | { | ||
2787 | .ifnum = 1, | ||
2788 | .type = QUIRK_AUDIO_FIXED_ENDPOINT, | ||
2789 | .data = & (const struct audioformat) { | ||
2790 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
2791 | .channels = 2, | ||
2792 | .iface = 1, | ||
2793 | .altsetting = 1, | ||
2794 | .altset_idx = 1, | ||
2795 | .attributes = 0, | ||
2796 | .endpoint = 0x01, | ||
2797 | .ep_attr = USB_ENDPOINT_XFER_ISOC | | ||
2798 | USB_ENDPOINT_SYNC_ASYNC, | ||
2799 | .protocol = UAC_VERSION_2, | ||
2800 | .rates = SNDRV_PCM_RATE_44100 | | ||
2801 | SNDRV_PCM_RATE_48000 | | ||
2802 | SNDRV_PCM_RATE_88200 | | ||
2803 | SNDRV_PCM_RATE_96000 | | ||
2804 | SNDRV_PCM_RATE_176400 | | ||
2805 | SNDRV_PCM_RATE_192000, | ||
2806 | .rate_min = 44100, | ||
2807 | .rate_max = 192000, | ||
2808 | .nr_rates = 6, | ||
2809 | .rate_table = (unsigned int[]) { | ||
2810 | 44100, 48000, 88200, | ||
2811 | 96000, 176400, 192000 | ||
2812 | }, | ||
2813 | .clock = 41 | ||
2814 | } | ||
2815 | }, | ||
2816 | { | ||
2817 | .ifnum = 2, | ||
2818 | .type = QUIRK_AUDIO_FIXED_ENDPOINT, | ||
2819 | .data = & (const struct audioformat) { | ||
2820 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
2821 | .channels = 2, | ||
2822 | .iface = 2, | ||
2823 | .altsetting = 1, | ||
2824 | .altset_idx = 1, | ||
2825 | .attributes = 0, | ||
2826 | .endpoint = 0x82, | ||
2827 | .ep_attr = USB_ENDPOINT_XFER_ISOC | | ||
2828 | USB_ENDPOINT_SYNC_ASYNC | | ||
2829 | USB_ENDPOINT_USAGE_IMPLICIT_FB, | ||
2830 | .protocol = UAC_VERSION_2, | ||
2831 | .rates = SNDRV_PCM_RATE_44100 | | ||
2832 | SNDRV_PCM_RATE_48000 | | ||
2833 | SNDRV_PCM_RATE_88200 | | ||
2834 | SNDRV_PCM_RATE_96000 | | ||
2835 | SNDRV_PCM_RATE_176400 | | ||
2836 | SNDRV_PCM_RATE_192000, | ||
2837 | .rate_min = 44100, | ||
2838 | .rate_max = 192000, | ||
2839 | .nr_rates = 6, | ||
2840 | .rate_table = (unsigned int[]) { | ||
2841 | 44100, 48000, 88200, | ||
2842 | 96000, 176400, 192000 | ||
2843 | }, | ||
2844 | .clock = 41 | ||
2845 | } | ||
2846 | }, | ||
2847 | { | ||
2848 | .ifnum = 3, | ||
2849 | .type = QUIRK_IGNORE_INTERFACE | ||
2850 | }, | ||
2851 | { | ||
2852 | .ifnum = -1 | ||
2853 | } | ||
2854 | } | ||
2855 | } | ||
2856 | }, | ||
2773 | 2857 | ||
2774 | /* Access Music devices */ | 2858 | /* Access Music devices */ |
2775 | { | 2859 | { |
diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index c1dd9a7b48df..bfe1108416cf 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c | |||
@@ -75,7 +75,8 @@ static int snd_us428ctls_mmap(struct snd_hwdep * hw, struct file *filp, struct v | |||
75 | 75 | ||
76 | if (!us428->us428ctls_sharedmem) { | 76 | if (!us428->us428ctls_sharedmem) { |
77 | init_waitqueue_head(&us428->us428ctls_wait_queue_head); | 77 | init_waitqueue_head(&us428->us428ctls_wait_queue_head); |
78 | if(!(us428->us428ctls_sharedmem = snd_malloc_pages(sizeof(struct us428ctls_sharedmem), GFP_KERNEL))) | 78 | us428->us428ctls_sharedmem = alloc_pages_exact(sizeof(struct us428ctls_sharedmem), GFP_KERNEL); |
79 | if (!us428->us428ctls_sharedmem) | ||
79 | return -ENOMEM; | 80 | return -ENOMEM; |
80 | memset(us428->us428ctls_sharedmem, -1, sizeof(struct us428ctls_sharedmem)); | 81 | memset(us428->us428ctls_sharedmem, -1, sizeof(struct us428ctls_sharedmem)); |
81 | us428->us428ctls_sharedmem->CtlSnapShotLast = -2; | 82 | us428->us428ctls_sharedmem->CtlSnapShotLast = -2; |
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index 221adf68bd0c..51d73111263a 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c | |||
@@ -155,9 +155,9 @@ void usb_stream_free(struct usb_stream_kernel *sk) | |||
155 | if (!s) | 155 | if (!s) |
156 | return; | 156 | return; |
157 | 157 | ||
158 | free_pages((unsigned long)sk->write_page, get_order(s->write_size)); | 158 | free_pages_exact(sk->write_page, s->write_size); |
159 | sk->write_page = NULL; | 159 | sk->write_page = NULL; |
160 | free_pages((unsigned long)s, get_order(s->read_size)); | 160 | free_pages_exact(s, s->read_size); |
161 | sk->s = NULL; | 161 | sk->s = NULL; |
162 | } | 162 | } |
163 | 163 | ||
@@ -172,7 +172,6 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, | |||
172 | int read_size = sizeof(struct usb_stream); | 172 | int read_size = sizeof(struct usb_stream); |
173 | int write_size; | 173 | int write_size; |
174 | int usb_frames = dev->speed == USB_SPEED_HIGH ? 8000 : 1000; | 174 | int usb_frames = dev->speed == USB_SPEED_HIGH ? 8000 : 1000; |
175 | int pg; | ||
176 | 175 | ||
177 | in_pipe = usb_rcvisocpipe(dev, in_endpoint); | 176 | in_pipe = usb_rcvisocpipe(dev, in_endpoint); |
178 | out_pipe = usb_sndisocpipe(dev, out_endpoint); | 177 | out_pipe = usb_sndisocpipe(dev, out_endpoint); |
@@ -202,11 +201,10 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, | |||
202 | goto out; | 201 | goto out; |
203 | } | 202 | } |
204 | 203 | ||
205 | pg = get_order(read_size); | 204 | sk->s = alloc_pages_exact(read_size, |
206 | sk->s = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO| | 205 | GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN); |
207 | __GFP_NOWARN, pg); | ||
208 | if (!sk->s) { | 206 | if (!sk->s) { |
209 | snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); | 207 | pr_warn("us122l: couldn't allocate read buffer\n"); |
210 | goto out; | 208 | goto out; |
211 | } | 209 | } |
212 | sk->s->cfg.version = USB_STREAM_INTERFACE_VERSION; | 210 | sk->s->cfg.version = USB_STREAM_INTERFACE_VERSION; |
@@ -221,13 +219,11 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, | |||
221 | sk->s->period_size = frame_size * period_frames; | 219 | sk->s->period_size = frame_size * period_frames; |
222 | 220 | ||
223 | sk->s->write_size = write_size; | 221 | sk->s->write_size = write_size; |
224 | pg = get_order(write_size); | ||
225 | 222 | ||
226 | sk->write_page = | 223 | sk->write_page = alloc_pages_exact(write_size, |
227 | (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO| | 224 | GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN); |
228 | __GFP_NOWARN, pg); | ||
229 | if (!sk->write_page) { | 225 | if (!sk->write_page) { |
230 | snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); | 226 | pr_warn("us122l: couldn't allocate write buffer\n"); |
231 | usb_stream_free(sk); | 227 | usb_stream_free(sk); |
232 | return NULL; | 228 | return NULL; |
233 | } | 229 | } |
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index da4a5a541512..e8687b3bd3c8 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c | |||
@@ -293,10 +293,8 @@ int usX2Y_In04_init(struct usX2Ydev *usX2Y) | |||
293 | if (! (usX2Y->In04urb = usb_alloc_urb(0, GFP_KERNEL))) | 293 | if (! (usX2Y->In04urb = usb_alloc_urb(0, GFP_KERNEL))) |
294 | return -ENOMEM; | 294 | return -ENOMEM; |
295 | 295 | ||
296 | if (! (usX2Y->In04Buf = kmalloc(21, GFP_KERNEL))) { | 296 | if (! (usX2Y->In04Buf = kmalloc(21, GFP_KERNEL))) |
297 | usb_free_urb(usX2Y->In04urb); | ||
298 | return -ENOMEM; | 297 | return -ENOMEM; |
299 | } | ||
300 | 298 | ||
301 | init_waitqueue_head(&usX2Y->In04WaitQueue); | 299 | init_waitqueue_head(&usX2Y->In04WaitQueue); |
302 | usb_fill_int_urb(usX2Y->In04urb, usX2Y->dev, usb_rcvintpipe(usX2Y->dev, 0x4), | 300 | usb_fill_int_urb(usX2Y->In04urb, usX2Y->dev, usb_rcvintpipe(usX2Y->dev, 0x4), |
@@ -437,7 +435,8 @@ static void snd_usX2Y_card_private_free(struct snd_card *card) | |||
437 | kfree(usX2Y(card)->In04Buf); | 435 | kfree(usX2Y(card)->In04Buf); |
438 | usb_free_urb(usX2Y(card)->In04urb); | 436 | usb_free_urb(usX2Y(card)->In04urb); |
439 | if (usX2Y(card)->us428ctls_sharedmem) | 437 | if (usX2Y(card)->us428ctls_sharedmem) |
440 | snd_free_pages(usX2Y(card)->us428ctls_sharedmem, sizeof(*usX2Y(card)->us428ctls_sharedmem)); | 438 | free_pages_exact(usX2Y(card)->us428ctls_sharedmem, |
439 | sizeof(*usX2Y(card)->us428ctls_sharedmem)); | ||
441 | if (usX2Y(card)->card_index >= 0 && usX2Y(card)->card_index < SNDRV_CARDS) | 440 | if (usX2Y(card)->card_index >= 0 && usX2Y(card)->card_index < SNDRV_CARDS) |
442 | snd_usX2Y_card_used[usX2Y(card)->card_index] = 0; | 441 | snd_usX2Y_card_used[usX2Y(card)->card_index] = 0; |
443 | } | 442 | } |
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 714cf50d4a4c..ace8185c3f6d 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c | |||
@@ -488,7 +488,9 @@ static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream) | |||
488 | snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); | 488 | snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); |
489 | 489 | ||
490 | if (NULL == usX2Y->hwdep_pcm_shm) { | 490 | if (NULL == usX2Y->hwdep_pcm_shm) { |
491 | if (NULL == (usX2Y->hwdep_pcm_shm = snd_malloc_pages(sizeof(struct snd_usX2Y_hwdep_pcm_shm), GFP_KERNEL))) | 491 | usX2Y->hwdep_pcm_shm = alloc_pages_exact(sizeof(struct snd_usX2Y_hwdep_pcm_shm), |
492 | GFP_KERNEL); | ||
493 | if (!usX2Y->hwdep_pcm_shm) | ||
492 | return -ENOMEM; | 494 | return -ENOMEM; |
493 | memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); | 495 | memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); |
494 | } | 496 | } |
@@ -700,7 +702,7 @@ static void snd_usX2Y_hwdep_pcm_private_free(struct snd_hwdep *hwdep) | |||
700 | { | 702 | { |
701 | struct usX2Ydev *usX2Y = hwdep->private_data; | 703 | struct usX2Ydev *usX2Y = hwdep->private_data; |
702 | if (NULL != usX2Y->hwdep_pcm_shm) | 704 | if (NULL != usX2Y->hwdep_pcm_shm) |
703 | snd_free_pages(usX2Y->hwdep_pcm_shm, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); | 705 | free_pages_exact(usX2Y->hwdep_pcm_shm, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); |
704 | } | 706 | } |
705 | 707 | ||
706 | 708 | ||
diff --git a/sound/xen/xen_snd_front_alsa.c b/sound/xen/xen_snd_front_alsa.c index a7f413cb704d..b14ab512c2ce 100644 --- a/sound/xen/xen_snd_front_alsa.c +++ b/sound/xen/xen_snd_front_alsa.c | |||
@@ -441,7 +441,7 @@ static int shbuf_setup_backstore(struct xen_snd_front_pcm_stream_info *stream, | |||
441 | { | 441 | { |
442 | int i; | 442 | int i; |
443 | 443 | ||
444 | stream->buffer = alloc_pages_exact(stream->buffer_sz, GFP_KERNEL); | 444 | stream->buffer = alloc_pages_exact(buffer_sz, GFP_KERNEL); |
445 | if (!stream->buffer) | 445 | if (!stream->buffer) |
446 | return -ENOMEM; | 446 | return -ENOMEM; |
447 | 447 | ||