diff options
Diffstat (limited to 'sound')
43 files changed, 948 insertions, 143 deletions
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index c40ae573346d..ad11dc994792 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c | |||
@@ -100,12 +100,15 @@ static int snd_compr_open(struct inode *inode, struct file *f) | |||
100 | 100 | ||
101 | if (dirn != compr->direction) { | 101 | if (dirn != compr->direction) { |
102 | pr_err("this device doesn't support this direction\n"); | 102 | pr_err("this device doesn't support this direction\n"); |
103 | snd_card_unref(compr->card); | ||
103 | return -EINVAL; | 104 | return -EINVAL; |
104 | } | 105 | } |
105 | 106 | ||
106 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 107 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
107 | if (!data) | 108 | if (!data) { |
109 | snd_card_unref(compr->card); | ||
108 | return -ENOMEM; | 110 | return -ENOMEM; |
111 | } | ||
109 | data->stream.ops = compr->ops; | 112 | data->stream.ops = compr->ops; |
110 | data->stream.direction = dirn; | 113 | data->stream.direction = dirn; |
111 | data->stream.private_data = compr->private_data; | 114 | data->stream.private_data = compr->private_data; |
@@ -113,6 +116,7 @@ static int snd_compr_open(struct inode *inode, struct file *f) | |||
113 | runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); | 116 | runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); |
114 | if (!runtime) { | 117 | if (!runtime) { |
115 | kfree(data); | 118 | kfree(data); |
119 | snd_card_unref(compr->card); | ||
116 | return -ENOMEM; | 120 | return -ENOMEM; |
117 | } | 121 | } |
118 | runtime->state = SNDRV_PCM_STATE_OPEN; | 122 | runtime->state = SNDRV_PCM_STATE_OPEN; |
@@ -126,7 +130,8 @@ static int snd_compr_open(struct inode *inode, struct file *f) | |||
126 | kfree(runtime); | 130 | kfree(runtime); |
127 | kfree(data); | 131 | kfree(data); |
128 | } | 132 | } |
129 | return ret; | 133 | snd_card_unref(compr->card); |
134 | return 0; | ||
130 | } | 135 | } |
131 | 136 | ||
132 | static int snd_compr_free(struct inode *inode, struct file *f) | 137 | static int snd_compr_free(struct inode *inode, struct file *f) |
diff --git a/sound/core/control.c b/sound/core/control.c index 7e86a5b9f3b5..8c7c2c9bba61 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -86,6 +86,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file) | |||
86 | write_lock_irqsave(&card->ctl_files_rwlock, flags); | 86 | write_lock_irqsave(&card->ctl_files_rwlock, flags); |
87 | list_add_tail(&ctl->list, &card->ctl_files); | 87 | list_add_tail(&ctl->list, &card->ctl_files); |
88 | write_unlock_irqrestore(&card->ctl_files_rwlock, flags); | 88 | write_unlock_irqrestore(&card->ctl_files_rwlock, flags); |
89 | snd_card_unref(card); | ||
89 | return 0; | 90 | return 0; |
90 | 91 | ||
91 | __error: | 92 | __error: |
@@ -93,6 +94,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file) | |||
93 | __error2: | 94 | __error2: |
94 | snd_card_file_remove(card, file); | 95 | snd_card_file_remove(card, file); |
95 | __error1: | 96 | __error1: |
97 | if (card) | ||
98 | snd_card_unref(card); | ||
96 | return err; | 99 | return err; |
97 | } | 100 | } |
98 | 101 | ||
@@ -1434,6 +1437,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, | |||
1434 | spin_unlock_irq(&ctl->read_lock); | 1437 | spin_unlock_irq(&ctl->read_lock); |
1435 | schedule(); | 1438 | schedule(); |
1436 | remove_wait_queue(&ctl->change_sleep, &wait); | 1439 | remove_wait_queue(&ctl->change_sleep, &wait); |
1440 | if (ctl->card->shutdown) | ||
1441 | return -ENODEV; | ||
1437 | if (signal_pending(current)) | 1442 | if (signal_pending(current)) |
1438 | return -ERESTARTSYS; | 1443 | return -ERESTARTSYS; |
1439 | spin_lock_irq(&ctl->read_lock); | 1444 | spin_lock_irq(&ctl->read_lock); |
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 75ea16f35b1a..3f7f6628cf7b 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c | |||
@@ -100,8 +100,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) | |||
100 | if (hw == NULL) | 100 | if (hw == NULL) |
101 | return -ENODEV; | 101 | return -ENODEV; |
102 | 102 | ||
103 | if (!try_module_get(hw->card->module)) | 103 | if (!try_module_get(hw->card->module)) { |
104 | snd_card_unref(hw->card); | ||
104 | return -EFAULT; | 105 | return -EFAULT; |
106 | } | ||
105 | 107 | ||
106 | init_waitqueue_entry(&wait, current); | 108 | init_waitqueue_entry(&wait, current); |
107 | add_wait_queue(&hw->open_wait, &wait); | 109 | add_wait_queue(&hw->open_wait, &wait); |
@@ -129,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) | |||
129 | mutex_unlock(&hw->open_mutex); | 131 | mutex_unlock(&hw->open_mutex); |
130 | schedule(); | 132 | schedule(); |
131 | mutex_lock(&hw->open_mutex); | 133 | mutex_lock(&hw->open_mutex); |
134 | if (hw->card->shutdown) { | ||
135 | err = -ENODEV; | ||
136 | break; | ||
137 | } | ||
132 | if (signal_pending(current)) { | 138 | if (signal_pending(current)) { |
133 | err = -ERESTARTSYS; | 139 | err = -ERESTARTSYS; |
134 | break; | 140 | break; |
@@ -148,6 +154,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) | |||
148 | mutex_unlock(&hw->open_mutex); | 154 | mutex_unlock(&hw->open_mutex); |
149 | if (err < 0) | 155 | if (err < 0) |
150 | module_put(hw->card->module); | 156 | module_put(hw->card->module); |
157 | snd_card_unref(hw->card); | ||
151 | return err; | 158 | return err; |
152 | } | 159 | } |
153 | 160 | ||
@@ -459,12 +466,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device) | |||
459 | mutex_unlock(®ister_mutex); | 466 | mutex_unlock(®ister_mutex); |
460 | return -EINVAL; | 467 | return -EINVAL; |
461 | } | 468 | } |
469 | mutex_lock(&hwdep->open_mutex); | ||
470 | wake_up(&hwdep->open_wait); | ||
462 | #ifdef CONFIG_SND_OSSEMUL | 471 | #ifdef CONFIG_SND_OSSEMUL |
463 | if (hwdep->ossreg) | 472 | if (hwdep->ossreg) |
464 | snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); | 473 | snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); |
465 | #endif | 474 | #endif |
466 | snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); | 475 | snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); |
467 | list_del_init(&hwdep->list); | 476 | list_del_init(&hwdep->list); |
477 | mutex_unlock(&hwdep->open_mutex); | ||
468 | mutex_unlock(®ister_mutex); | 478 | mutex_unlock(®ister_mutex); |
469 | return 0; | 479 | return 0; |
470 | } | 480 | } |
diff --git a/sound/core/init.c b/sound/core/init.c index d8ec849af128..7b012d15c2cf 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -213,6 +213,7 @@ int snd_card_create(int idx, const char *xid, | |||
213 | spin_lock_init(&card->files_lock); | 213 | spin_lock_init(&card->files_lock); |
214 | INIT_LIST_HEAD(&card->files_list); | 214 | INIT_LIST_HEAD(&card->files_list); |
215 | init_waitqueue_head(&card->shutdown_sleep); | 215 | init_waitqueue_head(&card->shutdown_sleep); |
216 | atomic_set(&card->refcount, 0); | ||
216 | #ifdef CONFIG_PM | 217 | #ifdef CONFIG_PM |
217 | mutex_init(&card->power_lock); | 218 | mutex_init(&card->power_lock); |
218 | init_waitqueue_head(&card->power_sleep); | 219 | init_waitqueue_head(&card->power_sleep); |
@@ -446,21 +447,36 @@ static int snd_card_do_free(struct snd_card *card) | |||
446 | return 0; | 447 | return 0; |
447 | } | 448 | } |
448 | 449 | ||
450 | /** | ||
451 | * snd_card_unref - release the reference counter | ||
452 | * @card: the card instance | ||
453 | * | ||
454 | * Decrements the reference counter. When it reaches to zero, wake up | ||
455 | * the sleeper and call the destructor if needed. | ||
456 | */ | ||
457 | void snd_card_unref(struct snd_card *card) | ||
458 | { | ||
459 | if (atomic_dec_and_test(&card->refcount)) { | ||
460 | wake_up(&card->shutdown_sleep); | ||
461 | if (card->free_on_last_close) | ||
462 | snd_card_do_free(card); | ||
463 | } | ||
464 | } | ||
465 | EXPORT_SYMBOL(snd_card_unref); | ||
466 | |||
449 | int snd_card_free_when_closed(struct snd_card *card) | 467 | int snd_card_free_when_closed(struct snd_card *card) |
450 | { | 468 | { |
451 | int free_now = 0; | 469 | int ret; |
452 | int ret = snd_card_disconnect(card); | ||
453 | if (ret) | ||
454 | return ret; | ||
455 | 470 | ||
456 | spin_lock(&card->files_lock); | 471 | atomic_inc(&card->refcount); |
457 | if (list_empty(&card->files_list)) | 472 | ret = snd_card_disconnect(card); |
458 | free_now = 1; | 473 | if (ret) { |
459 | else | 474 | atomic_dec(&card->refcount); |
460 | card->free_on_last_close = 1; | 475 | return ret; |
461 | spin_unlock(&card->files_lock); | 476 | } |
462 | 477 | ||
463 | if (free_now) | 478 | card->free_on_last_close = 1; |
479 | if (atomic_dec_and_test(&card->refcount)) | ||
464 | snd_card_do_free(card); | 480 | snd_card_do_free(card); |
465 | return 0; | 481 | return 0; |
466 | } | 482 | } |
@@ -474,7 +490,7 @@ int snd_card_free(struct snd_card *card) | |||
474 | return ret; | 490 | return ret; |
475 | 491 | ||
476 | /* wait, until all devices are ready for the free operation */ | 492 | /* wait, until all devices are ready for the free operation */ |
477 | wait_event(card->shutdown_sleep, list_empty(&card->files_list)); | 493 | wait_event(card->shutdown_sleep, !atomic_read(&card->refcount)); |
478 | snd_card_do_free(card); | 494 | snd_card_do_free(card); |
479 | return 0; | 495 | return 0; |
480 | } | 496 | } |
@@ -886,6 +902,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file) | |||
886 | return -ENODEV; | 902 | return -ENODEV; |
887 | } | 903 | } |
888 | list_add(&mfile->list, &card->files_list); | 904 | list_add(&mfile->list, &card->files_list); |
905 | atomic_inc(&card->refcount); | ||
889 | spin_unlock(&card->files_lock); | 906 | spin_unlock(&card->files_lock); |
890 | return 0; | 907 | return 0; |
891 | } | 908 | } |
@@ -908,7 +925,6 @@ EXPORT_SYMBOL(snd_card_file_add); | |||
908 | int snd_card_file_remove(struct snd_card *card, struct file *file) | 925 | int snd_card_file_remove(struct snd_card *card, struct file *file) |
909 | { | 926 | { |
910 | struct snd_monitor_file *mfile, *found = NULL; | 927 | struct snd_monitor_file *mfile, *found = NULL; |
911 | int last_close = 0; | ||
912 | 928 | ||
913 | spin_lock(&card->files_lock); | 929 | spin_lock(&card->files_lock); |
914 | list_for_each_entry(mfile, &card->files_list, list) { | 930 | list_for_each_entry(mfile, &card->files_list, list) { |
@@ -923,19 +939,13 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) | |||
923 | break; | 939 | break; |
924 | } | 940 | } |
925 | } | 941 | } |
926 | if (list_empty(&card->files_list)) | ||
927 | last_close = 1; | ||
928 | spin_unlock(&card->files_lock); | 942 | spin_unlock(&card->files_lock); |
929 | if (last_close) { | ||
930 | wake_up(&card->shutdown_sleep); | ||
931 | if (card->free_on_last_close) | ||
932 | snd_card_do_free(card); | ||
933 | } | ||
934 | if (!found) { | 943 | if (!found) { |
935 | snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); | 944 | snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); |
936 | return -ENOENT; | 945 | return -ENOENT; |
937 | } | 946 | } |
938 | kfree(found); | 947 | kfree(found); |
948 | snd_card_unref(card); | ||
939 | return 0; | 949 | return 0; |
940 | } | 950 | } |
941 | 951 | ||
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 29f6ded02555..e8a1d18774b2 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c | |||
@@ -52,14 +52,19 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) | |||
52 | SNDRV_OSS_DEVICE_TYPE_MIXER); | 52 | SNDRV_OSS_DEVICE_TYPE_MIXER); |
53 | if (card == NULL) | 53 | if (card == NULL) |
54 | return -ENODEV; | 54 | return -ENODEV; |
55 | if (card->mixer_oss == NULL) | 55 | if (card->mixer_oss == NULL) { |
56 | snd_card_unref(card); | ||
56 | return -ENODEV; | 57 | return -ENODEV; |
58 | } | ||
57 | err = snd_card_file_add(card, file); | 59 | err = snd_card_file_add(card, file); |
58 | if (err < 0) | 60 | if (err < 0) { |
61 | snd_card_unref(card); | ||
59 | return err; | 62 | return err; |
63 | } | ||
60 | fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL); | 64 | fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL); |
61 | if (fmixer == NULL) { | 65 | if (fmixer == NULL) { |
62 | snd_card_file_remove(card, file); | 66 | snd_card_file_remove(card, file); |
67 | snd_card_unref(card); | ||
63 | return -ENOMEM; | 68 | return -ENOMEM; |
64 | } | 69 | } |
65 | fmixer->card = card; | 70 | fmixer->card = card; |
@@ -68,8 +73,10 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) | |||
68 | if (!try_module_get(card->module)) { | 73 | if (!try_module_get(card->module)) { |
69 | kfree(fmixer); | 74 | kfree(fmixer); |
70 | snd_card_file_remove(card, file); | 75 | snd_card_file_remove(card, file); |
76 | snd_card_unref(card); | ||
71 | return -EFAULT; | 77 | return -EFAULT; |
72 | } | 78 | } |
79 | snd_card_unref(card); | ||
73 | return 0; | 80 | return 0; |
74 | } | 81 | } |
75 | 82 | ||
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 08fde0060fd9..4c1cc51772e6 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) | |||
2441 | mutex_unlock(&pcm->open_mutex); | 2441 | mutex_unlock(&pcm->open_mutex); |
2442 | schedule(); | 2442 | schedule(); |
2443 | mutex_lock(&pcm->open_mutex); | 2443 | mutex_lock(&pcm->open_mutex); |
2444 | if (pcm->card->shutdown) { | ||
2445 | err = -ENODEV; | ||
2446 | break; | ||
2447 | } | ||
2444 | if (signal_pending(current)) { | 2448 | if (signal_pending(current)) { |
2445 | err = -ERESTARTSYS; | 2449 | err = -ERESTARTSYS; |
2446 | break; | 2450 | break; |
@@ -2450,6 +2454,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) | |||
2450 | mutex_unlock(&pcm->open_mutex); | 2454 | mutex_unlock(&pcm->open_mutex); |
2451 | if (err < 0) | 2455 | if (err < 0) |
2452 | goto __error; | 2456 | goto __error; |
2457 | snd_card_unref(pcm->card); | ||
2453 | return err; | 2458 | return err; |
2454 | 2459 | ||
2455 | __error: | 2460 | __error: |
@@ -2457,6 +2462,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) | |||
2457 | __error2: | 2462 | __error2: |
2458 | snd_card_file_remove(pcm->card, file); | 2463 | snd_card_file_remove(pcm->card, file); |
2459 | __error1: | 2464 | __error1: |
2465 | if (pcm) | ||
2466 | snd_card_unref(pcm->card); | ||
2460 | return err; | 2467 | return err; |
2461 | } | 2468 | } |
2462 | 2469 | ||
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index f2991940b271..030102caeee9 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -1086,11 +1086,19 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) | |||
1086 | if (list_empty(&pcm->list)) | 1086 | if (list_empty(&pcm->list)) |
1087 | goto unlock; | 1087 | goto unlock; |
1088 | 1088 | ||
1089 | mutex_lock(&pcm->open_mutex); | ||
1090 | wake_up(&pcm->open_wait); | ||
1089 | list_del_init(&pcm->list); | 1091 | list_del_init(&pcm->list); |
1090 | for (cidx = 0; cidx < 2; cidx++) | 1092 | for (cidx = 0; cidx < 2; cidx++) |
1091 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) | 1093 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { |
1092 | if (substream->runtime) | 1094 | snd_pcm_stream_lock_irq(substream); |
1095 | if (substream->runtime) { | ||
1093 | substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; | 1096 | substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; |
1097 | wake_up(&substream->runtime->sleep); | ||
1098 | wake_up(&substream->runtime->tsleep); | ||
1099 | } | ||
1100 | snd_pcm_stream_unlock_irq(substream); | ||
1101 | } | ||
1094 | list_for_each_entry(notify, &snd_pcm_notify_list, list) { | 1102 | list_for_each_entry(notify, &snd_pcm_notify_list, list) { |
1095 | notify->n_disconnect(pcm); | 1103 | notify->n_disconnect(pcm); |
1096 | } | 1104 | } |
@@ -1110,6 +1118,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) | |||
1110 | pcm->streams[cidx].chmap_kctl = NULL; | 1118 | pcm->streams[cidx].chmap_kctl = NULL; |
1111 | } | 1119 | } |
1112 | } | 1120 | } |
1121 | mutex_unlock(&pcm->open_mutex); | ||
1113 | unlock: | 1122 | unlock: |
1114 | mutex_unlock(®ister_mutex); | 1123 | mutex_unlock(®ister_mutex); |
1115 | return 0; | 1124 | return 0; |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 5e12e5bacbba..f9ddecf2f4cd 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime) | |||
369 | return usecs; | 369 | return usecs; |
370 | } | 370 | } |
371 | 371 | ||
372 | static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state) | ||
373 | { | ||
374 | snd_pcm_stream_lock_irq(substream); | ||
375 | if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) | ||
376 | substream->runtime->status->state = state; | ||
377 | snd_pcm_stream_unlock_irq(substream); | ||
378 | } | ||
379 | |||
372 | static int snd_pcm_hw_params(struct snd_pcm_substream *substream, | 380 | static int snd_pcm_hw_params(struct snd_pcm_substream *substream, |
373 | struct snd_pcm_hw_params *params) | 381 | struct snd_pcm_hw_params *params) |
374 | { | 382 | { |
@@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, | |||
452 | runtime->boundary *= 2; | 460 | runtime->boundary *= 2; |
453 | 461 | ||
454 | snd_pcm_timer_resolution_change(substream); | 462 | snd_pcm_timer_resolution_change(substream); |
455 | runtime->status->state = SNDRV_PCM_STATE_SETUP; | 463 | snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP); |
456 | 464 | ||
457 | if (pm_qos_request_active(&substream->latency_pm_qos_req)) | 465 | if (pm_qos_request_active(&substream->latency_pm_qos_req)) |
458 | pm_qos_remove_request(&substream->latency_pm_qos_req); | 466 | pm_qos_remove_request(&substream->latency_pm_qos_req); |
@@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, | |||
464 | /* hardware might be unusable from this time, | 472 | /* hardware might be unusable from this time, |
465 | so we force application to retry to set | 473 | so we force application to retry to set |
466 | the correct hardware parameter settings */ | 474 | the correct hardware parameter settings */ |
467 | runtime->status->state = SNDRV_PCM_STATE_OPEN; | 475 | snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); |
468 | if (substream->ops->hw_free != NULL) | 476 | if (substream->ops->hw_free != NULL) |
469 | substream->ops->hw_free(substream); | 477 | substream->ops->hw_free(substream); |
470 | return err; | 478 | return err; |
@@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) | |||
512 | return -EBADFD; | 520 | return -EBADFD; |
513 | if (substream->ops->hw_free) | 521 | if (substream->ops->hw_free) |
514 | result = substream->ops->hw_free(substream); | 522 | result = substream->ops->hw_free(substream); |
515 | runtime->status->state = SNDRV_PCM_STATE_OPEN; | 523 | snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); |
516 | pm_qos_remove_request(&substream->latency_pm_qos_req); | 524 | pm_qos_remove_request(&substream->latency_pm_qos_req); |
517 | return result; | 525 | return result; |
518 | } | 526 | } |
@@ -1320,7 +1328,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state) | |||
1320 | { | 1328 | { |
1321 | struct snd_pcm_runtime *runtime = substream->runtime; | 1329 | struct snd_pcm_runtime *runtime = substream->runtime; |
1322 | runtime->control->appl_ptr = runtime->status->hw_ptr; | 1330 | runtime->control->appl_ptr = runtime->status->hw_ptr; |
1323 | runtime->status->state = SNDRV_PCM_STATE_PREPARED; | 1331 | snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED); |
1324 | } | 1332 | } |
1325 | 1333 | ||
1326 | static struct action_ops snd_pcm_action_prepare = { | 1334 | static struct action_ops snd_pcm_action_prepare = { |
@@ -1510,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, | |||
1510 | down_read(&snd_pcm_link_rwsem); | 1518 | down_read(&snd_pcm_link_rwsem); |
1511 | snd_pcm_stream_lock_irq(substream); | 1519 | snd_pcm_stream_lock_irq(substream); |
1512 | remove_wait_queue(&to_check->sleep, &wait); | 1520 | remove_wait_queue(&to_check->sleep, &wait); |
1521 | if (card->shutdown) { | ||
1522 | result = -ENODEV; | ||
1523 | break; | ||
1524 | } | ||
1513 | if (tout == 0) { | 1525 | if (tout == 0) { |
1514 | if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) | 1526 | if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) |
1515 | result = -ESTRPIPE; | 1527 | result = -ESTRPIPE; |
@@ -1634,6 +1646,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) | |||
1634 | write_unlock_irq(&snd_pcm_link_rwlock); | 1646 | write_unlock_irq(&snd_pcm_link_rwlock); |
1635 | up_write(&snd_pcm_link_rwsem); | 1647 | up_write(&snd_pcm_link_rwsem); |
1636 | _nolock: | 1648 | _nolock: |
1649 | snd_card_unref(substream1->pcm->card); | ||
1637 | fput_light(file, fput_needed); | 1650 | fput_light(file, fput_needed); |
1638 | if (res < 0) | 1651 | if (res < 0) |
1639 | kfree(group); | 1652 | kfree(group); |
@@ -2108,7 +2121,10 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file) | |||
2108 | return err; | 2121 | return err; |
2109 | pcm = snd_lookup_minor_data(iminor(inode), | 2122 | pcm = snd_lookup_minor_data(iminor(inode), |
2110 | SNDRV_DEVICE_TYPE_PCM_PLAYBACK); | 2123 | SNDRV_DEVICE_TYPE_PCM_PLAYBACK); |
2111 | return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); | 2124 | err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); |
2125 | if (pcm) | ||
2126 | snd_card_unref(pcm->card); | ||
2127 | return err; | ||
2112 | } | 2128 | } |
2113 | 2129 | ||
2114 | static int snd_pcm_capture_open(struct inode *inode, struct file *file) | 2130 | static int snd_pcm_capture_open(struct inode *inode, struct file *file) |
@@ -2119,7 +2135,10 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) | |||
2119 | return err; | 2135 | return err; |
2120 | pcm = snd_lookup_minor_data(iminor(inode), | 2136 | pcm = snd_lookup_minor_data(iminor(inode), |
2121 | SNDRV_DEVICE_TYPE_PCM_CAPTURE); | 2137 | SNDRV_DEVICE_TYPE_PCM_CAPTURE); |
2122 | return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); | 2138 | err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); |
2139 | if (pcm) | ||
2140 | snd_card_unref(pcm->card); | ||
2141 | return err; | ||
2123 | } | 2142 | } |
2124 | 2143 | ||
2125 | static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) | 2144 | static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) |
@@ -2156,6 +2175,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) | |||
2156 | mutex_unlock(&pcm->open_mutex); | 2175 | mutex_unlock(&pcm->open_mutex); |
2157 | schedule(); | 2176 | schedule(); |
2158 | mutex_lock(&pcm->open_mutex); | 2177 | mutex_lock(&pcm->open_mutex); |
2178 | if (pcm->card->shutdown) { | ||
2179 | err = -ENODEV; | ||
2180 | break; | ||
2181 | } | ||
2159 | if (signal_pending(current)) { | 2182 | if (signal_pending(current)) { |
2160 | err = -ERESTARTSYS; | 2183 | err = -ERESTARTSYS; |
2161 | break; | 2184 | break; |
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index ebf6e49ad3d4..1bb95aeea084 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
@@ -379,8 +379,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) | |||
379 | if (rmidi == NULL) | 379 | if (rmidi == NULL) |
380 | return -ENODEV; | 380 | return -ENODEV; |
381 | 381 | ||
382 | if (!try_module_get(rmidi->card->module)) | 382 | if (!try_module_get(rmidi->card->module)) { |
383 | snd_card_unref(rmidi->card); | ||
383 | return -ENXIO; | 384 | return -ENXIO; |
385 | } | ||
384 | 386 | ||
385 | mutex_lock(&rmidi->open_mutex); | 387 | mutex_lock(&rmidi->open_mutex); |
386 | card = rmidi->card; | 388 | card = rmidi->card; |
@@ -422,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) | |||
422 | mutex_unlock(&rmidi->open_mutex); | 424 | mutex_unlock(&rmidi->open_mutex); |
423 | schedule(); | 425 | schedule(); |
424 | mutex_lock(&rmidi->open_mutex); | 426 | mutex_lock(&rmidi->open_mutex); |
427 | if (rmidi->card->shutdown) { | ||
428 | err = -ENODEV; | ||
429 | break; | ||
430 | } | ||
425 | if (signal_pending(current)) { | 431 | if (signal_pending(current)) { |
426 | err = -ERESTARTSYS; | 432 | err = -ERESTARTSYS; |
427 | break; | 433 | break; |
@@ -440,6 +446,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) | |||
440 | #endif | 446 | #endif |
441 | file->private_data = rawmidi_file; | 447 | file->private_data = rawmidi_file; |
442 | mutex_unlock(&rmidi->open_mutex); | 448 | mutex_unlock(&rmidi->open_mutex); |
449 | snd_card_unref(rmidi->card); | ||
443 | return 0; | 450 | return 0; |
444 | 451 | ||
445 | __error: | 452 | __error: |
@@ -447,6 +454,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) | |||
447 | __error_card: | 454 | __error_card: |
448 | mutex_unlock(&rmidi->open_mutex); | 455 | mutex_unlock(&rmidi->open_mutex); |
449 | module_put(rmidi->card->module); | 456 | module_put(rmidi->card->module); |
457 | snd_card_unref(rmidi->card); | ||
450 | return err; | 458 | return err; |
451 | } | 459 | } |
452 | 460 | ||
@@ -991,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun | |||
991 | spin_unlock_irq(&runtime->lock); | 999 | spin_unlock_irq(&runtime->lock); |
992 | schedule(); | 1000 | schedule(); |
993 | remove_wait_queue(&runtime->sleep, &wait); | 1001 | remove_wait_queue(&runtime->sleep, &wait); |
1002 | if (rfile->rmidi->card->shutdown) | ||
1003 | return -ENODEV; | ||
994 | if (signal_pending(current)) | 1004 | if (signal_pending(current)) |
995 | return result > 0 ? result : -ERESTARTSYS; | 1005 | return result > 0 ? result : -ERESTARTSYS; |
996 | if (!runtime->avail) | 1006 | if (!runtime->avail) |
@@ -1234,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, | |||
1234 | spin_unlock_irq(&runtime->lock); | 1244 | spin_unlock_irq(&runtime->lock); |
1235 | timeout = schedule_timeout(30 * HZ); | 1245 | timeout = schedule_timeout(30 * HZ); |
1236 | remove_wait_queue(&runtime->sleep, &wait); | 1246 | remove_wait_queue(&runtime->sleep, &wait); |
1247 | if (rfile->rmidi->card->shutdown) | ||
1248 | return -ENODEV; | ||
1237 | if (signal_pending(current)) | 1249 | if (signal_pending(current)) |
1238 | return result > 0 ? result : -ERESTARTSYS; | 1250 | return result > 0 ? result : -ERESTARTSYS; |
1239 | if (!runtime->avail && !timeout) | 1251 | if (!runtime->avail && !timeout) |
@@ -1609,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device) | |||
1609 | static int snd_rawmidi_dev_disconnect(struct snd_device *device) | 1621 | static int snd_rawmidi_dev_disconnect(struct snd_device *device) |
1610 | { | 1622 | { |
1611 | struct snd_rawmidi *rmidi = device->device_data; | 1623 | struct snd_rawmidi *rmidi = device->device_data; |
1624 | int dir; | ||
1612 | 1625 | ||
1613 | mutex_lock(®ister_mutex); | 1626 | mutex_lock(®ister_mutex); |
1627 | mutex_lock(&rmidi->open_mutex); | ||
1628 | wake_up(&rmidi->open_wait); | ||
1614 | list_del_init(&rmidi->list); | 1629 | list_del_init(&rmidi->list); |
1630 | for (dir = 0; dir < 2; dir++) { | ||
1631 | struct snd_rawmidi_substream *s; | ||
1632 | list_for_each_entry(s, &rmidi->streams[dir].substreams, list) { | ||
1633 | if (s->runtime) | ||
1634 | wake_up(&s->runtime->sleep); | ||
1635 | } | ||
1636 | } | ||
1637 | |||
1615 | #ifdef CONFIG_SND_OSSEMUL | 1638 | #ifdef CONFIG_SND_OSSEMUL |
1616 | if (rmidi->ossreg) { | 1639 | if (rmidi->ossreg) { |
1617 | if ((int)rmidi->device == midi_map[rmidi->card->number]) { | 1640 | if ((int)rmidi->device == midi_map[rmidi->card->number]) { |
@@ -1626,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) | |||
1626 | } | 1649 | } |
1627 | #endif /* CONFIG_SND_OSSEMUL */ | 1650 | #endif /* CONFIG_SND_OSSEMUL */ |
1628 | snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); | 1651 | snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); |
1652 | mutex_unlock(&rmidi->open_mutex); | ||
1629 | mutex_unlock(®ister_mutex); | 1653 | mutex_unlock(®ister_mutex); |
1630 | return 0; | 1654 | return 0; |
1631 | } | 1655 | } |
diff --git a/sound/core/sound.c b/sound/core/sound.c index 643976000ce8..70ccdab74153 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c | |||
@@ -98,6 +98,10 @@ static void snd_request_other(int minor) | |||
98 | * | 98 | * |
99 | * Checks that a minor device with the specified type is registered, and returns | 99 | * Checks that a minor device with the specified type is registered, and returns |
100 | * its user data pointer. | 100 | * its user data pointer. |
101 | * | ||
102 | * This function increments the reference counter of the card instance | ||
103 | * if an associated instance with the given minor number and type is found. | ||
104 | * The caller must call snd_card_unref() appropriately later. | ||
101 | */ | 105 | */ |
102 | void *snd_lookup_minor_data(unsigned int minor, int type) | 106 | void *snd_lookup_minor_data(unsigned int minor, int type) |
103 | { | 107 | { |
@@ -108,9 +112,11 @@ void *snd_lookup_minor_data(unsigned int minor, int type) | |||
108 | return NULL; | 112 | return NULL; |
109 | mutex_lock(&sound_mutex); | 113 | mutex_lock(&sound_mutex); |
110 | mreg = snd_minors[minor]; | 114 | mreg = snd_minors[minor]; |
111 | if (mreg && mreg->type == type) | 115 | if (mreg && mreg->type == type) { |
112 | private_data = mreg->private_data; | 116 | private_data = mreg->private_data; |
113 | else | 117 | if (private_data && mreg->card_ptr) |
118 | atomic_inc(&mreg->card_ptr->refcount); | ||
119 | } else | ||
114 | private_data = NULL; | 120 | private_data = NULL; |
115 | mutex_unlock(&sound_mutex); | 121 | mutex_unlock(&sound_mutex); |
116 | return private_data; | 122 | return private_data; |
@@ -275,6 +281,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev, | |||
275 | preg->device = dev; | 281 | preg->device = dev; |
276 | preg->f_ops = f_ops; | 282 | preg->f_ops = f_ops; |
277 | preg->private_data = private_data; | 283 | preg->private_data = private_data; |
284 | preg->card_ptr = card; | ||
278 | mutex_lock(&sound_mutex); | 285 | mutex_lock(&sound_mutex); |
279 | #ifdef CONFIG_SND_DYNAMIC_MINORS | 286 | #ifdef CONFIG_SND_DYNAMIC_MINORS |
280 | minor = snd_find_free_minor(type); | 287 | minor = snd_find_free_minor(type); |
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index e9528333e36d..726a49ac9725 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c | |||
@@ -40,6 +40,9 @@ | |||
40 | static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS]; | 40 | static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS]; |
41 | static DEFINE_MUTEX(sound_oss_mutex); | 41 | static DEFINE_MUTEX(sound_oss_mutex); |
42 | 42 | ||
43 | /* NOTE: This function increments the refcount of the associated card like | ||
44 | * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately | ||
45 | */ | ||
43 | void *snd_lookup_oss_minor_data(unsigned int minor, int type) | 46 | void *snd_lookup_oss_minor_data(unsigned int minor, int type) |
44 | { | 47 | { |
45 | struct snd_minor *mreg; | 48 | struct snd_minor *mreg; |
@@ -49,9 +52,11 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) | |||
49 | return NULL; | 52 | return NULL; |
50 | mutex_lock(&sound_oss_mutex); | 53 | mutex_lock(&sound_oss_mutex); |
51 | mreg = snd_oss_minors[minor]; | 54 | mreg = snd_oss_minors[minor]; |
52 | if (mreg && mreg->type == type) | 55 | if (mreg && mreg->type == type) { |
53 | private_data = mreg->private_data; | 56 | private_data = mreg->private_data; |
54 | else | 57 | if (private_data && mreg->card_ptr) |
58 | atomic_inc(&mreg->card_ptr->refcount); | ||
59 | } else | ||
55 | private_data = NULL; | 60 | private_data = NULL; |
56 | mutex_unlock(&sound_oss_mutex); | 61 | mutex_unlock(&sound_oss_mutex); |
57 | return private_data; | 62 | return private_data; |
@@ -123,6 +128,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, | |||
123 | preg->device = dev; | 128 | preg->device = dev; |
124 | preg->f_ops = f_ops; | 129 | preg->f_ops = f_ops; |
125 | preg->private_data = private_data; | 130 | preg->private_data = private_data; |
131 | preg->card_ptr = card; | ||
126 | mutex_lock(&sound_oss_mutex); | 132 | mutex_lock(&sound_oss_mutex); |
127 | snd_oss_minors[minor] = preg; | 133 | snd_oss_minors[minor] = preg; |
128 | minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); | 134 | minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); |
diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c index ef68d710d08c..e04e750a77ed 100644 --- a/sound/i2c/other/ak4113.c +++ b/sound/i2c/other/ak4113.c | |||
@@ -426,7 +426,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = { | |||
426 | }, | 426 | }, |
427 | { | 427 | { |
428 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 428 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
429 | .name = "IEC958 Preample Capture Default", | 429 | .name = "IEC958 Preamble Capture Default", |
430 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | 430 | .access = SNDRV_CTL_ELEM_ACCESS_READ | |
431 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 431 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
432 | .info = snd_ak4113_spdif_pinfo, | 432 | .info = snd_ak4113_spdif_pinfo, |
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index 816e7d225fb0..5bf4fca19e48 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c | |||
@@ -401,7 +401,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { | |||
401 | }, | 401 | }, |
402 | { | 402 | { |
403 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 403 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
404 | .name = "IEC958 Preample Capture Default", | 404 | .name = "IEC958 Preamble Capture Default", |
405 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 405 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
406 | .info = snd_ak4114_spdif_pinfo, | 406 | .info = snd_ak4114_spdif_pinfo, |
407 | .get = snd_ak4114_spdif_pget, | 407 | .get = snd_ak4114_spdif_pget, |
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index b4b2a51fc117..40e33c9f2b09 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c | |||
@@ -380,7 +380,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = { | |||
380 | }, | 380 | }, |
381 | { | 381 | { |
382 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 382 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
383 | .name = "IEC958 Preample Capture Default", | 383 | .name = "IEC958 Preamble Capture Default", |
384 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 384 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
385 | .info = snd_ak4117_spdif_pinfo, | 385 | .info = snd_ak4117_spdif_pinfo, |
386 | .get = snd_ak4117_spdif_pget, | 386 | .get = snd_ak4117_spdif_pget, |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 5d0e568fdea1..50169bcfd903 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -2655,6 +2655,8 @@ static struct ess_device_list pm_whitelist[] __devinitdata = { | |||
2655 | { TYPE_MAESTRO2E, 0x1179 }, | 2655 | { TYPE_MAESTRO2E, 0x1179 }, |
2656 | { TYPE_MAESTRO2E, 0x14c0 }, /* HP omnibook 4150 */ | 2656 | { TYPE_MAESTRO2E, 0x14c0 }, /* HP omnibook 4150 */ |
2657 | { TYPE_MAESTRO2E, 0x1558 }, | 2657 | { TYPE_MAESTRO2E, 0x1558 }, |
2658 | { TYPE_MAESTRO2E, 0x125d }, /* a PCI card, e.g. Terratec DMX */ | ||
2659 | { TYPE_MAESTRO2, 0x125d }, /* a PCI card, e.g. SF64-PCE2 */ | ||
2658 | }; | 2660 | }; |
2659 | 2661 | ||
2660 | static struct ess_device_list mpu_blacklist[] __devinitdata = { | 2662 | static struct ess_device_list mpu_blacklist[] __devinitdata = { |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 72b085ae7d46..cd2dbaf1be78 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -3563,6 +3563,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
3563 | /* Teradici */ | 3563 | /* Teradici */ |
3564 | { PCI_DEVICE(0x6549, 0x1200), | 3564 | { PCI_DEVICE(0x6549, 0x1200), |
3565 | .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT }, | 3565 | .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT }, |
3566 | { PCI_DEVICE(0x6549, 0x2200), | ||
3567 | .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT }, | ||
3566 | /* Creative X-Fi (CA0110-IBG) */ | 3568 | /* Creative X-Fi (CA0110-IBG) */ |
3567 | /* CTHDA chips */ | 3569 | /* CTHDA chips */ |
3568 | { PCI_DEVICE(0x1102, 0x0010), | 3570 | { PCI_DEVICE(0x1102, 0x0010), |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index cdd43eadbc67..1eeba7386666 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -545,6 +545,7 @@ static int ad198x_build_pcms(struct hda_codec *codec) | |||
545 | if (spec->multiout.dig_out_nid) { | 545 | if (spec->multiout.dig_out_nid) { |
546 | info++; | 546 | info++; |
547 | codec->num_pcms++; | 547 | codec->num_pcms++; |
548 | codec->spdif_status_reset = 1; | ||
548 | info->name = "AD198x Digital"; | 549 | info->name = "AD198x Digital"; |
549 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | 550 | info->pcm_type = HDA_PCM_TYPE_SPDIF; |
550 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; | 551 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 61a71131711c..d5f3a26d608d 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -101,8 +101,8 @@ enum { | |||
101 | #define CS420X_VENDOR_NID 0x11 | 101 | #define CS420X_VENDOR_NID 0x11 |
102 | #define CS_DIG_OUT1_PIN_NID 0x10 | 102 | #define CS_DIG_OUT1_PIN_NID 0x10 |
103 | #define CS_DIG_OUT2_PIN_NID 0x15 | 103 | #define CS_DIG_OUT2_PIN_NID 0x15 |
104 | #define CS_DMIC1_PIN_NID 0x12 | 104 | #define CS_DMIC1_PIN_NID 0x0e |
105 | #define CS_DMIC2_PIN_NID 0x0e | 105 | #define CS_DMIC2_PIN_NID 0x12 |
106 | 106 | ||
107 | /* coef indices */ | 107 | /* coef indices */ |
108 | #define IDX_SPDIF_STAT 0x0000 | 108 | #define IDX_SPDIF_STAT 0x0000 |
@@ -1079,14 +1079,18 @@ static void init_input(struct hda_codec *codec) | |||
1079 | cs_automic(codec, NULL); | 1079 | cs_automic(codec, NULL); |
1080 | 1080 | ||
1081 | coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ | 1081 | coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ |
1082 | cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); | ||
1083 | |||
1084 | coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG); | ||
1082 | if (is_active_pin(codec, CS_DMIC2_PIN_NID)) | 1085 | if (is_active_pin(codec, CS_DMIC2_PIN_NID)) |
1083 | coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */ | 1086 | coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */ |
1084 | if (is_active_pin(codec, CS_DMIC1_PIN_NID)) | 1087 | if (is_active_pin(codec, CS_DMIC1_PIN_NID)) |
1085 | coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off | 1088 | coef |= 1 << 3; /* DMIC1 2 chan on, GPIO0 off |
1086 | * No effect if SPDIF_OUT2 is | 1089 | * No effect if SPDIF_OUT2 is |
1087 | * selected in IDX_SPDIF_CTL. | 1090 | * selected in IDX_SPDIF_CTL. |
1088 | */ | 1091 | */ |
1089 | cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); | 1092 | |
1093 | cs_vendor_coef_set(codec, IDX_BEEP_CFG, coef); | ||
1090 | } else { | 1094 | } else { |
1091 | if (spec->mic_detect) | 1095 | if (spec->mic_detect) |
1092 | cs_automic(codec, NULL); | 1096 | cs_automic(codec, NULL); |
@@ -1107,7 +1111,7 @@ static const struct hda_verb cs_coef_init_verbs[] = { | |||
1107 | | 0x0400 /* Disable Coefficient Auto increment */ | 1111 | | 0x0400 /* Disable Coefficient Auto increment */ |
1108 | )}, | 1112 | )}, |
1109 | /* Beep */ | 1113 | /* Beep */ |
1110 | {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG}, | 1114 | {0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG}, |
1111 | {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */ | 1115 | {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */ |
1112 | 1116 | ||
1113 | {} /* terminator */ | 1117 | {} /* terminator */ |
@@ -1728,8 +1732,7 @@ static int cs421x_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
1728 | 1732 | ||
1729 | } | 1733 | } |
1730 | 1734 | ||
1731 | static struct snd_kcontrol_new cs421x_capture_source = { | 1735 | static const struct snd_kcontrol_new cs421x_capture_source = { |
1732 | |||
1733 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1736 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1734 | .name = "Capture Source", | 1737 | .name = "Capture Source", |
1735 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 1738 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
@@ -1946,7 +1949,7 @@ static int cs421x_suspend(struct hda_codec *codec) | |||
1946 | } | 1949 | } |
1947 | #endif | 1950 | #endif |
1948 | 1951 | ||
1949 | static struct hda_codec_ops cs421x_patch_ops = { | 1952 | static const struct hda_codec_ops cs421x_patch_ops = { |
1950 | .build_controls = cs421x_build_controls, | 1953 | .build_controls = cs421x_build_controls, |
1951 | .build_pcms = cs_build_pcms, | 1954 | .build_pcms = cs_build_pcms, |
1952 | .init = cs421x_init, | 1955 | .init = cs421x_init, |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f7397ad02a0d..c0ce3b1f04b4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -5840,7 +5840,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
5840 | return alc_parse_auto_config(codec, alc269_ignore, ssids); | 5840 | return alc_parse_auto_config(codec, alc269_ignore, ssids); |
5841 | } | 5841 | } |
5842 | 5842 | ||
5843 | static void alc269_toggle_power_output(struct hda_codec *codec, int power_up) | 5843 | static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up) |
5844 | { | 5844 | { |
5845 | int val = alc_read_coef_idx(codec, 0x04); | 5845 | int val = alc_read_coef_idx(codec, 0x04); |
5846 | if (power_up) | 5846 | if (power_up) |
@@ -5857,10 +5857,10 @@ static void alc269_shutup(struct hda_codec *codec) | |||
5857 | if (spec->codec_variant != ALC269_TYPE_ALC269VB) | 5857 | if (spec->codec_variant != ALC269_TYPE_ALC269VB) |
5858 | return; | 5858 | return; |
5859 | 5859 | ||
5860 | if ((alc_get_coef0(codec) & 0x00ff) == 0x017) | 5860 | if (spec->codec_variant == ALC269_TYPE_ALC269VB) |
5861 | alc269_toggle_power_output(codec, 0); | 5861 | alc269vb_toggle_power_output(codec, 0); |
5862 | if ((alc_get_coef0(codec) & 0x00ff) == 0x018) { | 5862 | if (spec->codec_variant == ALC269_TYPE_ALC269VB && |
5863 | alc269_toggle_power_output(codec, 0); | 5863 | (alc_get_coef0(codec) & 0x00ff) == 0x018) { |
5864 | msleep(150); | 5864 | msleep(150); |
5865 | } | 5865 | } |
5866 | } | 5866 | } |
@@ -5870,24 +5870,22 @@ static int alc269_resume(struct hda_codec *codec) | |||
5870 | { | 5870 | { |
5871 | struct alc_spec *spec = codec->spec; | 5871 | struct alc_spec *spec = codec->spec; |
5872 | 5872 | ||
5873 | if (spec->codec_variant == ALC269_TYPE_ALC269VB || | 5873 | if (spec->codec_variant == ALC269_TYPE_ALC269VB) |
5874 | alc269vb_toggle_power_output(codec, 0); | ||
5875 | if (spec->codec_variant == ALC269_TYPE_ALC269VB && | ||
5874 | (alc_get_coef0(codec) & 0x00ff) == 0x018) { | 5876 | (alc_get_coef0(codec) & 0x00ff) == 0x018) { |
5875 | alc269_toggle_power_output(codec, 0); | ||
5876 | msleep(150); | 5877 | msleep(150); |
5877 | } | 5878 | } |
5878 | 5879 | ||
5879 | codec->patch_ops.init(codec); | 5880 | codec->patch_ops.init(codec); |
5880 | 5881 | ||
5881 | if (spec->codec_variant == ALC269_TYPE_ALC269VB || | 5882 | if (spec->codec_variant == ALC269_TYPE_ALC269VB) |
5883 | alc269vb_toggle_power_output(codec, 1); | ||
5884 | if (spec->codec_variant == ALC269_TYPE_ALC269VB && | ||
5882 | (alc_get_coef0(codec) & 0x00ff) == 0x017) { | 5885 | (alc_get_coef0(codec) & 0x00ff) == 0x017) { |
5883 | alc269_toggle_power_output(codec, 1); | ||
5884 | msleep(200); | 5886 | msleep(200); |
5885 | } | 5887 | } |
5886 | 5888 | ||
5887 | if (spec->codec_variant == ALC269_TYPE_ALC269VB || | ||
5888 | (alc_get_coef0(codec) & 0x00ff) == 0x018) | ||
5889 | alc269_toggle_power_output(codec, 1); | ||
5890 | |||
5891 | snd_hda_codec_resume_amp(codec); | 5889 | snd_hda_codec_resume_amp(codec); |
5892 | snd_hda_codec_resume_cache(codec); | 5890 | snd_hda_codec_resume_cache(codec); |
5893 | hda_call_check_power_status(codec, 0x01); | 5891 | hda_call_check_power_status(codec, 0x01); |
@@ -7079,6 +7077,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { | |||
7079 | .patch = patch_alc662 }, | 7077 | .patch = patch_alc662 }, |
7080 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, | 7078 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, |
7081 | { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, | 7079 | { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, |
7080 | { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 }, | ||
7082 | { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, | 7081 | { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, |
7083 | { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 }, | 7082 | { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 }, |
7084 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, | 7083 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, |
@@ -7096,6 +7095,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { | |||
7096 | { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 }, | 7095 | { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 }, |
7097 | { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 }, | 7096 | { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 }, |
7098 | { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 }, | 7097 | { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 }, |
7098 | { .id = 0x10ec0900, .name = "ALC1150", .patch = patch_alc882 }, | ||
7099 | {} /* terminator */ | 7099 | {} /* terminator */ |
7100 | }; | 7100 | }; |
7101 | 7101 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 770013ff556f..9ba8af056170 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -1763,6 +1763,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | |||
1763 | "HP", STAC_HP_ZEPHYR), | 1763 | "HP", STAC_HP_ZEPHYR), |
1764 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660, | 1764 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660, |
1765 | "HP Mini", STAC_92HD83XXX_HP_LED), | 1765 | "HP Mini", STAC_92HD83XXX_HP_LED), |
1766 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x144E, | ||
1767 | "HP Pavilion dv5", STAC_92HD83XXX_HP_INV_LED), | ||
1766 | {} /* terminator */ | 1768 | {} /* terminator */ |
1767 | }; | 1769 | }; |
1768 | 1770 | ||
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 72a2f60b087c..019e1a00414a 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -1809,11 +1809,11 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec) | |||
1809 | { | 1809 | { |
1810 | struct via_spec *spec = codec->spec; | 1810 | struct via_spec *spec = codec->spec; |
1811 | const struct auto_pin_cfg *cfg = &spec->autocfg; | 1811 | const struct auto_pin_cfg *cfg = &spec->autocfg; |
1812 | int i, dac_num; | 1812 | int i; |
1813 | hda_nid_t nid; | 1813 | hda_nid_t nid; |
1814 | 1814 | ||
1815 | spec->multiout.num_dacs = 0; | ||
1815 | spec->multiout.dac_nids = spec->private_dac_nids; | 1816 | spec->multiout.dac_nids = spec->private_dac_nids; |
1816 | dac_num = 0; | ||
1817 | for (i = 0; i < cfg->line_outs; i++) { | 1817 | for (i = 0; i < cfg->line_outs; i++) { |
1818 | hda_nid_t dac = 0; | 1818 | hda_nid_t dac = 0; |
1819 | nid = cfg->line_out_pins[i]; | 1819 | nid = cfg->line_out_pins[i]; |
@@ -1824,16 +1824,13 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec) | |||
1824 | if (!i && parse_output_path(codec, nid, dac, 1, | 1824 | if (!i && parse_output_path(codec, nid, dac, 1, |
1825 | &spec->out_mix_path)) | 1825 | &spec->out_mix_path)) |
1826 | dac = spec->out_mix_path.path[0]; | 1826 | dac = spec->out_mix_path.path[0]; |
1827 | if (dac) { | 1827 | if (dac) |
1828 | spec->private_dac_nids[i] = dac; | 1828 | spec->private_dac_nids[spec->multiout.num_dacs++] = dac; |
1829 | dac_num++; | ||
1830 | } | ||
1831 | } | 1829 | } |
1832 | if (!spec->out_path[0].depth && spec->out_mix_path.depth) { | 1830 | if (!spec->out_path[0].depth && spec->out_mix_path.depth) { |
1833 | spec->out_path[0] = spec->out_mix_path; | 1831 | spec->out_path[0] = spec->out_mix_path; |
1834 | spec->out_mix_path.depth = 0; | 1832 | spec->out_mix_path.depth = 0; |
1835 | } | 1833 | } |
1836 | spec->multiout.num_dacs = dac_num; | ||
1837 | return 0; | 1834 | return 0; |
1838 | } | 1835 | } |
1839 | 1836 | ||
@@ -3628,6 +3625,7 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec) | |||
3628 | */ | 3625 | */ |
3629 | enum { | 3626 | enum { |
3630 | VIA_FIXUP_INTMIC_BOOST, | 3627 | VIA_FIXUP_INTMIC_BOOST, |
3628 | VIA_FIXUP_ASUS_G75, | ||
3631 | }; | 3629 | }; |
3632 | 3630 | ||
3633 | static void via_fixup_intmic_boost(struct hda_codec *codec, | 3631 | static void via_fixup_intmic_boost(struct hda_codec *codec, |
@@ -3642,13 +3640,35 @@ static const struct hda_fixup via_fixups[] = { | |||
3642 | .type = HDA_FIXUP_FUNC, | 3640 | .type = HDA_FIXUP_FUNC, |
3643 | .v.func = via_fixup_intmic_boost, | 3641 | .v.func = via_fixup_intmic_boost, |
3644 | }, | 3642 | }, |
3643 | [VIA_FIXUP_ASUS_G75] = { | ||
3644 | .type = HDA_FIXUP_PINS, | ||
3645 | .v.pins = (const struct hda_pintbl[]) { | ||
3646 | /* set 0x24 and 0x33 as speakers */ | ||
3647 | { 0x24, 0x991301f0 }, | ||
3648 | { 0x33, 0x991301f1 }, /* subwoofer */ | ||
3649 | { } | ||
3650 | } | ||
3651 | }, | ||
3645 | }; | 3652 | }; |
3646 | 3653 | ||
3647 | static const struct snd_pci_quirk vt2002p_fixups[] = { | 3654 | static const struct snd_pci_quirk vt2002p_fixups[] = { |
3655 | SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75), | ||
3648 | SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST), | 3656 | SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST), |
3649 | {} | 3657 | {} |
3650 | }; | 3658 | }; |
3651 | 3659 | ||
3660 | /* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e | ||
3661 | * Replace this with mixer NID 0x1c | ||
3662 | */ | ||
3663 | static void fix_vt1802_connections(struct hda_codec *codec) | ||
3664 | { | ||
3665 | static hda_nid_t conn_24[] = { 0x14, 0x1c }; | ||
3666 | static hda_nid_t conn_33[] = { 0x1c }; | ||
3667 | |||
3668 | snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24); | ||
3669 | snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33); | ||
3670 | } | ||
3671 | |||
3652 | /* patch for vt2002P */ | 3672 | /* patch for vt2002P */ |
3653 | static int patch_vt2002P(struct hda_codec *codec) | 3673 | static int patch_vt2002P(struct hda_codec *codec) |
3654 | { | 3674 | { |
@@ -3663,6 +3683,8 @@ static int patch_vt2002P(struct hda_codec *codec) | |||
3663 | spec->aa_mix_nid = 0x21; | 3683 | spec->aa_mix_nid = 0x21; |
3664 | override_mic_boost(codec, 0x2b, 0, 3, 40); | 3684 | override_mic_boost(codec, 0x2b, 0, 3, 40); |
3665 | override_mic_boost(codec, 0x29, 0, 3, 40); | 3685 | override_mic_boost(codec, 0x29, 0, 3, 40); |
3686 | if (spec->codec_type == VT1802) | ||
3687 | fix_vt1802_connections(codec); | ||
3666 | add_secret_dac_path(codec); | 3688 | add_secret_dac_path(codec); |
3667 | 3689 | ||
3668 | snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups); | 3690 | snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups); |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 3050a5279253..245d874891ba 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -2859,7 +2859,12 @@ static int snd_vt1724_resume(struct device *dev) | |||
2859 | ice->set_spdif_clock(ice, 0); | 2859 | ice->set_spdif_clock(ice, 0); |
2860 | } else { | 2860 | } else { |
2861 | /* internal on-card clock */ | 2861 | /* internal on-card clock */ |
2862 | snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); | 2862 | int rate; |
2863 | if (ice->cur_rate) | ||
2864 | rate = ice->cur_rate; | ||
2865 | else | ||
2866 | rate = ice->pro_rate_default; | ||
2867 | snd_vt1724_set_pro_rate(ice, rate, 1); | ||
2863 | } | 2868 | } |
2864 | 2869 | ||
2865 | update_spdif_bits(ice, ice->pm_saved_spdif_ctrl); | 2870 | update_spdif_bits(ice, ice->pm_saved_spdif_ctrl); |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index f1cd1e387801..748e36c66603 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -3979,7 +3979,8 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol, | |||
3979 | case 8: /* SYNC IN */ | 3979 | case 8: /* SYNC IN */ |
3980 | val = hdspm_sync_in_sync_check(hdspm); break; | 3980 | val = hdspm_sync_in_sync_check(hdspm); break; |
3981 | default: | 3981 | default: |
3982 | val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1); | 3982 | val = hdspm_s1_sync_check(hdspm, |
3983 | kcontrol->private_value-1); | ||
3983 | } | 3984 | } |
3984 | break; | 3985 | break; |
3985 | 3986 | ||
@@ -4899,7 +4900,7 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
4899 | insel = "Coaxial"; | 4900 | insel = "Coaxial"; |
4900 | break; | 4901 | break; |
4901 | default: | 4902 | default: |
4902 | insel = "Unkown"; | 4903 | insel = "Unknown"; |
4903 | } | 4904 | } |
4904 | 4905 | ||
4905 | snd_iprintf(buffer, | 4906 | snd_iprintf(buffer, |
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 61599298fb26..97a81051e88d 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
@@ -763,7 +763,7 @@ static int cs42l52_set_sysclk(struct snd_soc_dai *codec_dai, | |||
763 | if ((freq >= CS42L52_MIN_CLK) && (freq <= CS42L52_MAX_CLK)) { | 763 | if ((freq >= CS42L52_MIN_CLK) && (freq <= CS42L52_MAX_CLK)) { |
764 | cs42l52->sysclk = freq; | 764 | cs42l52->sysclk = freq; |
765 | } else { | 765 | } else { |
766 | dev_err(codec->dev, "Invalid freq paramter\n"); | 766 | dev_err(codec->dev, "Invalid freq parameter\n"); |
767 | return -EINVAL; | 767 | return -EINVAL; |
768 | } | 768 | } |
769 | return 0; | 769 | return 0; |
@@ -773,7 +773,6 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | |||
773 | { | 773 | { |
774 | struct snd_soc_codec *codec = codec_dai->codec; | 774 | struct snd_soc_codec *codec = codec_dai->codec; |
775 | struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec); | 775 | struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec); |
776 | int ret = 0; | ||
777 | u8 iface = 0; | 776 | u8 iface = 0; |
778 | 777 | ||
779 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 778 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
@@ -822,7 +821,7 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | |||
822 | case SND_SOC_DAIFMT_NB_IF: | 821 | case SND_SOC_DAIFMT_NB_IF: |
823 | break; | 822 | break; |
824 | default: | 823 | default: |
825 | ret = -EINVAL; | 824 | return -EINVAL; |
826 | } | 825 | } |
827 | cs42l52->config.format = iface; | 826 | cs42l52->config.format = iface; |
828 | snd_soc_write(codec, CS42L52_IFACE_CTL1, cs42l52->config.format); | 827 | snd_soc_write(codec, CS42L52_IFACE_CTL1, cs42l52->config.format); |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 1722b586bdba..7394e73fa43c 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -42,6 +42,556 @@ static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | |||
42 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); | 42 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); |
43 | static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); | 43 | static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); |
44 | 44 | ||
45 | static const struct reg_default wm5102_sysclk_reva_patch[] = { | ||
46 | { 0x3000, 0x2225 }, | ||
47 | { 0x3001, 0x3a03 }, | ||
48 | { 0x3002, 0x0225 }, | ||
49 | { 0x3003, 0x0801 }, | ||
50 | { 0x3004, 0x6249 }, | ||
51 | { 0x3005, 0x0c04 }, | ||
52 | { 0x3006, 0x0225 }, | ||
53 | { 0x3007, 0x5901 }, | ||
54 | { 0x3008, 0xe249 }, | ||
55 | { 0x3009, 0x030d }, | ||
56 | { 0x300a, 0x0249 }, | ||
57 | { 0x300b, 0x2c01 }, | ||
58 | { 0x300c, 0xe249 }, | ||
59 | { 0x300d, 0x4342 }, | ||
60 | { 0x300e, 0xe249 }, | ||
61 | { 0x300f, 0x73c0 }, | ||
62 | { 0x3010, 0x4249 }, | ||
63 | { 0x3011, 0x0c00 }, | ||
64 | { 0x3012, 0x0225 }, | ||
65 | { 0x3013, 0x1f01 }, | ||
66 | { 0x3014, 0x0225 }, | ||
67 | { 0x3015, 0x1e01 }, | ||
68 | { 0x3016, 0x0225 }, | ||
69 | { 0x3017, 0xfa00 }, | ||
70 | { 0x3018, 0x0000 }, | ||
71 | { 0x3019, 0xf000 }, | ||
72 | { 0x301a, 0x0000 }, | ||
73 | { 0x301b, 0xf000 }, | ||
74 | { 0x301c, 0x0000 }, | ||
75 | { 0x301d, 0xf000 }, | ||
76 | { 0x301e, 0x0000 }, | ||
77 | { 0x301f, 0xf000 }, | ||
78 | { 0x3020, 0x0000 }, | ||
79 | { 0x3021, 0xf000 }, | ||
80 | { 0x3022, 0x0000 }, | ||
81 | { 0x3023, 0xf000 }, | ||
82 | { 0x3024, 0x0000 }, | ||
83 | { 0x3025, 0xf000 }, | ||
84 | { 0x3026, 0x0000 }, | ||
85 | { 0x3027, 0xf000 }, | ||
86 | { 0x3028, 0x0000 }, | ||
87 | { 0x3029, 0xf000 }, | ||
88 | { 0x302a, 0x0000 }, | ||
89 | { 0x302b, 0xf000 }, | ||
90 | { 0x302c, 0x0000 }, | ||
91 | { 0x302d, 0xf000 }, | ||
92 | { 0x302e, 0x0000 }, | ||
93 | { 0x302f, 0xf000 }, | ||
94 | { 0x3030, 0x0225 }, | ||
95 | { 0x3031, 0x1a01 }, | ||
96 | { 0x3032, 0x0225 }, | ||
97 | { 0x3033, 0x1e00 }, | ||
98 | { 0x3034, 0x0225 }, | ||
99 | { 0x3035, 0x1f00 }, | ||
100 | { 0x3036, 0x6225 }, | ||
101 | { 0x3037, 0xf800 }, | ||
102 | { 0x3038, 0x0000 }, | ||
103 | { 0x3039, 0xf000 }, | ||
104 | { 0x303a, 0x0000 }, | ||
105 | { 0x303b, 0xf000 }, | ||
106 | { 0x303c, 0x0000 }, | ||
107 | { 0x303d, 0xf000 }, | ||
108 | { 0x303e, 0x0000 }, | ||
109 | { 0x303f, 0xf000 }, | ||
110 | { 0x3040, 0x2226 }, | ||
111 | { 0x3041, 0x3a03 }, | ||
112 | { 0x3042, 0x0226 }, | ||
113 | { 0x3043, 0x0801 }, | ||
114 | { 0x3044, 0x6249 }, | ||
115 | { 0x3045, 0x0c06 }, | ||
116 | { 0x3046, 0x0226 }, | ||
117 | { 0x3047, 0x5901 }, | ||
118 | { 0x3048, 0xe249 }, | ||
119 | { 0x3049, 0x030d }, | ||
120 | { 0x304a, 0x0249 }, | ||
121 | { 0x304b, 0x2c01 }, | ||
122 | { 0x304c, 0xe249 }, | ||
123 | { 0x304d, 0x4342 }, | ||
124 | { 0x304e, 0xe249 }, | ||
125 | { 0x304f, 0x73c0 }, | ||
126 | { 0x3050, 0x4249 }, | ||
127 | { 0x3051, 0x0c00 }, | ||
128 | { 0x3052, 0x0226 }, | ||
129 | { 0x3053, 0x1f01 }, | ||
130 | { 0x3054, 0x0226 }, | ||
131 | { 0x3055, 0x1e01 }, | ||
132 | { 0x3056, 0x0226 }, | ||
133 | { 0x3057, 0xfa00 }, | ||
134 | { 0x3058, 0x0000 }, | ||
135 | { 0x3059, 0xf000 }, | ||
136 | { 0x305a, 0x0000 }, | ||
137 | { 0x305b, 0xf000 }, | ||
138 | { 0x305c, 0x0000 }, | ||
139 | { 0x305d, 0xf000 }, | ||
140 | { 0x305e, 0x0000 }, | ||
141 | { 0x305f, 0xf000 }, | ||
142 | { 0x3060, 0x0000 }, | ||
143 | { 0x3061, 0xf000 }, | ||
144 | { 0x3062, 0x0000 }, | ||
145 | { 0x3063, 0xf000 }, | ||
146 | { 0x3064, 0x0000 }, | ||
147 | { 0x3065, 0xf000 }, | ||
148 | { 0x3066, 0x0000 }, | ||
149 | { 0x3067, 0xf000 }, | ||
150 | { 0x3068, 0x0000 }, | ||
151 | { 0x3069, 0xf000 }, | ||
152 | { 0x306a, 0x0000 }, | ||
153 | { 0x306b, 0xf000 }, | ||
154 | { 0x306c, 0x0000 }, | ||
155 | { 0x306d, 0xf000 }, | ||
156 | { 0x306e, 0x0000 }, | ||
157 | { 0x306f, 0xf000 }, | ||
158 | { 0x3070, 0x0226 }, | ||
159 | { 0x3071, 0x1a01 }, | ||
160 | { 0x3072, 0x0226 }, | ||
161 | { 0x3073, 0x1e00 }, | ||
162 | { 0x3074, 0x0226 }, | ||
163 | { 0x3075, 0x1f00 }, | ||
164 | { 0x3076, 0x6226 }, | ||
165 | { 0x3077, 0xf800 }, | ||
166 | { 0x3078, 0x0000 }, | ||
167 | { 0x3079, 0xf000 }, | ||
168 | { 0x307a, 0x0000 }, | ||
169 | { 0x307b, 0xf000 }, | ||
170 | { 0x307c, 0x0000 }, | ||
171 | { 0x307d, 0xf000 }, | ||
172 | { 0x307e, 0x0000 }, | ||
173 | { 0x307f, 0xf000 }, | ||
174 | { 0x3080, 0x2227 }, | ||
175 | { 0x3081, 0x3a03 }, | ||
176 | { 0x3082, 0x0227 }, | ||
177 | { 0x3083, 0x0801 }, | ||
178 | { 0x3084, 0x6255 }, | ||
179 | { 0x3085, 0x0c04 }, | ||
180 | { 0x3086, 0x0227 }, | ||
181 | { 0x3087, 0x5901 }, | ||
182 | { 0x3088, 0xe255 }, | ||
183 | { 0x3089, 0x030d }, | ||
184 | { 0x308a, 0x0255 }, | ||
185 | { 0x308b, 0x2c01 }, | ||
186 | { 0x308c, 0xe255 }, | ||
187 | { 0x308d, 0x4342 }, | ||
188 | { 0x308e, 0xe255 }, | ||
189 | { 0x308f, 0x73c0 }, | ||
190 | { 0x3090, 0x4255 }, | ||
191 | { 0x3091, 0x0c00 }, | ||
192 | { 0x3092, 0x0227 }, | ||
193 | { 0x3093, 0x1f01 }, | ||
194 | { 0x3094, 0x0227 }, | ||
195 | { 0x3095, 0x1e01 }, | ||
196 | { 0x3096, 0x0227 }, | ||
197 | { 0x3097, 0xfa00 }, | ||
198 | { 0x3098, 0x0000 }, | ||
199 | { 0x3099, 0xf000 }, | ||
200 | { 0x309a, 0x0000 }, | ||
201 | { 0x309b, 0xf000 }, | ||
202 | { 0x309c, 0x0000 }, | ||
203 | { 0x309d, 0xf000 }, | ||
204 | { 0x309e, 0x0000 }, | ||
205 | { 0x309f, 0xf000 }, | ||
206 | { 0x30a0, 0x0000 }, | ||
207 | { 0x30a1, 0xf000 }, | ||
208 | { 0x30a2, 0x0000 }, | ||
209 | { 0x30a3, 0xf000 }, | ||
210 | { 0x30a4, 0x0000 }, | ||
211 | { 0x30a5, 0xf000 }, | ||
212 | { 0x30a6, 0x0000 }, | ||
213 | { 0x30a7, 0xf000 }, | ||
214 | { 0x30a8, 0x0000 }, | ||
215 | { 0x30a9, 0xf000 }, | ||
216 | { 0x30aa, 0x0000 }, | ||
217 | { 0x30ab, 0xf000 }, | ||
218 | { 0x30ac, 0x0000 }, | ||
219 | { 0x30ad, 0xf000 }, | ||
220 | { 0x30ae, 0x0000 }, | ||
221 | { 0x30af, 0xf000 }, | ||
222 | { 0x30b0, 0x0227 }, | ||
223 | { 0x30b1, 0x1a01 }, | ||
224 | { 0x30b2, 0x0227 }, | ||
225 | { 0x30b3, 0x1e00 }, | ||
226 | { 0x30b4, 0x0227 }, | ||
227 | { 0x30b5, 0x1f00 }, | ||
228 | { 0x30b6, 0x6227 }, | ||
229 | { 0x30b7, 0xf800 }, | ||
230 | { 0x30b8, 0x0000 }, | ||
231 | { 0x30b9, 0xf000 }, | ||
232 | { 0x30ba, 0x0000 }, | ||
233 | { 0x30bb, 0xf000 }, | ||
234 | { 0x30bc, 0x0000 }, | ||
235 | { 0x30bd, 0xf000 }, | ||
236 | { 0x30be, 0x0000 }, | ||
237 | { 0x30bf, 0xf000 }, | ||
238 | { 0x30c0, 0x2228 }, | ||
239 | { 0x30c1, 0x3a03 }, | ||
240 | { 0x30c2, 0x0228 }, | ||
241 | { 0x30c3, 0x0801 }, | ||
242 | { 0x30c4, 0x6255 }, | ||
243 | { 0x30c5, 0x0c06 }, | ||
244 | { 0x30c6, 0x0228 }, | ||
245 | { 0x30c7, 0x5901 }, | ||
246 | { 0x30c8, 0xe255 }, | ||
247 | { 0x30c9, 0x030d }, | ||
248 | { 0x30ca, 0x0255 }, | ||
249 | { 0x30cb, 0x2c01 }, | ||
250 | { 0x30cc, 0xe255 }, | ||
251 | { 0x30cd, 0x4342 }, | ||
252 | { 0x30ce, 0xe255 }, | ||
253 | { 0x30cf, 0x73c0 }, | ||
254 | { 0x30d0, 0x4255 }, | ||
255 | { 0x30d1, 0x0c00 }, | ||
256 | { 0x30d2, 0x0228 }, | ||
257 | { 0x30d3, 0x1f01 }, | ||
258 | { 0x30d4, 0x0228 }, | ||
259 | { 0x30d5, 0x1e01 }, | ||
260 | { 0x30d6, 0x0228 }, | ||
261 | { 0x30d7, 0xfa00 }, | ||
262 | { 0x30d8, 0x0000 }, | ||
263 | { 0x30d9, 0xf000 }, | ||
264 | { 0x30da, 0x0000 }, | ||
265 | { 0x30db, 0xf000 }, | ||
266 | { 0x30dc, 0x0000 }, | ||
267 | { 0x30dd, 0xf000 }, | ||
268 | { 0x30de, 0x0000 }, | ||
269 | { 0x30df, 0xf000 }, | ||
270 | { 0x30e0, 0x0000 }, | ||
271 | { 0x30e1, 0xf000 }, | ||
272 | { 0x30e2, 0x0000 }, | ||
273 | { 0x30e3, 0xf000 }, | ||
274 | { 0x30e4, 0x0000 }, | ||
275 | { 0x30e5, 0xf000 }, | ||
276 | { 0x30e6, 0x0000 }, | ||
277 | { 0x30e7, 0xf000 }, | ||
278 | { 0x30e8, 0x0000 }, | ||
279 | { 0x30e9, 0xf000 }, | ||
280 | { 0x30ea, 0x0000 }, | ||
281 | { 0x30eb, 0xf000 }, | ||
282 | { 0x30ec, 0x0000 }, | ||
283 | { 0x30ed, 0xf000 }, | ||
284 | { 0x30ee, 0x0000 }, | ||
285 | { 0x30ef, 0xf000 }, | ||
286 | { 0x30f0, 0x0228 }, | ||
287 | { 0x30f1, 0x1a01 }, | ||
288 | { 0x30f2, 0x0228 }, | ||
289 | { 0x30f3, 0x1e00 }, | ||
290 | { 0x30f4, 0x0228 }, | ||
291 | { 0x30f5, 0x1f00 }, | ||
292 | { 0x30f6, 0x6228 }, | ||
293 | { 0x30f7, 0xf800 }, | ||
294 | { 0x30f8, 0x0000 }, | ||
295 | { 0x30f9, 0xf000 }, | ||
296 | { 0x30fa, 0x0000 }, | ||
297 | { 0x30fb, 0xf000 }, | ||
298 | { 0x30fc, 0x0000 }, | ||
299 | { 0x30fd, 0xf000 }, | ||
300 | { 0x30fe, 0x0000 }, | ||
301 | { 0x30ff, 0xf000 }, | ||
302 | { 0x3100, 0x222b }, | ||
303 | { 0x3101, 0x3a03 }, | ||
304 | { 0x3102, 0x222b }, | ||
305 | { 0x3103, 0x5803 }, | ||
306 | { 0x3104, 0xe26f }, | ||
307 | { 0x3105, 0x030d }, | ||
308 | { 0x3106, 0x626f }, | ||
309 | { 0x3107, 0x2c01 }, | ||
310 | { 0x3108, 0xe26f }, | ||
311 | { 0x3109, 0x4342 }, | ||
312 | { 0x310a, 0xe26f }, | ||
313 | { 0x310b, 0x73c0 }, | ||
314 | { 0x310c, 0x026f }, | ||
315 | { 0x310d, 0x0c00 }, | ||
316 | { 0x310e, 0x022b }, | ||
317 | { 0x310f, 0x1f01 }, | ||
318 | { 0x3110, 0x022b }, | ||
319 | { 0x3111, 0x1e01 }, | ||
320 | { 0x3112, 0x022b }, | ||
321 | { 0x3113, 0xfa00 }, | ||
322 | { 0x3114, 0x0000 }, | ||
323 | { 0x3115, 0xf000 }, | ||
324 | { 0x3116, 0x0000 }, | ||
325 | { 0x3117, 0xf000 }, | ||
326 | { 0x3118, 0x0000 }, | ||
327 | { 0x3119, 0xf000 }, | ||
328 | { 0x311a, 0x0000 }, | ||
329 | { 0x311b, 0xf000 }, | ||
330 | { 0x311c, 0x0000 }, | ||
331 | { 0x311d, 0xf000 }, | ||
332 | { 0x311e, 0x0000 }, | ||
333 | { 0x311f, 0xf000 }, | ||
334 | { 0x3120, 0x022b }, | ||
335 | { 0x3121, 0x0a01 }, | ||
336 | { 0x3122, 0x022b }, | ||
337 | { 0x3123, 0x1e00 }, | ||
338 | { 0x3124, 0x022b }, | ||
339 | { 0x3125, 0x1f00 }, | ||
340 | { 0x3126, 0x622b }, | ||
341 | { 0x3127, 0xf800 }, | ||
342 | { 0x3128, 0x0000 }, | ||
343 | { 0x3129, 0xf000 }, | ||
344 | { 0x312a, 0x0000 }, | ||
345 | { 0x312b, 0xf000 }, | ||
346 | { 0x312c, 0x0000 }, | ||
347 | { 0x312d, 0xf000 }, | ||
348 | { 0x312e, 0x0000 }, | ||
349 | { 0x312f, 0xf000 }, | ||
350 | { 0x3130, 0x0000 }, | ||
351 | { 0x3131, 0xf000 }, | ||
352 | { 0x3132, 0x0000 }, | ||
353 | { 0x3133, 0xf000 }, | ||
354 | { 0x3134, 0x0000 }, | ||
355 | { 0x3135, 0xf000 }, | ||
356 | { 0x3136, 0x0000 }, | ||
357 | { 0x3137, 0xf000 }, | ||
358 | { 0x3138, 0x0000 }, | ||
359 | { 0x3139, 0xf000 }, | ||
360 | { 0x313a, 0x0000 }, | ||
361 | { 0x313b, 0xf000 }, | ||
362 | { 0x313c, 0x0000 }, | ||
363 | { 0x313d, 0xf000 }, | ||
364 | { 0x313e, 0x0000 }, | ||
365 | { 0x313f, 0xf000 }, | ||
366 | { 0x3140, 0x0000 }, | ||
367 | { 0x3141, 0xf000 }, | ||
368 | { 0x3142, 0x0000 }, | ||
369 | { 0x3143, 0xf000 }, | ||
370 | { 0x3144, 0x0000 }, | ||
371 | { 0x3145, 0xf000 }, | ||
372 | { 0x3146, 0x0000 }, | ||
373 | { 0x3147, 0xf000 }, | ||
374 | { 0x3148, 0x0000 }, | ||
375 | { 0x3149, 0xf000 }, | ||
376 | { 0x314a, 0x0000 }, | ||
377 | { 0x314b, 0xf000 }, | ||
378 | { 0x314c, 0x0000 }, | ||
379 | { 0x314d, 0xf000 }, | ||
380 | { 0x314e, 0x0000 }, | ||
381 | { 0x314f, 0xf000 }, | ||
382 | { 0x3150, 0x0000 }, | ||
383 | { 0x3151, 0xf000 }, | ||
384 | { 0x3152, 0x0000 }, | ||
385 | { 0x3153, 0xf000 }, | ||
386 | { 0x3154, 0x0000 }, | ||
387 | { 0x3155, 0xf000 }, | ||
388 | { 0x3156, 0x0000 }, | ||
389 | { 0x3157, 0xf000 }, | ||
390 | { 0x3158, 0x0000 }, | ||
391 | { 0x3159, 0xf000 }, | ||
392 | { 0x315a, 0x0000 }, | ||
393 | { 0x315b, 0xf000 }, | ||
394 | { 0x315c, 0x0000 }, | ||
395 | { 0x315d, 0xf000 }, | ||
396 | { 0x315e, 0x0000 }, | ||
397 | { 0x315f, 0xf000 }, | ||
398 | { 0x3160, 0x0000 }, | ||
399 | { 0x3161, 0xf000 }, | ||
400 | { 0x3162, 0x0000 }, | ||
401 | { 0x3163, 0xf000 }, | ||
402 | { 0x3164, 0x0000 }, | ||
403 | { 0x3165, 0xf000 }, | ||
404 | { 0x3166, 0x0000 }, | ||
405 | { 0x3167, 0xf000 }, | ||
406 | { 0x3168, 0x0000 }, | ||
407 | { 0x3169, 0xf000 }, | ||
408 | { 0x316a, 0x0000 }, | ||
409 | { 0x316b, 0xf000 }, | ||
410 | { 0x316c, 0x0000 }, | ||
411 | { 0x316d, 0xf000 }, | ||
412 | { 0x316e, 0x0000 }, | ||
413 | { 0x316f, 0xf000 }, | ||
414 | { 0x3170, 0x0000 }, | ||
415 | { 0x3171, 0xf000 }, | ||
416 | { 0x3172, 0x0000 }, | ||
417 | { 0x3173, 0xf000 }, | ||
418 | { 0x3174, 0x0000 }, | ||
419 | { 0x3175, 0xf000 }, | ||
420 | { 0x3176, 0x0000 }, | ||
421 | { 0x3177, 0xf000 }, | ||
422 | { 0x3178, 0x0000 }, | ||
423 | { 0x3179, 0xf000 }, | ||
424 | { 0x317a, 0x0000 }, | ||
425 | { 0x317b, 0xf000 }, | ||
426 | { 0x317c, 0x0000 }, | ||
427 | { 0x317d, 0xf000 }, | ||
428 | { 0x317e, 0x0000 }, | ||
429 | { 0x317f, 0xf000 }, | ||
430 | { 0x3180, 0x2001 }, | ||
431 | { 0x3181, 0xf101 }, | ||
432 | { 0x3182, 0x0000 }, | ||
433 | { 0x3183, 0xf000 }, | ||
434 | { 0x3184, 0x0000 }, | ||
435 | { 0x3185, 0xf000 }, | ||
436 | { 0x3186, 0x0000 }, | ||
437 | { 0x3187, 0xf000 }, | ||
438 | { 0x3188, 0x0000 }, | ||
439 | { 0x3189, 0xf000 }, | ||
440 | { 0x318a, 0x0000 }, | ||
441 | { 0x318b, 0xf000 }, | ||
442 | { 0x318c, 0x0000 }, | ||
443 | { 0x318d, 0xf000 }, | ||
444 | { 0x318e, 0x0000 }, | ||
445 | { 0x318f, 0xf000 }, | ||
446 | { 0x3190, 0x0000 }, | ||
447 | { 0x3191, 0xf000 }, | ||
448 | { 0x3192, 0x0000 }, | ||
449 | { 0x3193, 0xf000 }, | ||
450 | { 0x3194, 0x0000 }, | ||
451 | { 0x3195, 0xf000 }, | ||
452 | { 0x3196, 0x0000 }, | ||
453 | { 0x3197, 0xf000 }, | ||
454 | { 0x3198, 0x0000 }, | ||
455 | { 0x3199, 0xf000 }, | ||
456 | { 0x319a, 0x0000 }, | ||
457 | { 0x319b, 0xf000 }, | ||
458 | { 0x319c, 0x0000 }, | ||
459 | { 0x319d, 0xf000 }, | ||
460 | { 0x319e, 0x0000 }, | ||
461 | { 0x319f, 0xf000 }, | ||
462 | { 0x31a0, 0x0000 }, | ||
463 | { 0x31a1, 0xf000 }, | ||
464 | { 0x31a2, 0x0000 }, | ||
465 | { 0x31a3, 0xf000 }, | ||
466 | { 0x31a4, 0x0000 }, | ||
467 | { 0x31a5, 0xf000 }, | ||
468 | { 0x31a6, 0x0000 }, | ||
469 | { 0x31a7, 0xf000 }, | ||
470 | { 0x31a8, 0x0000 }, | ||
471 | { 0x31a9, 0xf000 }, | ||
472 | { 0x31aa, 0x0000 }, | ||
473 | { 0x31ab, 0xf000 }, | ||
474 | { 0x31ac, 0x0000 }, | ||
475 | { 0x31ad, 0xf000 }, | ||
476 | { 0x31ae, 0x0000 }, | ||
477 | { 0x31af, 0xf000 }, | ||
478 | { 0x31b0, 0x0000 }, | ||
479 | { 0x31b1, 0xf000 }, | ||
480 | { 0x31b2, 0x0000 }, | ||
481 | { 0x31b3, 0xf000 }, | ||
482 | { 0x31b4, 0x0000 }, | ||
483 | { 0x31b5, 0xf000 }, | ||
484 | { 0x31b6, 0x0000 }, | ||
485 | { 0x31b7, 0xf000 }, | ||
486 | { 0x31b8, 0x0000 }, | ||
487 | { 0x31b9, 0xf000 }, | ||
488 | { 0x31ba, 0x0000 }, | ||
489 | { 0x31bb, 0xf000 }, | ||
490 | { 0x31bc, 0x0000 }, | ||
491 | { 0x31bd, 0xf000 }, | ||
492 | { 0x31be, 0x0000 }, | ||
493 | { 0x31bf, 0xf000 }, | ||
494 | { 0x31c0, 0x0000 }, | ||
495 | { 0x31c1, 0xf000 }, | ||
496 | { 0x31c2, 0x0000 }, | ||
497 | { 0x31c3, 0xf000 }, | ||
498 | { 0x31c4, 0x0000 }, | ||
499 | { 0x31c5, 0xf000 }, | ||
500 | { 0x31c6, 0x0000 }, | ||
501 | { 0x31c7, 0xf000 }, | ||
502 | { 0x31c8, 0x0000 }, | ||
503 | { 0x31c9, 0xf000 }, | ||
504 | { 0x31ca, 0x0000 }, | ||
505 | { 0x31cb, 0xf000 }, | ||
506 | { 0x31cc, 0x0000 }, | ||
507 | { 0x31cd, 0xf000 }, | ||
508 | { 0x31ce, 0x0000 }, | ||
509 | { 0x31cf, 0xf000 }, | ||
510 | { 0x31d0, 0x0000 }, | ||
511 | { 0x31d1, 0xf000 }, | ||
512 | { 0x31d2, 0x0000 }, | ||
513 | { 0x31d3, 0xf000 }, | ||
514 | { 0x31d4, 0x0000 }, | ||
515 | { 0x31d5, 0xf000 }, | ||
516 | { 0x31d6, 0x0000 }, | ||
517 | { 0x31d7, 0xf000 }, | ||
518 | { 0x31d8, 0x0000 }, | ||
519 | { 0x31d9, 0xf000 }, | ||
520 | { 0x31da, 0x0000 }, | ||
521 | { 0x31db, 0xf000 }, | ||
522 | { 0x31dc, 0x0000 }, | ||
523 | { 0x31dd, 0xf000 }, | ||
524 | { 0x31de, 0x0000 }, | ||
525 | { 0x31df, 0xf000 }, | ||
526 | { 0x31e0, 0x0000 }, | ||
527 | { 0x31e1, 0xf000 }, | ||
528 | { 0x31e2, 0x0000 }, | ||
529 | { 0x31e3, 0xf000 }, | ||
530 | { 0x31e4, 0x0000 }, | ||
531 | { 0x31e5, 0xf000 }, | ||
532 | { 0x31e6, 0x0000 }, | ||
533 | { 0x31e7, 0xf000 }, | ||
534 | { 0x31e8, 0x0000 }, | ||
535 | { 0x31e9, 0xf000 }, | ||
536 | { 0x31ea, 0x0000 }, | ||
537 | { 0x31eb, 0xf000 }, | ||
538 | { 0x31ec, 0x0000 }, | ||
539 | { 0x31ed, 0xf000 }, | ||
540 | { 0x31ee, 0x0000 }, | ||
541 | { 0x31ef, 0xf000 }, | ||
542 | { 0x31f0, 0x0000 }, | ||
543 | { 0x31f1, 0xf000 }, | ||
544 | { 0x31f2, 0x0000 }, | ||
545 | { 0x31f3, 0xf000 }, | ||
546 | { 0x31f4, 0x0000 }, | ||
547 | { 0x31f5, 0xf000 }, | ||
548 | { 0x31f6, 0x0000 }, | ||
549 | { 0x31f7, 0xf000 }, | ||
550 | { 0x31f8, 0x0000 }, | ||
551 | { 0x31f9, 0xf000 }, | ||
552 | { 0x31fa, 0x0000 }, | ||
553 | { 0x31fb, 0xf000 }, | ||
554 | { 0x31fc, 0x0000 }, | ||
555 | { 0x31fd, 0xf000 }, | ||
556 | { 0x31fe, 0x0000 }, | ||
557 | { 0x31ff, 0xf000 }, | ||
558 | { 0x024d, 0xff50 }, | ||
559 | { 0x0252, 0xff50 }, | ||
560 | { 0x0259, 0x0112 }, | ||
561 | { 0x025e, 0x0112 }, | ||
562 | }; | ||
563 | |||
564 | static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, | ||
565 | struct snd_kcontrol *kcontrol, int event) | ||
566 | { | ||
567 | struct snd_soc_codec *codec = w->codec; | ||
568 | struct arizona *arizona = dev_get_drvdata(codec->dev); | ||
569 | struct regmap *regmap = codec->control_data; | ||
570 | const struct reg_default *patch = NULL; | ||
571 | int i, patch_size; | ||
572 | |||
573 | switch (arizona->rev) { | ||
574 | case 0: | ||
575 | patch = wm5102_sysclk_reva_patch; | ||
576 | patch_size = ARRAY_SIZE(wm5102_sysclk_reva_patch); | ||
577 | break; | ||
578 | } | ||
579 | |||
580 | switch (event) { | ||
581 | case SND_SOC_DAPM_POST_PMU: | ||
582 | if (patch) | ||
583 | for (i = 0; i < patch_size; i++) | ||
584 | regmap_write(regmap, patch[i].reg, | ||
585 | patch[i].def); | ||
586 | break; | ||
587 | |||
588 | default: | ||
589 | break; | ||
590 | } | ||
591 | |||
592 | return 0; | ||
593 | } | ||
594 | |||
45 | static const struct snd_kcontrol_new wm5102_snd_controls[] = { | 595 | static const struct snd_kcontrol_new wm5102_snd_controls[] = { |
46 | SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL, | 596 | SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL, |
47 | ARIZONA_IN1_OSR_SHIFT, 1, 0), | 597 | ARIZONA_IN1_OSR_SHIFT, 1, 0), |
@@ -297,7 +847,7 @@ static const struct snd_kcontrol_new wm5102_aec_loopback_mux = | |||
297 | 847 | ||
298 | static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { | 848 | static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { |
299 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | 849 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, |
300 | 0, NULL, 0), | 850 | 0, wm5102_sysclk_ev, SND_SOC_DAPM_POST_PMU), |
301 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, | 851 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, |
302 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | 852 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), |
303 | SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, | 853 | SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, |
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 5421fd9fbcb5..4c0a8e496131 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c | |||
@@ -782,7 +782,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, | |||
782 | wm8978->mclk_idx = -1; | 782 | wm8978->mclk_idx = -1; |
783 | f_sel = wm8978->f_mclk; | 783 | f_sel = wm8978->f_mclk; |
784 | } else { | 784 | } else { |
785 | if (!wm8978->f_pllout) { | 785 | if (!wm8978->f_opclk) { |
786 | /* We only enter here, if OPCLK is not used */ | 786 | /* We only enter here, if OPCLK is not used */ |
787 | int ret = wm8978_configure_pll(codec); | 787 | int ret = wm8978_configure_pll(codec); |
788 | if (ret < 0) | 788 | if (ret < 0) |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 3fddc7ad1127..b2b2b37131bd 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -3722,7 +3722,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) | |||
3722 | } while (count--); | 3722 | } while (count--); |
3723 | 3723 | ||
3724 | if (count == 0) | 3724 | if (count == 0) |
3725 | dev_warn(codec->dev, "No impedence range reported for jack\n"); | 3725 | dev_warn(codec->dev, "No impedance range reported for jack\n"); |
3726 | 3726 | ||
3727 | #ifndef CONFIG_SND_SOC_WM8994_MODULE | 3727 | #ifndef CONFIG_SND_SOC_WM8994_MODULE |
3728 | trace_snd_soc_jack_irq(dev_name(codec->dev)); | 3728 | trace_snd_soc_jack_irq(dev_name(codec->dev)); |
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 68f2cd1a9206..5a6aeaf552a8 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c | |||
@@ -464,9 +464,9 @@ static __devinit int asoc_dmic_probe(struct platform_device *pdev) | |||
464 | 464 | ||
465 | mutex_init(&dmic->mutex); | 465 | mutex_init(&dmic->mutex); |
466 | 466 | ||
467 | dmic->fclk = clk_get(dmic->dev, "dmic_fck"); | 467 | dmic->fclk = clk_get(dmic->dev, "fck"); |
468 | if (IS_ERR(dmic->fclk)) { | 468 | if (IS_ERR(dmic->fclk)) { |
469 | dev_err(dmic->dev, "cant get dmic_fck\n"); | 469 | dev_err(dmic->dev, "cant get fck\n"); |
470 | return -ENODEV; | 470 | return -ENODEV; |
471 | } | 471 | } |
472 | 472 | ||
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index 677b567935f8..1ff6bb9ade5c 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c | |||
@@ -21,15 +21,14 @@ | |||
21 | 21 | ||
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/gpio.h> | ||
24 | #include <sound/core.h> | 25 | #include <sound/core.h> |
25 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
26 | #include <sound/soc.h> | 27 | #include <sound/soc.h> |
27 | 28 | ||
28 | #include <asm/mach-types.h> | 29 | #include <asm/mach-types.h> |
29 | #include <mach/hardware.h> | ||
30 | #include <mach/gpio.h> | ||
31 | #include <mach/board-zoom.h> | ||
32 | #include <linux/platform_data/asoc-ti-mcbsp.h> | 30 | #include <linux/platform_data/asoc-ti-mcbsp.h> |
31 | #include <linux/platform_data/gpio-omap.h> | ||
33 | 32 | ||
34 | /* Register descriptions for twl4030 codec part */ | 33 | /* Register descriptions for twl4030 codec part */ |
35 | #include <linux/mfd/twl4030-audio.h> | 34 | #include <linux/mfd/twl4030-audio.h> |
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index e7b83179aca2..3c7c3a59ed39 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -207,6 +207,8 @@ config SND_SOC_BELLS | |||
207 | select SND_SOC_WM5102 | 207 | select SND_SOC_WM5102 |
208 | select SND_SOC_WM5110 | 208 | select SND_SOC_WM5110 |
209 | select SND_SOC_WM9081 | 209 | select SND_SOC_WM9081 |
210 | select SND_SOC_WM0010 | ||
211 | select SND_SOC_WM1250_EV1 | ||
210 | 212 | ||
211 | config SND_SOC_LOWLAND | 213 | config SND_SOC_LOWLAND |
212 | tristate "Audio support for Wolfson Lowland" | 214 | tristate "Audio support for Wolfson Lowland" |
diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c index b0d46d63d55e..b56b9a3c6169 100644 --- a/sound/soc/samsung/bells.c +++ b/sound/soc/samsung/bells.c | |||
@@ -247,7 +247,7 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = { | |||
247 | { | 247 | { |
248 | .name = "Sub", | 248 | .name = "Sub", |
249 | .stream_name = "Sub", | 249 | .stream_name = "Sub", |
250 | .cpu_dai_name = "wm5110-aif3", | 250 | .cpu_dai_name = "wm5102-aif3", |
251 | .codec_dai_name = "wm9081-hifi", | 251 | .codec_dai_name = "wm9081-hifi", |
252 | .codec_name = "wm9081.1-006c", | 252 | .codec_name = "wm9081.1-006c", |
253 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 253 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d1198627fc40..10d21be383f6 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -2786,8 +2786,9 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, | |||
2786 | val = (ucontrol->value.integer.value[0] + min) & mask; | 2786 | val = (ucontrol->value.integer.value[0] + min) & mask; |
2787 | val = val << shift; | 2787 | val = val << shift; |
2788 | 2788 | ||
2789 | if (snd_soc_update_bits_locked(codec, reg, val_mask, val)) | 2789 | err = snd_soc_update_bits_locked(codec, reg, val_mask, val); |
2790 | return err; | 2790 | if (err < 0) |
2791 | return err; | ||
2791 | 2792 | ||
2792 | if (snd_soc_volsw_is_stereo(mc)) { | 2793 | if (snd_soc_volsw_is_stereo(mc)) { |
2793 | val_mask = mask << rshift; | 2794 | val_mask = mask << rshift; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index d0a4be38dc0f..6e35bcae02df 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -3745,7 +3745,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card) | |||
3745 | { | 3745 | { |
3746 | struct snd_soc_codec *codec; | 3746 | struct snd_soc_codec *codec; |
3747 | 3747 | ||
3748 | list_for_each_entry(codec, &card->codec_dev_list, list) { | 3748 | list_for_each_entry(codec, &card->codec_dev_list, card_list) { |
3749 | soc_dapm_shutdown_codec(&codec->dapm); | 3749 | soc_dapm_shutdown_codec(&codec->dapm); |
3750 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) | 3750 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) |
3751 | snd_soc_dapm_set_bias_level(&codec->dapm, | 3751 | snd_soc_dapm_set_bias_level(&codec->dapm, |
diff --git a/sound/usb/card.c b/sound/usb/card.c index 561bb74fd364..282f0fc9fed1 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c | |||
@@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
339 | } | 339 | } |
340 | 340 | ||
341 | mutex_init(&chip->mutex); | 341 | mutex_init(&chip->mutex); |
342 | mutex_init(&chip->shutdown_mutex); | 342 | init_rwsem(&chip->shutdown_rwsem); |
343 | chip->index = idx; | 343 | chip->index = idx; |
344 | chip->dev = dev; | 344 | chip->dev = dev; |
345 | chip->card = card; | 345 | chip->card = card; |
@@ -560,7 +560,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, | |||
560 | 560 | ||
561 | card = chip->card; | 561 | card = chip->card; |
562 | mutex_lock(®ister_mutex); | 562 | mutex_lock(®ister_mutex); |
563 | mutex_lock(&chip->shutdown_mutex); | 563 | down_write(&chip->shutdown_rwsem); |
564 | chip->shutdown = 1; | 564 | chip->shutdown = 1; |
565 | chip->num_interfaces--; | 565 | chip->num_interfaces--; |
566 | if (chip->num_interfaces <= 0) { | 566 | if (chip->num_interfaces <= 0) { |
@@ -582,11 +582,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, | |||
582 | snd_usb_mixer_disconnect(p); | 582 | snd_usb_mixer_disconnect(p); |
583 | } | 583 | } |
584 | usb_chip[chip->index] = NULL; | 584 | usb_chip[chip->index] = NULL; |
585 | mutex_unlock(&chip->shutdown_mutex); | 585 | up_write(&chip->shutdown_rwsem); |
586 | mutex_unlock(®ister_mutex); | 586 | mutex_unlock(®ister_mutex); |
587 | snd_card_free_when_closed(card); | 587 | snd_card_free_when_closed(card); |
588 | } else { | 588 | } else { |
589 | mutex_unlock(&chip->shutdown_mutex); | 589 | up_write(&chip->shutdown_rwsem); |
590 | mutex_unlock(®ister_mutex); | 590 | mutex_unlock(®ister_mutex); |
591 | } | 591 | } |
592 | } | 592 | } |
@@ -618,16 +618,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) | |||
618 | { | 618 | { |
619 | int err = -ENODEV; | 619 | int err = -ENODEV; |
620 | 620 | ||
621 | down_read(&chip->shutdown_rwsem); | ||
621 | if (!chip->shutdown && !chip->probing) | 622 | if (!chip->shutdown && !chip->probing) |
622 | err = usb_autopm_get_interface(chip->pm_intf); | 623 | err = usb_autopm_get_interface(chip->pm_intf); |
624 | up_read(&chip->shutdown_rwsem); | ||
623 | 625 | ||
624 | return err; | 626 | return err; |
625 | } | 627 | } |
626 | 628 | ||
627 | void snd_usb_autosuspend(struct snd_usb_audio *chip) | 629 | void snd_usb_autosuspend(struct snd_usb_audio *chip) |
628 | { | 630 | { |
631 | down_read(&chip->shutdown_rwsem); | ||
629 | if (!chip->shutdown && !chip->probing) | 632 | if (!chip->shutdown && !chip->probing) |
630 | usb_autopm_put_interface(chip->pm_intf); | 633 | usb_autopm_put_interface(chip->pm_intf); |
634 | up_read(&chip->shutdown_rwsem); | ||
631 | } | 635 | } |
632 | 636 | ||
633 | static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) | 637 | static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) |
diff --git a/sound/usb/card.h b/sound/usb/card.h index afa4f9e9b27a..814cb357ff88 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h | |||
@@ -126,6 +126,7 @@ struct snd_usb_substream { | |||
126 | struct snd_usb_endpoint *sync_endpoint; | 126 | struct snd_usb_endpoint *sync_endpoint; |
127 | unsigned long flags; | 127 | unsigned long flags; |
128 | bool need_setup_ep; /* (re)configure EP at prepare? */ | 128 | bool need_setup_ep; /* (re)configure EP at prepare? */ |
129 | unsigned int speed; /* USB_SPEED_XXX */ | ||
129 | 130 | ||
130 | u64 formats; /* format bitmasks (all or'ed) */ | 131 | u64 formats; /* format bitmasks (all or'ed) */ |
131 | unsigned int num_formats; /* number of supported audio formats (list) */ | 132 | unsigned int num_formats; /* number of supported audio formats (list) */ |
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 7f78c6d782b0..34de6f2faf61 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | #define EP_FLAG_ACTIVATED 0 | 36 | #define EP_FLAG_ACTIVATED 0 |
37 | #define EP_FLAG_RUNNING 1 | 37 | #define EP_FLAG_RUNNING 1 |
38 | #define EP_FLAG_STOPPING 2 | ||
38 | 39 | ||
39 | /* | 40 | /* |
40 | * snd_usb_endpoint is a model that abstracts everything related to an | 41 | * snd_usb_endpoint is a model that abstracts everything related to an |
@@ -502,10 +503,20 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) | |||
502 | if (alive) | 503 | if (alive) |
503 | snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n", | 504 | snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n", |
504 | alive, ep->ep_num); | 505 | alive, ep->ep_num); |
506 | clear_bit(EP_FLAG_STOPPING, &ep->flags); | ||
505 | 507 | ||
506 | return 0; | 508 | return 0; |
507 | } | 509 | } |
508 | 510 | ||
511 | /* sync the pending stop operation; | ||
512 | * this function itself doesn't trigger the stop operation | ||
513 | */ | ||
514 | void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) | ||
515 | { | ||
516 | if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags)) | ||
517 | wait_clear_urbs(ep); | ||
518 | } | ||
519 | |||
509 | /* | 520 | /* |
510 | * unlink active urbs. | 521 | * unlink active urbs. |
511 | */ | 522 | */ |
@@ -918,6 +929,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, | |||
918 | 929 | ||
919 | if (wait) | 930 | if (wait) |
920 | wait_clear_urbs(ep); | 931 | wait_clear_urbs(ep); |
932 | else | ||
933 | set_bit(EP_FLAG_STOPPING, &ep->flags); | ||
921 | } | 934 | } |
922 | } | 935 | } |
923 | 936 | ||
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index 6376ccf10fd4..3d4c9705041f 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h | |||
@@ -19,6 +19,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, | |||
19 | int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); | 19 | int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); |
20 | void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, | 20 | void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, |
21 | int force, int can_sleep, int wait); | 21 | int force, int can_sleep, int wait); |
22 | void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); | ||
22 | int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); | 23 | int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); |
23 | int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); | 24 | int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); |
24 | void snd_usb_endpoint_free(struct list_head *head); | 25 | void snd_usb_endpoint_free(struct list_head *head); |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index fe56c9da38e9..298070e8f2d4 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -287,25 +287,32 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v | |||
287 | unsigned char buf[2]; | 287 | unsigned char buf[2]; |
288 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 288 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
289 | int timeout = 10; | 289 | int timeout = 10; |
290 | int err; | 290 | int idx = 0, err; |
291 | 291 | ||
292 | err = snd_usb_autoresume(cval->mixer->chip); | 292 | err = snd_usb_autoresume(cval->mixer->chip); |
293 | if (err < 0) | 293 | if (err < 0) |
294 | return -EIO; | 294 | return -EIO; |
295 | down_read(&chip->shutdown_rwsem); | ||
295 | while (timeout-- > 0) { | 296 | while (timeout-- > 0) { |
297 | if (chip->shutdown) | ||
298 | break; | ||
299 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); | ||
296 | if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, | 300 | if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, |
297 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 301 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
298 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 302 | validx, idx, buf, val_len) >= val_len) { |
299 | buf, val_len) >= val_len) { | ||
300 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); | 303 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); |
301 | snd_usb_autosuspend(cval->mixer->chip); | 304 | err = 0; |
302 | return 0; | 305 | goto out; |
303 | } | 306 | } |
304 | } | 307 | } |
305 | snd_usb_autosuspend(cval->mixer->chip); | ||
306 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", | 308 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
307 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); | 309 | request, validx, idx, cval->val_type); |
308 | return -EINVAL; | 310 | err = -EINVAL; |
311 | |||
312 | out: | ||
313 | up_read(&chip->shutdown_rwsem); | ||
314 | snd_usb_autosuspend(cval->mixer->chip); | ||
315 | return err; | ||
309 | } | 316 | } |
310 | 317 | ||
311 | static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) | 318 | static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) |
@@ -313,7 +320,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v | |||
313 | struct snd_usb_audio *chip = cval->mixer->chip; | 320 | struct snd_usb_audio *chip = cval->mixer->chip; |
314 | unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ | 321 | unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ |
315 | unsigned char *val; | 322 | unsigned char *val; |
316 | int ret, size; | 323 | int idx = 0, ret, size; |
317 | __u8 bRequest; | 324 | __u8 bRequest; |
318 | 325 | ||
319 | if (request == UAC_GET_CUR) { | 326 | if (request == UAC_GET_CUR) { |
@@ -330,16 +337,22 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v | |||
330 | if (ret) | 337 | if (ret) |
331 | goto error; | 338 | goto error; |
332 | 339 | ||
333 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, | 340 | down_read(&chip->shutdown_rwsem); |
341 | if (chip->shutdown) | ||
342 | ret = -ENODEV; | ||
343 | else { | ||
344 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); | ||
345 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, | ||
334 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 346 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
335 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 347 | validx, idx, buf, size); |
336 | buf, size); | 348 | } |
349 | up_read(&chip->shutdown_rwsem); | ||
337 | snd_usb_autosuspend(chip); | 350 | snd_usb_autosuspend(chip); |
338 | 351 | ||
339 | if (ret < 0) { | 352 | if (ret < 0) { |
340 | error: | 353 | error: |
341 | snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", | 354 | snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
342 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); | 355 | request, validx, idx, cval->val_type); |
343 | return ret; | 356 | return ret; |
344 | } | 357 | } |
345 | 358 | ||
@@ -417,7 +430,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
417 | { | 430 | { |
418 | struct snd_usb_audio *chip = cval->mixer->chip; | 431 | struct snd_usb_audio *chip = cval->mixer->chip; |
419 | unsigned char buf[2]; | 432 | unsigned char buf[2]; |
420 | int val_len, err, timeout = 10; | 433 | int idx = 0, val_len, err, timeout = 10; |
421 | 434 | ||
422 | if (cval->mixer->protocol == UAC_VERSION_1) { | 435 | if (cval->mixer->protocol == UAC_VERSION_1) { |
423 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 436 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
@@ -440,19 +453,27 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
440 | err = snd_usb_autoresume(chip); | 453 | err = snd_usb_autoresume(chip); |
441 | if (err < 0) | 454 | if (err < 0) |
442 | return -EIO; | 455 | return -EIO; |
443 | while (timeout-- > 0) | 456 | down_read(&chip->shutdown_rwsem); |
457 | while (timeout-- > 0) { | ||
458 | if (chip->shutdown) | ||
459 | break; | ||
460 | idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); | ||
444 | if (snd_usb_ctl_msg(chip->dev, | 461 | if (snd_usb_ctl_msg(chip->dev, |
445 | usb_sndctrlpipe(chip->dev, 0), request, | 462 | usb_sndctrlpipe(chip->dev, 0), request, |
446 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 463 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
447 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 464 | validx, idx, buf, val_len) >= 0) { |
448 | buf, val_len) >= 0) { | 465 | err = 0; |
449 | snd_usb_autosuspend(chip); | 466 | goto out; |
450 | return 0; | ||
451 | } | 467 | } |
452 | snd_usb_autosuspend(chip); | 468 | } |
453 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", | 469 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", |
454 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); | 470 | request, validx, idx, cval->val_type, buf[0], buf[1]); |
455 | return -EINVAL; | 471 | err = -EINVAL; |
472 | |||
473 | out: | ||
474 | up_read(&chip->shutdown_rwsem); | ||
475 | snd_usb_autosuspend(chip); | ||
476 | return err; | ||
456 | } | 477 | } |
457 | 478 | ||
458 | static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) | 479 | static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) |
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 690000db0ec0..ae2b71435220 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -283,6 +283,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
283 | if (value > 1) | 283 | if (value > 1) |
284 | return -EINVAL; | 284 | return -EINVAL; |
285 | changed = value != mixer->audigy2nx_leds[index]; | 285 | changed = value != mixer->audigy2nx_leds[index]; |
286 | down_read(&mixer->chip->shutdown_rwsem); | ||
287 | if (mixer->chip->shutdown) { | ||
288 | err = -ENODEV; | ||
289 | goto out; | ||
290 | } | ||
286 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) | 291 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) |
287 | err = snd_usb_ctl_msg(mixer->chip->dev, | 292 | err = snd_usb_ctl_msg(mixer->chip->dev, |
288 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | 293 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, |
@@ -299,6 +304,8 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
299 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | 304 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, |
300 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 305 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
301 | value, index + 2, NULL, 0); | 306 | value, index + 2, NULL, 0); |
307 | out: | ||
308 | up_read(&mixer->chip->shutdown_rwsem); | ||
302 | if (err < 0) | 309 | if (err < 0) |
303 | return err; | 310 | return err; |
304 | mixer->audigy2nx_leds[index] = value; | 311 | mixer->audigy2nx_leds[index] = value; |
@@ -392,11 +399,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, | |||
392 | 399 | ||
393 | for (i = 0; jacks[i].name; ++i) { | 400 | for (i = 0; jacks[i].name; ++i) { |
394 | snd_iprintf(buffer, "%s: ", jacks[i].name); | 401 | snd_iprintf(buffer, "%s: ", jacks[i].name); |
395 | err = snd_usb_ctl_msg(mixer->chip->dev, | 402 | down_read(&mixer->chip->shutdown_rwsem); |
403 | if (mixer->chip->shutdown) | ||
404 | err = 0; | ||
405 | else | ||
406 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
396 | usb_rcvctrlpipe(mixer->chip->dev, 0), | 407 | usb_rcvctrlpipe(mixer->chip->dev, 0), |
397 | UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | | 408 | UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | |
398 | USB_RECIP_INTERFACE, 0, | 409 | USB_RECIP_INTERFACE, 0, |
399 | jacks[i].unitid << 8, buf, 3); | 410 | jacks[i].unitid << 8, buf, 3); |
411 | up_read(&mixer->chip->shutdown_rwsem); | ||
400 | if (err == 3 && (buf[0] == 3 || buf[0] == 6)) | 412 | if (err == 3 && (buf[0] == 3 || buf[0] == 6)) |
401 | snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); | 413 | snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); |
402 | else | 414 | else |
@@ -426,10 +438,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, | |||
426 | else | 438 | else |
427 | new_status = old_status & ~0x02; | 439 | new_status = old_status & ~0x02; |
428 | changed = new_status != old_status; | 440 | changed = new_status != old_status; |
429 | err = snd_usb_ctl_msg(mixer->chip->dev, | 441 | down_read(&mixer->chip->shutdown_rwsem); |
442 | if (mixer->chip->shutdown) | ||
443 | err = -ENODEV; | ||
444 | else | ||
445 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
430 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, | 446 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, |
431 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 447 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
432 | 50, 0, &new_status, 1); | 448 | 50, 0, &new_status, 1); |
449 | up_read(&mixer->chip->shutdown_rwsem); | ||
433 | if (err < 0) | 450 | if (err < 0) |
434 | return err; | 451 | return err; |
435 | mixer->xonar_u1_status = new_status; | 452 | mixer->xonar_u1_status = new_status; |
@@ -468,11 +485,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, | |||
468 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; | 485 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; |
469 | u16 wIndex = kcontrol->private_value & 0xffff; | 486 | u16 wIndex = kcontrol->private_value & 0xffff; |
470 | u8 tmp; | 487 | u8 tmp; |
488 | int ret; | ||
471 | 489 | ||
472 | int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, | 490 | down_read(&mixer->chip->shutdown_rwsem); |
491 | if (mixer->chip->shutdown) | ||
492 | ret = -ENODEV; | ||
493 | else | ||
494 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, | ||
473 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | 495 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, |
474 | 0, cpu_to_le16(wIndex), | 496 | 0, cpu_to_le16(wIndex), |
475 | &tmp, sizeof(tmp), 1000); | 497 | &tmp, sizeof(tmp), 1000); |
498 | up_read(&mixer->chip->shutdown_rwsem); | ||
476 | 499 | ||
477 | if (ret < 0) { | 500 | if (ret < 0) { |
478 | snd_printk(KERN_ERR | 501 | snd_printk(KERN_ERR |
@@ -493,11 +516,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, | |||
493 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; | 516 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; |
494 | u16 wIndex = kcontrol->private_value & 0xffff; | 517 | u16 wIndex = kcontrol->private_value & 0xffff; |
495 | u16 wValue = ucontrol->value.integer.value[0]; | 518 | u16 wValue = ucontrol->value.integer.value[0]; |
519 | int ret; | ||
496 | 520 | ||
497 | int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, | 521 | down_read(&mixer->chip->shutdown_rwsem); |
522 | if (mixer->chip->shutdown) | ||
523 | ret = -ENODEV; | ||
524 | else | ||
525 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, | ||
498 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | 526 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, |
499 | cpu_to_le16(wValue), cpu_to_le16(wIndex), | 527 | cpu_to_le16(wValue), cpu_to_le16(wIndex), |
500 | NULL, 0, 1000); | 528 | NULL, 0, 1000); |
529 | up_read(&mixer->chip->shutdown_rwsem); | ||
501 | 530 | ||
502 | if (ret < 0) { | 531 | if (ret < 0) { |
503 | snd_printk(KERN_ERR | 532 | snd_printk(KERN_ERR |
@@ -656,11 +685,16 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, | |||
656 | return -EINVAL; | 685 | return -EINVAL; |
657 | 686 | ||
658 | 687 | ||
659 | err = snd_usb_ctl_msg(chip->dev, | 688 | down_read(&mixer->chip->shutdown_rwsem); |
689 | if (mixer->chip->shutdown) | ||
690 | err = -ENODEV; | ||
691 | else | ||
692 | err = snd_usb_ctl_msg(chip->dev, | ||
660 | usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, | 693 | usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, |
661 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 694 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
662 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), | 695 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), |
663 | value, val_len); | 696 | value, val_len); |
697 | up_read(&mixer->chip->shutdown_rwsem); | ||
664 | if (err < 0) | 698 | if (err < 0) |
665 | return err; | 699 | return err; |
666 | 700 | ||
@@ -703,11 +737,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, | |||
703 | 737 | ||
704 | if (!pval->is_cached) { | 738 | if (!pval->is_cached) { |
705 | /* Read current value */ | 739 | /* Read current value */ |
706 | err = snd_usb_ctl_msg(chip->dev, | 740 | down_read(&mixer->chip->shutdown_rwsem); |
741 | if (mixer->chip->shutdown) | ||
742 | err = -ENODEV; | ||
743 | else | ||
744 | err = snd_usb_ctl_msg(chip->dev, | ||
707 | usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, | 745 | usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, |
708 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 746 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
709 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), | 747 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), |
710 | value, val_len); | 748 | value, val_len); |
749 | up_read(&mixer->chip->shutdown_rwsem); | ||
711 | if (err < 0) | 750 | if (err < 0) |
712 | return err; | 751 | return err; |
713 | 752 | ||
@@ -719,11 +758,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, | |||
719 | if (cur_val != new_val) { | 758 | if (cur_val != new_val) { |
720 | value[0] = new_val; | 759 | value[0] = new_val; |
721 | value[1] = 0; | 760 | value[1] = 0; |
722 | err = snd_usb_ctl_msg(chip->dev, | 761 | down_read(&mixer->chip->shutdown_rwsem); |
762 | if (mixer->chip->shutdown) | ||
763 | err = -ENODEV; | ||
764 | else | ||
765 | err = snd_usb_ctl_msg(chip->dev, | ||
723 | usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, | 766 | usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, |
724 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 767 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
725 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), | 768 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), |
726 | value, val_len); | 769 | value, val_len); |
770 | up_read(&mixer->chip->shutdown_rwsem); | ||
727 | if (err < 0) | 771 | if (err < 0) |
728 | return err; | 772 | return err; |
729 | 773 | ||
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 55e19e1b80ec..5c12a3fe8c3e 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
@@ -71,6 +71,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream | |||
71 | unsigned int hwptr_done; | 71 | unsigned int hwptr_done; |
72 | 72 | ||
73 | subs = (struct snd_usb_substream *)substream->runtime->private_data; | 73 | subs = (struct snd_usb_substream *)substream->runtime->private_data; |
74 | if (subs->stream->chip->shutdown) | ||
75 | return SNDRV_PCM_POS_XRUN; | ||
74 | spin_lock(&subs->lock); | 76 | spin_lock(&subs->lock); |
75 | hwptr_done = subs->hwptr_done; | 77 | hwptr_done = subs->hwptr_done; |
76 | substream->runtime->delay = snd_usb_pcm_delay(subs, | 78 | substream->runtime->delay = snd_usb_pcm_delay(subs, |
@@ -444,7 +446,6 @@ static int configure_endpoint(struct snd_usb_substream *subs) | |||
444 | { | 446 | { |
445 | int ret; | 447 | int ret; |
446 | 448 | ||
447 | mutex_lock(&subs->stream->chip->shutdown_mutex); | ||
448 | /* format changed */ | 449 | /* format changed */ |
449 | stop_endpoints(subs, 0, 0, 0); | 450 | stop_endpoints(subs, 0, 0, 0); |
450 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, | 451 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, |
@@ -455,7 +456,7 @@ static int configure_endpoint(struct snd_usb_substream *subs) | |||
455 | subs->cur_audiofmt, | 456 | subs->cur_audiofmt, |
456 | subs->sync_endpoint); | 457 | subs->sync_endpoint); |
457 | if (ret < 0) | 458 | if (ret < 0) |
458 | goto unlock; | 459 | return ret; |
459 | 460 | ||
460 | if (subs->sync_endpoint) | 461 | if (subs->sync_endpoint) |
461 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, | 462 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, |
@@ -465,9 +466,6 @@ static int configure_endpoint(struct snd_usb_substream *subs) | |||
465 | subs->cur_rate, | 466 | subs->cur_rate, |
466 | subs->cur_audiofmt, | 467 | subs->cur_audiofmt, |
467 | NULL); | 468 | NULL); |
468 | |||
469 | unlock: | ||
470 | mutex_unlock(&subs->stream->chip->shutdown_mutex); | ||
471 | return ret; | 469 | return ret; |
472 | } | 470 | } |
473 | 471 | ||
@@ -505,7 +503,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
505 | return -EINVAL; | 503 | return -EINVAL; |
506 | } | 504 | } |
507 | 505 | ||
508 | if ((ret = set_format(subs, fmt)) < 0) | 506 | down_read(&subs->stream->chip->shutdown_rwsem); |
507 | if (subs->stream->chip->shutdown) | ||
508 | ret = -ENODEV; | ||
509 | else | ||
510 | ret = set_format(subs, fmt); | ||
511 | up_read(&subs->stream->chip->shutdown_rwsem); | ||
512 | if (ret < 0) | ||
509 | return ret; | 513 | return ret; |
510 | 514 | ||
511 | subs->interface = fmt->iface; | 515 | subs->interface = fmt->iface; |
@@ -527,10 +531,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) | |||
527 | subs->cur_audiofmt = NULL; | 531 | subs->cur_audiofmt = NULL; |
528 | subs->cur_rate = 0; | 532 | subs->cur_rate = 0; |
529 | subs->period_bytes = 0; | 533 | subs->period_bytes = 0; |
530 | mutex_lock(&subs->stream->chip->shutdown_mutex); | 534 | down_read(&subs->stream->chip->shutdown_rwsem); |
531 | stop_endpoints(subs, 0, 1, 1); | 535 | if (!subs->stream->chip->shutdown) { |
532 | deactivate_endpoints(subs); | 536 | stop_endpoints(subs, 0, 1, 1); |
533 | mutex_unlock(&subs->stream->chip->shutdown_mutex); | 537 | deactivate_endpoints(subs); |
538 | } | ||
539 | up_read(&subs->stream->chip->shutdown_rwsem); | ||
534 | return snd_pcm_lib_free_vmalloc_buffer(substream); | 540 | return snd_pcm_lib_free_vmalloc_buffer(substream); |
535 | } | 541 | } |
536 | 542 | ||
@@ -552,12 +558,22 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) | |||
552 | return -ENXIO; | 558 | return -ENXIO; |
553 | } | 559 | } |
554 | 560 | ||
555 | if (snd_BUG_ON(!subs->data_endpoint)) | 561 | down_read(&subs->stream->chip->shutdown_rwsem); |
556 | return -EIO; | 562 | if (subs->stream->chip->shutdown) { |
563 | ret = -ENODEV; | ||
564 | goto unlock; | ||
565 | } | ||
566 | if (snd_BUG_ON(!subs->data_endpoint)) { | ||
567 | ret = -EIO; | ||
568 | goto unlock; | ||
569 | } | ||
570 | |||
571 | snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); | ||
572 | snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); | ||
557 | 573 | ||
558 | ret = set_format(subs, subs->cur_audiofmt); | 574 | ret = set_format(subs, subs->cur_audiofmt); |
559 | if (ret < 0) | 575 | if (ret < 0) |
560 | return ret; | 576 | goto unlock; |
561 | 577 | ||
562 | iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); | 578 | iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); |
563 | alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; | 579 | alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; |
@@ -567,12 +583,12 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) | |||
567 | subs->cur_audiofmt, | 583 | subs->cur_audiofmt, |
568 | subs->cur_rate); | 584 | subs->cur_rate); |
569 | if (ret < 0) | 585 | if (ret < 0) |
570 | return ret; | 586 | goto unlock; |
571 | 587 | ||
572 | if (subs->need_setup_ep) { | 588 | if (subs->need_setup_ep) { |
573 | ret = configure_endpoint(subs); | 589 | ret = configure_endpoint(subs); |
574 | if (ret < 0) | 590 | if (ret < 0) |
575 | return ret; | 591 | goto unlock; |
576 | subs->need_setup_ep = false; | 592 | subs->need_setup_ep = false; |
577 | } | 593 | } |
578 | 594 | ||
@@ -592,9 +608,11 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) | |||
592 | /* for playback, submit the URBs now; otherwise, the first hwptr_done | 608 | /* for playback, submit the URBs now; otherwise, the first hwptr_done |
593 | * updates for all URBs would happen at the same time when starting */ | 609 | * updates for all URBs would happen at the same time when starting */ |
594 | if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) | 610 | if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) |
595 | return start_endpoints(subs, 1); | 611 | ret = start_endpoints(subs, 1); |
596 | 612 | ||
597 | return 0; | 613 | unlock: |
614 | up_read(&subs->stream->chip->shutdown_rwsem); | ||
615 | return ret; | ||
598 | } | 616 | } |
599 | 617 | ||
600 | static struct snd_pcm_hardware snd_usb_hardware = | 618 | static struct snd_pcm_hardware snd_usb_hardware = |
@@ -647,7 +665,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs, | |||
647 | return 0; | 665 | return 0; |
648 | } | 666 | } |
649 | /* check whether the period time is >= the data packet interval */ | 667 | /* check whether the period time is >= the data packet interval */ |
650 | if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) { | 668 | if (subs->speed != USB_SPEED_FULL) { |
651 | ptime = 125 * (1 << fp->datainterval); | 669 | ptime = 125 * (1 << fp->datainterval); |
652 | if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { | 670 | if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { |
653 | hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); | 671 | hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); |
@@ -925,7 +943,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre | |||
925 | return err; | 943 | return err; |
926 | 944 | ||
927 | param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; | 945 | param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; |
928 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) | 946 | if (subs->speed == USB_SPEED_FULL) |
929 | /* full speed devices have fixed data packet interval */ | 947 | /* full speed devices have fixed data packet interval */ |
930 | ptmin = 1000; | 948 | ptmin = 1000; |
931 | if (ptmin == 1000) | 949 | if (ptmin == 1000) |
diff --git a/sound/usb/proc.c b/sound/usb/proc.c index ebc1a5b5b3f1..d218f763501f 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c | |||
@@ -108,7 +108,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s | |||
108 | } | 108 | } |
109 | snd_iprintf(buffer, "\n"); | 109 | snd_iprintf(buffer, "\n"); |
110 | } | 110 | } |
111 | if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) | 111 | if (subs->speed != USB_SPEED_FULL) |
112 | snd_iprintf(buffer, " Data packet interval: %d us\n", | 112 | snd_iprintf(buffer, " Data packet interval: %d us\n", |
113 | 125 * (1 << fp->datainterval)); | 113 | 125 * (1 << fp->datainterval)); |
114 | // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); | 114 | // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); |
@@ -124,7 +124,7 @@ static void proc_dump_ep_status(struct snd_usb_substream *subs, | |||
124 | return; | 124 | return; |
125 | snd_iprintf(buffer, " Packet Size = %d\n", ep->curpacksize); | 125 | snd_iprintf(buffer, " Packet Size = %d\n", ep->curpacksize); |
126 | snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n", | 126 | snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n", |
127 | snd_usb_get_speed(subs->dev) == USB_SPEED_FULL | 127 | subs->speed == USB_SPEED_FULL |
128 | ? get_full_speed_hz(ep->freqm) | 128 | ? get_full_speed_hz(ep->freqm) |
129 | : get_high_speed_hz(ep->freqm), | 129 | : get_high_speed_hz(ep->freqm), |
130 | ep->freqm >> 16, ep->freqm & 0xffff); | 130 | ep->freqm >> 16, ep->freqm & 0xffff); |
diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 083ed81160e5..1de0c8c002a8 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c | |||
@@ -90,6 +90,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, | |||
90 | subs->direction = stream; | 90 | subs->direction = stream; |
91 | subs->dev = as->chip->dev; | 91 | subs->dev = as->chip->dev; |
92 | subs->txfr_quirk = as->chip->txfr_quirk; | 92 | subs->txfr_quirk = as->chip->txfr_quirk; |
93 | subs->speed = snd_usb_get_speed(subs->dev); | ||
93 | 94 | ||
94 | snd_usb_set_pcm_ops(as->pcm, stream); | 95 | snd_usb_set_pcm_ops(as->pcm, stream); |
95 | 96 | ||
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index b8233ebe250f..ef42797f56fb 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h | |||
@@ -37,7 +37,7 @@ struct snd_usb_audio { | |||
37 | struct usb_interface *pm_intf; | 37 | struct usb_interface *pm_intf; |
38 | u32 usb_id; | 38 | u32 usb_id; |
39 | struct mutex mutex; | 39 | struct mutex mutex; |
40 | struct mutex shutdown_mutex; | 40 | struct rw_semaphore shutdown_rwsem; |
41 | unsigned int shutdown:1; | 41 | unsigned int shutdown:1; |
42 | unsigned int probing:1; | 42 | unsigned int probing:1; |
43 | unsigned int autosuspended:1; | 43 | unsigned int autosuspended:1; |