diff options
Diffstat (limited to 'sound')
45 files changed, 618 insertions, 281 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..a9a2e63c0222 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,6 +73,7 @@ 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 | } |
73 | return 0; | 79 | return 0; |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 08fde0060fd9..f337b66a020b 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; |
@@ -2457,6 +2461,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) | |||
2457 | __error2: | 2461 | __error2: |
2458 | snd_card_file_remove(pcm->card, file); | 2462 | snd_card_file_remove(pcm->card, file); |
2459 | __error1: | 2463 | __error1: |
2464 | if (pcm) | ||
2465 | snd_card_unref(pcm->card); | ||
2460 | return err; | 2466 | return err; |
2461 | } | 2467 | } |
2462 | 2468 | ||
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..6e8872de5ba0 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,9 @@ 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 | snd_card_unref(pcm->card); | ||
2126 | return err; | ||
2112 | } | 2127 | } |
2113 | 2128 | ||
2114 | static int snd_pcm_capture_open(struct inode *inode, struct file *file) | 2129 | static int snd_pcm_capture_open(struct inode *inode, struct file *file) |
@@ -2119,7 +2134,9 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) | |||
2119 | return err; | 2134 | return err; |
2120 | pcm = snd_lookup_minor_data(iminor(inode), | 2135 | pcm = snd_lookup_minor_data(iminor(inode), |
2121 | SNDRV_DEVICE_TYPE_PCM_CAPTURE); | 2136 | SNDRV_DEVICE_TYPE_PCM_CAPTURE); |
2122 | return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); | 2137 | err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); |
2138 | snd_card_unref(pcm->card); | ||
2139 | return err; | ||
2123 | } | 2140 | } |
2124 | 2141 | ||
2125 | static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) | 2142 | static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) |
@@ -2156,6 +2173,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) | |||
2156 | mutex_unlock(&pcm->open_mutex); | 2173 | mutex_unlock(&pcm->open_mutex); |
2157 | schedule(); | 2174 | schedule(); |
2158 | mutex_lock(&pcm->open_mutex); | 2175 | mutex_lock(&pcm->open_mutex); |
2176 | if (pcm->card->shutdown) { | ||
2177 | err = -ENODEV; | ||
2178 | break; | ||
2179 | } | ||
2159 | if (signal_pending(current)) { | 2180 | if (signal_pending(current)) { |
2160 | err = -ERESTARTSYS; | 2181 | err = -ERESTARTSYS; |
2161 | break; | 2182 | 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..89780c323f19 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 (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..e1d79ee35906 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 (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/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 3d1afb612b35..4a7ff4e8985b 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c | |||
@@ -1286,7 +1286,6 @@ static int __devinit snd_miro_probe(struct snd_card *card) | |||
1286 | 1286 | ||
1287 | error = snd_card_miro_aci_detect(card, miro); | 1287 | error = snd_card_miro_aci_detect(card, miro); |
1288 | if (error < 0) { | 1288 | if (error < 0) { |
1289 | snd_card_free(card); | ||
1290 | snd_printk(KERN_ERR "unable to detect aci chip\n"); | 1289 | snd_printk(KERN_ERR "unable to detect aci chip\n"); |
1291 | return -ENODEV; | 1290 | return -ENODEV; |
1292 | } | 1291 | } |
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 9473fca9681d..8b0f99688303 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
@@ -1271,6 +1271,8 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne | |||
1271 | tmp.index = ac97->num; | 1271 | tmp.index = ac97->num; |
1272 | kctl = snd_ctl_new1(&tmp, ac97); | 1272 | kctl = snd_ctl_new1(&tmp, ac97); |
1273 | } | 1273 | } |
1274 | if (!kctl) | ||
1275 | return -ENOMEM; | ||
1274 | if (reg >= AC97_PHONE && reg <= AC97_PCM) | 1276 | if (reg >= AC97_PHONE && reg <= AC97_PCM) |
1275 | set_tlv_db_scale(kctl, db_scale_5bit_12db_max); | 1277 | set_tlv_db_scale(kctl, db_scale_5bit_12db_max); |
1276 | else | 1278 | else |
diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 00f157a2cf64..5af3cb6b0c18 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c | |||
@@ -394,6 +394,8 @@ static int snd_als300_playback_open(struct snd_pcm_substream *substream) | |||
394 | struct snd_als300_substream_data *data = kzalloc(sizeof(*data), | 394 | struct snd_als300_substream_data *data = kzalloc(sizeof(*data), |
395 | GFP_KERNEL); | 395 | GFP_KERNEL); |
396 | 396 | ||
397 | if (!data) | ||
398 | return -ENOMEM; | ||
397 | snd_als300_dbgcallenter(); | 399 | snd_als300_dbgcallenter(); |
398 | chip->playback_substream = substream; | 400 | chip->playback_substream = substream; |
399 | runtime->hw = snd_als300_playback_hw; | 401 | runtime->hw = snd_als300_playback_hw; |
@@ -425,6 +427,8 @@ static int snd_als300_capture_open(struct snd_pcm_substream *substream) | |||
425 | struct snd_als300_substream_data *data = kzalloc(sizeof(*data), | 427 | struct snd_als300_substream_data *data = kzalloc(sizeof(*data), |
426 | GFP_KERNEL); | 428 | GFP_KERNEL); |
427 | 429 | ||
430 | if (!data) | ||
431 | return -ENOMEM; | ||
428 | snd_als300_dbgcallenter(); | 432 | snd_als300_dbgcallenter(); |
429 | chip->capture_substream = substream; | 433 | chip->capture_substream = substream; |
430 | runtime->hw = snd_als300_capture_hw; | 434 | runtime->hw = snd_als300_capture_hw; |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index bed4485f34f6..c21adb6ef1d5 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -1416,6 +1416,15 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1416 | .ca0108_chip = 1, | 1416 | .ca0108_chip = 1, |
1417 | .spk71 = 1, | 1417 | .spk71 = 1, |
1418 | .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */ | 1418 | .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */ |
1419 | /* Tested by Maxim Kachur <mcdebugger@duganet.ru> 17th Oct 2012. */ | ||
1420 | /* This is MAEM8986, 0202 is MAEM8980 */ | ||
1421 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40071102, | ||
1422 | .driver = "Audigy2", .name = "E-mu 1010 PCIe [MAEM8986]", | ||
1423 | .id = "EMU1010", | ||
1424 | .emu10k2_chip = 1, | ||
1425 | .ca0108_chip = 1, | ||
1426 | .spk71 = 1, | ||
1427 | .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 PCIe */ | ||
1419 | /* Tested by James@superbug.co.uk 8th July 2005. */ | 1428 | /* Tested by James@superbug.co.uk 8th July 2005. */ |
1420 | /* This is MAEM8810, 0202 is MAEM8820 */ | 1429 | /* This is MAEM8810, 0202 is MAEM8820 */ |
1421 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, | 1430 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 6833835a218b..72b085ae7d46 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -501,6 +501,7 @@ struct azx { | |||
501 | 501 | ||
502 | /* VGA-switcheroo setup */ | 502 | /* VGA-switcheroo setup */ |
503 | unsigned int use_vga_switcheroo:1; | 503 | unsigned int use_vga_switcheroo:1; |
504 | unsigned int vga_switcheroo_registered:1; | ||
504 | unsigned int init_failed:1; /* delayed init failed */ | 505 | unsigned int init_failed:1; /* delayed init failed */ |
505 | unsigned int disabled:1; /* disabled by VGA-switcher */ | 506 | unsigned int disabled:1; /* disabled by VGA-switcher */ |
506 | 507 | ||
@@ -2157,9 +2158,12 @@ static unsigned int azx_get_position(struct azx *chip, | |||
2157 | if (delay < 0) | 2158 | if (delay < 0) |
2158 | delay += azx_dev->bufsize; | 2159 | delay += azx_dev->bufsize; |
2159 | if (delay >= azx_dev->period_bytes) { | 2160 | if (delay >= azx_dev->period_bytes) { |
2160 | snd_printdd("delay %d > period_bytes %d\n", | 2161 | snd_printk(KERN_WARNING SFX |
2161 | delay, azx_dev->period_bytes); | 2162 | "Unstable LPIB (%d >= %d); " |
2162 | delay = 0; /* something is wrong */ | 2163 | "disabling LPIB delay counting\n", |
2164 | delay, azx_dev->period_bytes); | ||
2165 | delay = 0; | ||
2166 | chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; | ||
2163 | } | 2167 | } |
2164 | azx_dev->substream->runtime->delay = | 2168 | azx_dev->substream->runtime->delay = |
2165 | bytes_to_frames(azx_dev->substream->runtime, delay); | 2169 | bytes_to_frames(azx_dev->substream->runtime, delay); |
@@ -2640,7 +2644,9 @@ static void azx_vs_set_state(struct pci_dev *pci, | |||
2640 | if (disabled) { | 2644 | if (disabled) { |
2641 | azx_suspend(&pci->dev); | 2645 | azx_suspend(&pci->dev); |
2642 | chip->disabled = true; | 2646 | chip->disabled = true; |
2643 | snd_hda_lock_devices(chip->bus); | 2647 | if (snd_hda_lock_devices(chip->bus)) |
2648 | snd_printk(KERN_WARNING SFX | ||
2649 | "Cannot lock devices!\n"); | ||
2644 | } else { | 2650 | } else { |
2645 | snd_hda_unlock_devices(chip->bus); | 2651 | snd_hda_unlock_devices(chip->bus); |
2646 | chip->disabled = false; | 2652 | chip->disabled = false; |
@@ -2683,14 +2689,20 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = { | |||
2683 | 2689 | ||
2684 | static int __devinit register_vga_switcheroo(struct azx *chip) | 2690 | static int __devinit register_vga_switcheroo(struct azx *chip) |
2685 | { | 2691 | { |
2692 | int err; | ||
2693 | |||
2686 | if (!chip->use_vga_switcheroo) | 2694 | if (!chip->use_vga_switcheroo) |
2687 | return 0; | 2695 | return 0; |
2688 | /* FIXME: currently only handling DIS controller | 2696 | /* FIXME: currently only handling DIS controller |
2689 | * is there any machine with two switchable HDMI audio controllers? | 2697 | * is there any machine with two switchable HDMI audio controllers? |
2690 | */ | 2698 | */ |
2691 | return vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, | 2699 | err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, |
2692 | VGA_SWITCHEROO_DIS, | 2700 | VGA_SWITCHEROO_DIS, |
2693 | chip->bus != NULL); | 2701 | chip->bus != NULL); |
2702 | if (err < 0) | ||
2703 | return err; | ||
2704 | chip->vga_switcheroo_registered = 1; | ||
2705 | return 0; | ||
2694 | } | 2706 | } |
2695 | #else | 2707 | #else |
2696 | #define init_vga_switcheroo(chip) /* NOP */ | 2708 | #define init_vga_switcheroo(chip) /* NOP */ |
@@ -2712,7 +2724,8 @@ static int azx_free(struct azx *chip) | |||
2712 | if (use_vga_switcheroo(chip)) { | 2724 | if (use_vga_switcheroo(chip)) { |
2713 | if (chip->disabled && chip->bus) | 2725 | if (chip->disabled && chip->bus) |
2714 | snd_hda_unlock_devices(chip->bus); | 2726 | snd_hda_unlock_devices(chip->bus); |
2715 | vga_switcheroo_unregister_client(chip->pci); | 2727 | if (chip->vga_switcheroo_registered) |
2728 | vga_switcheroo_unregister_client(chip->pci); | ||
2716 | } | 2729 | } |
2717 | 2730 | ||
2718 | if (chip->initialized) { | 2731 | if (chip->initialized) { |
@@ -2813,8 +2826,6 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { | |||
2813 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), | 2826 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), |
2814 | SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), | 2827 | SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), |
2815 | SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), | 2828 | SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), |
2816 | SND_PCI_QUIRK(0x1043, 0x1ac3, "ASUS X53S", POS_FIX_POSBUF), | ||
2817 | SND_PCI_QUIRK(0x1043, 0x1b43, "ASUS K53E", POS_FIX_POSBUF), | ||
2818 | SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), | 2829 | SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), |
2819 | SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB), | 2830 | SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB), |
2820 | SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB), | 2831 | SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB), |
@@ -3062,14 +3073,6 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
3062 | } | 3073 | } |
3063 | 3074 | ||
3064 | ok: | 3075 | ok: |
3065 | err = register_vga_switcheroo(chip); | ||
3066 | if (err < 0) { | ||
3067 | snd_printk(KERN_ERR SFX | ||
3068 | "Error registering VGA-switcheroo client\n"); | ||
3069 | azx_free(chip); | ||
3070 | return err; | ||
3071 | } | ||
3072 | |||
3073 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | 3076 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); |
3074 | if (err < 0) { | 3077 | if (err < 0) { |
3075 | snd_printk(KERN_ERR SFX "Error creating device [card]!\n"); | 3078 | snd_printk(KERN_ERR SFX "Error creating device [card]!\n"); |
@@ -3340,6 +3343,13 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
3340 | if (pci_dev_run_wake(pci)) | 3343 | if (pci_dev_run_wake(pci)) |
3341 | pm_runtime_put_noidle(&pci->dev); | 3344 | pm_runtime_put_noidle(&pci->dev); |
3342 | 3345 | ||
3346 | err = register_vga_switcheroo(chip); | ||
3347 | if (err < 0) { | ||
3348 | snd_printk(KERN_ERR SFX | ||
3349 | "Error registering VGA-switcheroo client\n"); | ||
3350 | goto out_free; | ||
3351 | } | ||
3352 | |||
3343 | dev++; | 3353 | dev++; |
3344 | return 0; | 3354 | return 0; |
3345 | 3355 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8253b4eeb6a1..f7397ad02a0d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -2598,8 +2598,10 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, | |||
2598 | return "PCM"; | 2598 | return "PCM"; |
2599 | break; | 2599 | break; |
2600 | } | 2600 | } |
2601 | if (snd_BUG_ON(ch >= ARRAY_SIZE(channel_name))) | 2601 | if (ch >= ARRAY_SIZE(channel_name)) { |
2602 | snd_BUG(); | ||
2602 | return "PCM"; | 2603 | return "PCM"; |
2604 | } | ||
2603 | 2605 | ||
2604 | return channel_name[ch]; | 2606 | return channel_name[ch]; |
2605 | } | 2607 | } |
@@ -5675,6 +5677,7 @@ static const struct hda_verb alc268_beep_init_verbs[] = { | |||
5675 | 5677 | ||
5676 | enum { | 5678 | enum { |
5677 | ALC268_FIXUP_INV_DMIC, | 5679 | ALC268_FIXUP_INV_DMIC, |
5680 | ALC268_FIXUP_HP_EAPD, | ||
5678 | }; | 5681 | }; |
5679 | 5682 | ||
5680 | static const struct alc_fixup alc268_fixups[] = { | 5683 | static const struct alc_fixup alc268_fixups[] = { |
@@ -5682,10 +5685,26 @@ static const struct alc_fixup alc268_fixups[] = { | |||
5682 | .type = ALC_FIXUP_FUNC, | 5685 | .type = ALC_FIXUP_FUNC, |
5683 | .v.func = alc_fixup_inv_dmic_0x12, | 5686 | .v.func = alc_fixup_inv_dmic_0x12, |
5684 | }, | 5687 | }, |
5688 | [ALC268_FIXUP_HP_EAPD] = { | ||
5689 | .type = ALC_FIXUP_VERBS, | ||
5690 | .v.verbs = (const struct hda_verb[]) { | ||
5691 | {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0}, | ||
5692 | {} | ||
5693 | } | ||
5694 | }, | ||
5685 | }; | 5695 | }; |
5686 | 5696 | ||
5687 | static const struct alc_model_fixup alc268_fixup_models[] = { | 5697 | static const struct alc_model_fixup alc268_fixup_models[] = { |
5688 | {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"}, | 5698 | {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"}, |
5699 | {.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"}, | ||
5700 | {} | ||
5701 | }; | ||
5702 | |||
5703 | static const struct snd_pci_quirk alc268_fixup_tbl[] = { | ||
5704 | /* below is codec SSID since multiple Toshiba laptops have the | ||
5705 | * same PCI SSID 1179:ff00 | ||
5706 | */ | ||
5707 | SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD), | ||
5689 | {} | 5708 | {} |
5690 | }; | 5709 | }; |
5691 | 5710 | ||
@@ -5720,7 +5739,7 @@ static int patch_alc268(struct hda_codec *codec) | |||
5720 | 5739 | ||
5721 | spec = codec->spec; | 5740 | spec = codec->spec; |
5722 | 5741 | ||
5723 | alc_pick_fixup(codec, alc268_fixup_models, NULL, alc268_fixups); | 5742 | alc_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups); |
5724 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); | 5743 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); |
5725 | 5744 | ||
5726 | /* automatic parse from the BIOS config */ | 5745 | /* automatic parse from the BIOS config */ |
@@ -6186,6 +6205,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
6186 | SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), | 6205 | SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), |
6187 | SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK), | 6206 | SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK), |
6188 | SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK), | 6207 | SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK), |
6208 | SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK), | ||
6189 | SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK), | 6209 | SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK), |
6190 | SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), | 6210 | SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), |
6191 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), | 6211 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), |
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/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 b12308b5ba2a..f1cd1e387801 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -971,6 +971,7 @@ static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm); | |||
971 | static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm); | 971 | static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm); |
972 | static int hdspm_autosync_ref(struct hdspm *hdspm); | 972 | static int hdspm_autosync_ref(struct hdspm *hdspm); |
973 | static int snd_hdspm_set_defaults(struct hdspm *hdspm); | 973 | static int snd_hdspm_set_defaults(struct hdspm *hdspm); |
974 | static int hdspm_system_clock_mode(struct hdspm *hdspm); | ||
974 | static void hdspm_set_sgbuf(struct hdspm *hdspm, | 975 | static void hdspm_set_sgbuf(struct hdspm *hdspm, |
975 | struct snd_pcm_substream *substream, | 976 | struct snd_pcm_substream *substream, |
976 | unsigned int reg, int channels); | 977 | unsigned int reg, int channels); |
@@ -1989,10 +1990,14 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm) | |||
1989 | rate = hdspm_calc_dds_value(hdspm, period); | 1990 | rate = hdspm_calc_dds_value(hdspm, period); |
1990 | 1991 | ||
1991 | if (rate > 207000) { | 1992 | if (rate > 207000) { |
1992 | /* Unreasonable high sample rate as seen on PCI MADI cards. | 1993 | /* Unreasonable high sample rate as seen on PCI MADI cards. */ |
1993 | * Use the cached value instead. | 1994 | if (0 == hdspm_system_clock_mode(hdspm)) { |
1994 | */ | 1995 | /* master mode, return internal sample rate */ |
1995 | rate = hdspm->system_sample_rate; | 1996 | rate = hdspm->system_sample_rate; |
1997 | } else { | ||
1998 | /* slave mode, return external sample rate */ | ||
1999 | rate = hdspm_external_sample_rate(hdspm); | ||
2000 | } | ||
1996 | } | 2001 | } |
1997 | 2002 | ||
1998 | return rate; | 2003 | return rate; |
@@ -2000,12 +2005,14 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm) | |||
2000 | 2005 | ||
2001 | 2006 | ||
2002 | #define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \ | 2007 | #define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \ |
2003 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2008 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2004 | .name = xname, \ | 2009 | .name = xname, \ |
2005 | .index = xindex, \ | 2010 | .index = xindex, \ |
2006 | .access = SNDRV_CTL_ELEM_ACCESS_READ, \ | 2011 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ |
2007 | .info = snd_hdspm_info_system_sample_rate, \ | 2012 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ |
2008 | .get = snd_hdspm_get_system_sample_rate \ | 2013 | .info = snd_hdspm_info_system_sample_rate, \ |
2014 | .put = snd_hdspm_put_system_sample_rate, \ | ||
2015 | .get = snd_hdspm_get_system_sample_rate \ | ||
2009 | } | 2016 | } |
2010 | 2017 | ||
2011 | static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol, | 2018 | static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol, |
@@ -2030,6 +2037,16 @@ static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol, | |||
2030 | return 0; | 2037 | return 0; |
2031 | } | 2038 | } |
2032 | 2039 | ||
2040 | static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol, | ||
2041 | struct snd_ctl_elem_value * | ||
2042 | ucontrol) | ||
2043 | { | ||
2044 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2045 | |||
2046 | hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]); | ||
2047 | return 0; | ||
2048 | } | ||
2049 | |||
2033 | 2050 | ||
2034 | /** | 2051 | /** |
2035 | * Returns the WordClock sample rate class for the given card. | 2052 | * Returns the WordClock sample rate class for the given card. |
@@ -2163,6 +2180,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, | |||
2163 | hdspm_get_s1_sample_rate(hdspm, | 2180 | hdspm_get_s1_sample_rate(hdspm, |
2164 | kcontrol->private_value-1); | 2181 | kcontrol->private_value-1); |
2165 | } | 2182 | } |
2183 | break; | ||
2166 | 2184 | ||
2167 | case AIO: | 2185 | case AIO: |
2168 | switch (kcontrol->private_value) { | 2186 | switch (kcontrol->private_value) { |
@@ -2183,6 +2201,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, | |||
2183 | hdspm_get_s1_sample_rate(hdspm, | 2201 | hdspm_get_s1_sample_rate(hdspm, |
2184 | ucontrol->id.index-1); | 2202 | ucontrol->id.index-1); |
2185 | } | 2203 | } |
2204 | break; | ||
2186 | 2205 | ||
2187 | case AES32: | 2206 | case AES32: |
2188 | 2207 | ||
@@ -2204,8 +2223,23 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, | |||
2204 | hdspm_get_s1_sample_rate(hdspm, | 2223 | hdspm_get_s1_sample_rate(hdspm, |
2205 | kcontrol->private_value-1); | 2224 | kcontrol->private_value-1); |
2206 | break; | 2225 | break; |
2226 | } | ||
2227 | break; | ||
2207 | 2228 | ||
2229 | case MADI: | ||
2230 | case MADIface: | ||
2231 | { | ||
2232 | int rate = hdspm_external_sample_rate(hdspm); | ||
2233 | int i, selected_rate = 0; | ||
2234 | for (i = 1; i < 10; i++) | ||
2235 | if (HDSPM_bit2freq(i) == rate) { | ||
2236 | selected_rate = i; | ||
2237 | break; | ||
2238 | } | ||
2239 | ucontrol->value.enumerated.item[0] = selected_rate; | ||
2208 | } | 2240 | } |
2241 | break; | ||
2242 | |||
2209 | default: | 2243 | default: |
2210 | break; | 2244 | break; |
2211 | } | 2245 | } |
@@ -2430,7 +2464,7 @@ static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol, | |||
2430 | 2464 | ||
2431 | 2465 | ||
2432 | #define HDSPM_PREF_SYNC_REF(xname, xindex) \ | 2466 | #define HDSPM_PREF_SYNC_REF(xname, xindex) \ |
2433 | {.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2467 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2434 | .name = xname, \ | 2468 | .name = xname, \ |
2435 | .index = xindex, \ | 2469 | .index = xindex, \ |
2436 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | 2470 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ |
@@ -2766,12 +2800,12 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol, | |||
2766 | 2800 | ||
2767 | 2801 | ||
2768 | #define HDSPM_AUTOSYNC_REF(xname, xindex) \ | 2802 | #define HDSPM_AUTOSYNC_REF(xname, xindex) \ |
2769 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2803 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2770 | .name = xname, \ | 2804 | .name = xname, \ |
2771 | .index = xindex, \ | 2805 | .index = xindex, \ |
2772 | .access = SNDRV_CTL_ELEM_ACCESS_READ, \ | 2806 | .access = SNDRV_CTL_ELEM_ACCESS_READ, \ |
2773 | .info = snd_hdspm_info_autosync_ref, \ | 2807 | .info = snd_hdspm_info_autosync_ref, \ |
2774 | .get = snd_hdspm_get_autosync_ref, \ | 2808 | .get = snd_hdspm_get_autosync_ref, \ |
2775 | } | 2809 | } |
2776 | 2810 | ||
2777 | static int hdspm_autosync_ref(struct hdspm *hdspm) | 2811 | static int hdspm_autosync_ref(struct hdspm *hdspm) |
@@ -2855,12 +2889,12 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol, | |||
2855 | 2889 | ||
2856 | 2890 | ||
2857 | #define HDSPM_LINE_OUT(xname, xindex) \ | 2891 | #define HDSPM_LINE_OUT(xname, xindex) \ |
2858 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2892 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2859 | .name = xname, \ | 2893 | .name = xname, \ |
2860 | .index = xindex, \ | 2894 | .index = xindex, \ |
2861 | .info = snd_hdspm_info_line_out, \ | 2895 | .info = snd_hdspm_info_line_out, \ |
2862 | .get = snd_hdspm_get_line_out, \ | 2896 | .get = snd_hdspm_get_line_out, \ |
2863 | .put = snd_hdspm_put_line_out \ | 2897 | .put = snd_hdspm_put_line_out \ |
2864 | } | 2898 | } |
2865 | 2899 | ||
2866 | static int hdspm_line_out(struct hdspm * hdspm) | 2900 | static int hdspm_line_out(struct hdspm * hdspm) |
@@ -2912,12 +2946,12 @@ static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol, | |||
2912 | 2946 | ||
2913 | 2947 | ||
2914 | #define HDSPM_TX_64(xname, xindex) \ | 2948 | #define HDSPM_TX_64(xname, xindex) \ |
2915 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2949 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2916 | .name = xname, \ | 2950 | .name = xname, \ |
2917 | .index = xindex, \ | 2951 | .index = xindex, \ |
2918 | .info = snd_hdspm_info_tx_64, \ | 2952 | .info = snd_hdspm_info_tx_64, \ |
2919 | .get = snd_hdspm_get_tx_64, \ | 2953 | .get = snd_hdspm_get_tx_64, \ |
2920 | .put = snd_hdspm_put_tx_64 \ | 2954 | .put = snd_hdspm_put_tx_64 \ |
2921 | } | 2955 | } |
2922 | 2956 | ||
2923 | static int hdspm_tx_64(struct hdspm * hdspm) | 2957 | static int hdspm_tx_64(struct hdspm * hdspm) |
@@ -2968,12 +3002,12 @@ static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol, | |||
2968 | 3002 | ||
2969 | 3003 | ||
2970 | #define HDSPM_C_TMS(xname, xindex) \ | 3004 | #define HDSPM_C_TMS(xname, xindex) \ |
2971 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3005 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2972 | .name = xname, \ | 3006 | .name = xname, \ |
2973 | .index = xindex, \ | 3007 | .index = xindex, \ |
2974 | .info = snd_hdspm_info_c_tms, \ | 3008 | .info = snd_hdspm_info_c_tms, \ |
2975 | .get = snd_hdspm_get_c_tms, \ | 3009 | .get = snd_hdspm_get_c_tms, \ |
2976 | .put = snd_hdspm_put_c_tms \ | 3010 | .put = snd_hdspm_put_c_tms \ |
2977 | } | 3011 | } |
2978 | 3012 | ||
2979 | static int hdspm_c_tms(struct hdspm * hdspm) | 3013 | static int hdspm_c_tms(struct hdspm * hdspm) |
@@ -3024,12 +3058,12 @@ static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol, | |||
3024 | 3058 | ||
3025 | 3059 | ||
3026 | #define HDSPM_SAFE_MODE(xname, xindex) \ | 3060 | #define HDSPM_SAFE_MODE(xname, xindex) \ |
3027 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3061 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
3028 | .name = xname, \ | 3062 | .name = xname, \ |
3029 | .index = xindex, \ | 3063 | .index = xindex, \ |
3030 | .info = snd_hdspm_info_safe_mode, \ | 3064 | .info = snd_hdspm_info_safe_mode, \ |
3031 | .get = snd_hdspm_get_safe_mode, \ | 3065 | .get = snd_hdspm_get_safe_mode, \ |
3032 | .put = snd_hdspm_put_safe_mode \ | 3066 | .put = snd_hdspm_put_safe_mode \ |
3033 | } | 3067 | } |
3034 | 3068 | ||
3035 | static int hdspm_safe_mode(struct hdspm * hdspm) | 3069 | static int hdspm_safe_mode(struct hdspm * hdspm) |
@@ -3080,12 +3114,12 @@ static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol, | |||
3080 | 3114 | ||
3081 | 3115 | ||
3082 | #define HDSPM_EMPHASIS(xname, xindex) \ | 3116 | #define HDSPM_EMPHASIS(xname, xindex) \ |
3083 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3117 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
3084 | .name = xname, \ | 3118 | .name = xname, \ |
3085 | .index = xindex, \ | 3119 | .index = xindex, \ |
3086 | .info = snd_hdspm_info_emphasis, \ | 3120 | .info = snd_hdspm_info_emphasis, \ |
3087 | .get = snd_hdspm_get_emphasis, \ | 3121 | .get = snd_hdspm_get_emphasis, \ |
3088 | .put = snd_hdspm_put_emphasis \ | 3122 | .put = snd_hdspm_put_emphasis \ |
3089 | } | 3123 | } |
3090 | 3124 | ||
3091 | static int hdspm_emphasis(struct hdspm * hdspm) | 3125 | static int hdspm_emphasis(struct hdspm * hdspm) |
@@ -3136,12 +3170,12 @@ static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol, | |||
3136 | 3170 | ||
3137 | 3171 | ||
3138 | #define HDSPM_DOLBY(xname, xindex) \ | 3172 | #define HDSPM_DOLBY(xname, xindex) \ |
3139 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3173 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
3140 | .name = xname, \ | 3174 | .name = xname, \ |
3141 | .index = xindex, \ | 3175 | .index = xindex, \ |
3142 | .info = snd_hdspm_info_dolby, \ | 3176 | .info = snd_hdspm_info_dolby, \ |
3143 | .get = snd_hdspm_get_dolby, \ | 3177 | .get = snd_hdspm_get_dolby, \ |
3144 | .put = snd_hdspm_put_dolby \ | 3178 | .put = snd_hdspm_put_dolby \ |
3145 | } | 3179 | } |
3146 | 3180 | ||
3147 | static int hdspm_dolby(struct hdspm * hdspm) | 3181 | static int hdspm_dolby(struct hdspm * hdspm) |
@@ -3192,12 +3226,12 @@ static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol, | |||
3192 | 3226 | ||
3193 | 3227 | ||
3194 | #define HDSPM_PROFESSIONAL(xname, xindex) \ | 3228 | #define HDSPM_PROFESSIONAL(xname, xindex) \ |
3195 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3229 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
3196 | .name = xname, \ | 3230 | .name = xname, \ |
3197 | .index = xindex, \ | 3231 | .index = xindex, \ |
3198 | .info = snd_hdspm_info_professional, \ | 3232 | .info = snd_hdspm_info_professional, \ |
3199 | .get = snd_hdspm_get_professional, \ | 3233 | .get = snd_hdspm_get_professional, \ |
3200 | .put = snd_hdspm_put_professional \ | 3234 | .put = snd_hdspm_put_professional \ |
3201 | } | 3235 | } |
3202 | 3236 | ||
3203 | static int hdspm_professional(struct hdspm * hdspm) | 3237 | static int hdspm_professional(struct hdspm * hdspm) |
@@ -3247,12 +3281,12 @@ static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol, | |||
3247 | } | 3281 | } |
3248 | 3282 | ||
3249 | #define HDSPM_INPUT_SELECT(xname, xindex) \ | 3283 | #define HDSPM_INPUT_SELECT(xname, xindex) \ |
3250 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3284 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
3251 | .name = xname, \ | 3285 | .name = xname, \ |
3252 | .index = xindex, \ | 3286 | .index = xindex, \ |
3253 | .info = snd_hdspm_info_input_select, \ | 3287 | .info = snd_hdspm_info_input_select, \ |
3254 | .get = snd_hdspm_get_input_select, \ | 3288 | .get = snd_hdspm_get_input_select, \ |
3255 | .put = snd_hdspm_put_input_select \ | 3289 | .put = snd_hdspm_put_input_select \ |
3256 | } | 3290 | } |
3257 | 3291 | ||
3258 | static int hdspm_input_select(struct hdspm * hdspm) | 3292 | static int hdspm_input_select(struct hdspm * hdspm) |
@@ -3319,12 +3353,12 @@ static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol, | |||
3319 | 3353 | ||
3320 | 3354 | ||
3321 | #define HDSPM_DS_WIRE(xname, xindex) \ | 3355 | #define HDSPM_DS_WIRE(xname, xindex) \ |
3322 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3356 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
3323 | .name = xname, \ | 3357 | .name = xname, \ |
3324 | .index = xindex, \ | 3358 | .index = xindex, \ |
3325 | .info = snd_hdspm_info_ds_wire, \ | 3359 | .info = snd_hdspm_info_ds_wire, \ |
3326 | .get = snd_hdspm_get_ds_wire, \ | 3360 | .get = snd_hdspm_get_ds_wire, \ |
3327 | .put = snd_hdspm_put_ds_wire \ | 3361 | .put = snd_hdspm_put_ds_wire \ |
3328 | } | 3362 | } |
3329 | 3363 | ||
3330 | static int hdspm_ds_wire(struct hdspm * hdspm) | 3364 | static int hdspm_ds_wire(struct hdspm * hdspm) |
@@ -3391,12 +3425,12 @@ static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol, | |||
3391 | 3425 | ||
3392 | 3426 | ||
3393 | #define HDSPM_QS_WIRE(xname, xindex) \ | 3427 | #define HDSPM_QS_WIRE(xname, xindex) \ |
3394 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3428 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
3395 | .name = xname, \ | 3429 | .name = xname, \ |
3396 | .index = xindex, \ | 3430 | .index = xindex, \ |
3397 | .info = snd_hdspm_info_qs_wire, \ | 3431 | .info = snd_hdspm_info_qs_wire, \ |
3398 | .get = snd_hdspm_get_qs_wire, \ | 3432 | .get = snd_hdspm_get_qs_wire, \ |
3399 | .put = snd_hdspm_put_qs_wire \ | 3433 | .put = snd_hdspm_put_qs_wire \ |
3400 | } | 3434 | } |
3401 | 3435 | ||
3402 | static int hdspm_qs_wire(struct hdspm * hdspm) | 3436 | static int hdspm_qs_wire(struct hdspm * hdspm) |
@@ -3563,15 +3597,15 @@ static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol, | |||
3563 | } | 3597 | } |
3564 | 3598 | ||
3565 | #define HDSPM_MIXER(xname, xindex) \ | 3599 | #define HDSPM_MIXER(xname, xindex) \ |
3566 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | 3600 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ |
3567 | .name = xname, \ | 3601 | .name = xname, \ |
3568 | .index = xindex, \ | 3602 | .index = xindex, \ |
3569 | .device = 0, \ | 3603 | .device = 0, \ |
3570 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | 3604 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ |
3571 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | 3605 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ |
3572 | .info = snd_hdspm_info_mixer, \ | 3606 | .info = snd_hdspm_info_mixer, \ |
3573 | .get = snd_hdspm_get_mixer, \ | 3607 | .get = snd_hdspm_get_mixer, \ |
3574 | .put = snd_hdspm_put_mixer \ | 3608 | .put = snd_hdspm_put_mixer \ |
3575 | } | 3609 | } |
3576 | 3610 | ||
3577 | static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol, | 3611 | static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol, |
@@ -3670,12 +3704,12 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol, | |||
3670 | */ | 3704 | */ |
3671 | 3705 | ||
3672 | #define HDSPM_PLAYBACK_MIXER \ | 3706 | #define HDSPM_PLAYBACK_MIXER \ |
3673 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3707 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
3674 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \ | 3708 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \ |
3675 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | 3709 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ |
3676 | .info = snd_hdspm_info_playback_mixer, \ | 3710 | .info = snd_hdspm_info_playback_mixer, \ |
3677 | .get = snd_hdspm_get_playback_mixer, \ | 3711 | .get = snd_hdspm_get_playback_mixer, \ |
3678 | .put = snd_hdspm_put_playback_mixer \ | 3712 | .put = snd_hdspm_put_playback_mixer \ |
3679 | } | 3713 | } |
3680 | 3714 | ||
3681 | static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol, | 3715 | static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol, |
@@ -3851,12 +3885,17 @@ static int hdspm_sync_in_sync_check(struct hdspm *hdspm) | |||
3851 | break; | 3885 | break; |
3852 | 3886 | ||
3853 | case MADI: | 3887 | case MADI: |
3854 | case AES32: | 3888 | status = hdspm_read(hdspm, HDSPM_statusRegister); |
3855 | status = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
3856 | lock = (status & HDSPM_syncInLock) ? 1 : 0; | 3889 | lock = (status & HDSPM_syncInLock) ? 1 : 0; |
3857 | sync = (status & HDSPM_syncInSync) ? 1 : 0; | 3890 | sync = (status & HDSPM_syncInSync) ? 1 : 0; |
3858 | break; | 3891 | break; |
3859 | 3892 | ||
3893 | case AES32: | ||
3894 | status = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
3895 | lock = (status & 0x100000) ? 1 : 0; | ||
3896 | sync = (status & 0x200000) ? 1 : 0; | ||
3897 | break; | ||
3898 | |||
3860 | case MADIface: | 3899 | case MADIface: |
3861 | break; | 3900 | break; |
3862 | } | 3901 | } |
@@ -3942,6 +3981,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol, | |||
3942 | default: | 3981 | default: |
3943 | val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1); | 3982 | val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1); |
3944 | } | 3983 | } |
3984 | break; | ||
3945 | 3985 | ||
3946 | case AIO: | 3986 | case AIO: |
3947 | switch (kcontrol->private_value) { | 3987 | switch (kcontrol->private_value) { |
@@ -3954,6 +3994,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol, | |||
3954 | default: | 3994 | default: |
3955 | val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1); | 3995 | val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1); |
3956 | } | 3996 | } |
3997 | break; | ||
3957 | 3998 | ||
3958 | case MADI: | 3999 | case MADI: |
3959 | switch (kcontrol->private_value) { | 4000 | switch (kcontrol->private_value) { |
@@ -3966,6 +4007,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol, | |||
3966 | case 3: /* SYNC_IN */ | 4007 | case 3: /* SYNC_IN */ |
3967 | val = hdspm_sync_in_sync_check(hdspm); break; | 4008 | val = hdspm_sync_in_sync_check(hdspm); break; |
3968 | } | 4009 | } |
4010 | break; | ||
3969 | 4011 | ||
3970 | case MADIface: | 4012 | case MADIface: |
3971 | val = hdspm_madi_sync_check(hdspm); /* MADI */ | 4013 | val = hdspm_madi_sync_check(hdspm); /* MADI */ |
@@ -3983,6 +4025,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol, | |||
3983 | val = hdspm_aes_sync_check(hdspm, | 4025 | val = hdspm_aes_sync_check(hdspm, |
3984 | kcontrol->private_value-1); | 4026 | kcontrol->private_value-1); |
3985 | } | 4027 | } |
4028 | break; | ||
3986 | 4029 | ||
3987 | } | 4030 | } |
3988 | 4031 | ||
@@ -4427,9 +4470,10 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { | |||
4427 | HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), | 4470 | HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), |
4428 | HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), | 4471 | HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), |
4429 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), | 4472 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), |
4473 | HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), | ||
4430 | HDSPM_SYNC_CHECK("WC SyncCheck", 0), | 4474 | HDSPM_SYNC_CHECK("WC SyncCheck", 0), |
4431 | HDSPM_SYNC_CHECK("MADI SyncCheck", 1), | 4475 | HDSPM_SYNC_CHECK("MADI SyncCheck", 1), |
4432 | HDSPM_SYNC_CHECK("TCO SyncCHeck", 2), | 4476 | HDSPM_SYNC_CHECK("TCO SyncCheck", 2), |
4433 | HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3), | 4477 | HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3), |
4434 | HDSPM_LINE_OUT("Line Out", 0), | 4478 | HDSPM_LINE_OUT("Line Out", 0), |
4435 | HDSPM_TX_64("TX 64 channels mode", 0), | 4479 | HDSPM_TX_64("TX 64 channels mode", 0), |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index bcbf1d00aa85..99f32f7c0692 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -1,8 +1,9 @@ | |||
1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o | 1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o |
2 | snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o | 2 | snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o |
3 | 3 | ||
4 | snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o | 4 | ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),) |
5 | obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o | 5 | snd-soc-core-objs += soc-dmaengine-pcm.o |
6 | endif | ||
6 | 7 | ||
7 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o | 8 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o |
8 | obj-$(CONFIG_SND_SOC) += codecs/ | 9 | obj-$(CONFIG_SND_SOC) += codecs/ |
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index 185d8dd36399..f379b085c392 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c | |||
@@ -178,6 +178,12 @@ | |||
178 | #define DA9055_AIF_WORD_S24_LE (2 << 2) | 178 | #define DA9055_AIF_WORD_S24_LE (2 << 2) |
179 | #define DA9055_AIF_WORD_S32_LE (3 << 2) | 179 | #define DA9055_AIF_WORD_S32_LE (3 << 2) |
180 | 180 | ||
181 | /* MIC_L_CTRL bit fields */ | ||
182 | #define DA9055_MIC_L_MUTE_EN (1 << 6) | ||
183 | |||
184 | /* MIC_R_CTRL bit fields */ | ||
185 | #define DA9055_MIC_R_MUTE_EN (1 << 6) | ||
186 | |||
181 | /* MIXIN_L_CTRL bit fields */ | 187 | /* MIXIN_L_CTRL bit fields */ |
182 | #define DA9055_MIXIN_L_MIX_EN (1 << 3) | 188 | #define DA9055_MIXIN_L_MIX_EN (1 << 3) |
183 | 189 | ||
@@ -476,7 +482,7 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol, | |||
476 | struct snd_ctl_elem_value *ucontrol) | 482 | struct snd_ctl_elem_value *ucontrol) |
477 | { | 483 | { |
478 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 484 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
479 | u8 reg_val, adc_left, adc_right; | 485 | u8 reg_val, adc_left, adc_right, mic_left, mic_right; |
480 | int avg_left_data, avg_right_data, offset_l, offset_r; | 486 | int avg_left_data, avg_right_data, offset_l, offset_r; |
481 | 487 | ||
482 | if (ucontrol->value.integer.value[0]) { | 488 | if (ucontrol->value.integer.value[0]) { |
@@ -485,6 +491,16 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol, | |||
485 | * offsets must be done first | 491 | * offsets must be done first |
486 | */ | 492 | */ |
487 | 493 | ||
494 | /* Save current values from Mic control registers */ | ||
495 | mic_left = snd_soc_read(codec, DA9055_MIC_L_CTRL); | ||
496 | mic_right = snd_soc_read(codec, DA9055_MIC_R_CTRL); | ||
497 | |||
498 | /* Mute Mic PGA Left and Right */ | ||
499 | snd_soc_update_bits(codec, DA9055_MIC_L_CTRL, | ||
500 | DA9055_MIC_L_MUTE_EN, DA9055_MIC_L_MUTE_EN); | ||
501 | snd_soc_update_bits(codec, DA9055_MIC_R_CTRL, | ||
502 | DA9055_MIC_R_MUTE_EN, DA9055_MIC_R_MUTE_EN); | ||
503 | |||
488 | /* Save current values from ADC control registers */ | 504 | /* Save current values from ADC control registers */ |
489 | adc_left = snd_soc_read(codec, DA9055_ADC_L_CTRL); | 505 | adc_left = snd_soc_read(codec, DA9055_ADC_L_CTRL); |
490 | adc_right = snd_soc_read(codec, DA9055_ADC_R_CTRL); | 506 | adc_right = snd_soc_read(codec, DA9055_ADC_R_CTRL); |
@@ -520,6 +536,10 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol, | |||
520 | /* Restore original values of ADC control registers */ | 536 | /* Restore original values of ADC control registers */ |
521 | snd_soc_write(codec, DA9055_ADC_L_CTRL, adc_left); | 537 | snd_soc_write(codec, DA9055_ADC_L_CTRL, adc_left); |
522 | snd_soc_write(codec, DA9055_ADC_R_CTRL, adc_right); | 538 | snd_soc_write(codec, DA9055_ADC_R_CTRL, adc_right); |
539 | |||
540 | /* Restore original values of Mic control registers */ | ||
541 | snd_soc_write(codec, DA9055_MIC_L_CTRL, mic_left); | ||
542 | snd_soc_write(codec, DA9055_MIC_R_CTRL, mic_right); | ||
523 | } | 543 | } |
524 | 544 | ||
525 | return snd_soc_put_volsw(kcontrol, ucontrol); | 545 | return snd_soc_put_volsw(kcontrol, ucontrol); |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index e8f97af75928..00b85cc1b9a3 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -820,10 +820,10 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
820 | {"VIBRA DAC", NULL, "Vibra Playback"}, | 820 | {"VIBRA DAC", NULL, "Vibra Playback"}, |
821 | 821 | ||
822 | /* ADC -> Stream mapping */ | 822 | /* ADC -> Stream mapping */ |
823 | {"ADC Left", NULL, "Legacy Capture"}, | 823 | {"Legacy Capture" , NULL, "ADC Left"}, |
824 | {"ADC Left", NULL, "Capture"}, | 824 | {"Capture", NULL, "ADC Left"}, |
825 | {"ADC Right", NULL, "Legacy Capture"}, | 825 | {"Legacy Capture", NULL, "ADC Right"}, |
826 | {"ADC Right", NULL, "Capture"}, | 826 | {"Capture" , NULL, "ADC Right"}, |
827 | 827 | ||
828 | /* Capture path */ | 828 | /* Capture path */ |
829 | {"Analog Left Capture Route", "Headset Mic", "HSMIC"}, | 829 | {"Analog Left Capture Route", "Headset Mic", "HSMIC"}, |
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index efa93dbb0191..eab64a193989 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c | |||
@@ -1028,7 +1028,7 @@ SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L, | |||
1028 | WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0, | 1028 | WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0, |
1029 | digital_tlv), | 1029 | digital_tlv), |
1030 | SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT, | 1030 | SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT, |
1031 | WM2200_SPK1R_MUTE_SHIFT, 1, 0), | 1031 | WM2200_SPK1R_MUTE_SHIFT, 1, 1), |
1032 | }; | 1032 | }; |
1033 | 1033 | ||
1034 | WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE); | 1034 | WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE); |
@@ -2091,6 +2091,7 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c, | |||
2091 | 2091 | ||
2092 | switch (wm2200->rev) { | 2092 | switch (wm2200->rev) { |
2093 | case 0: | 2093 | case 0: |
2094 | case 1: | ||
2094 | ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch, | 2095 | ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch, |
2095 | ARRAY_SIZE(wm2200_reva_patch)); | 2096 | ARRAY_SIZE(wm2200_reva_patch)); |
2096 | if (ret != 0) { | 2097 | if (ret != 0) { |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 2b2dadc54dac..3fddc7ad1127 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -1045,6 +1045,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, | |||
1045 | struct snd_kcontrol *kcontrol, int event) | 1045 | struct snd_kcontrol *kcontrol, int event) |
1046 | { | 1046 | { |
1047 | struct snd_soc_codec *codec = w->codec; | 1047 | struct snd_soc_codec *codec = w->codec; |
1048 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
1048 | struct wm8994 *control = codec->control_data; | 1049 | struct wm8994 *control = codec->control_data; |
1049 | int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA; | 1050 | int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA; |
1050 | int i; | 1051 | int i; |
@@ -1063,6 +1064,10 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, | |||
1063 | 1064 | ||
1064 | switch (event) { | 1065 | switch (event) { |
1065 | case SND_SOC_DAPM_PRE_PMU: | 1066 | case SND_SOC_DAPM_PRE_PMU: |
1067 | /* Don't enable timeslot 2 if not in use */ | ||
1068 | if (wm8994->channels[0] <= 2) | ||
1069 | mask &= ~(WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA); | ||
1070 | |||
1066 | val = snd_soc_read(codec, WM8994_AIF1_CONTROL_1); | 1071 | val = snd_soc_read(codec, WM8994_AIF1_CONTROL_1); |
1067 | if ((val & WM8994_AIF1ADCL_SRC) && | 1072 | if ((val & WM8994_AIF1ADCL_SRC) && |
1068 | (val & WM8994_AIF1ADCR_SRC)) | 1073 | (val & WM8994_AIF1ADCR_SRC)) |
@@ -2687,7 +2692,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, | |||
2687 | return -EINVAL; | 2692 | return -EINVAL; |
2688 | } | 2693 | } |
2689 | 2694 | ||
2690 | bclk_rate = params_rate(params) * 4; | 2695 | bclk_rate = params_rate(params); |
2691 | switch (params_format(params)) { | 2696 | switch (params_format(params)) { |
2692 | case SNDRV_PCM_FORMAT_S16_LE: | 2697 | case SNDRV_PCM_FORMAT_S16_LE: |
2693 | bclk_rate *= 16; | 2698 | bclk_rate *= 16; |
@@ -2708,6 +2713,17 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, | |||
2708 | return -EINVAL; | 2713 | return -EINVAL; |
2709 | } | 2714 | } |
2710 | 2715 | ||
2716 | wm8994->channels[id] = params_channels(params); | ||
2717 | switch (params_channels(params)) { | ||
2718 | case 1: | ||
2719 | case 2: | ||
2720 | bclk_rate *= 2; | ||
2721 | break; | ||
2722 | default: | ||
2723 | bclk_rate *= 4; | ||
2724 | break; | ||
2725 | } | ||
2726 | |||
2711 | /* Try to find an appropriate sample rate; look for an exact match. */ | 2727 | /* Try to find an appropriate sample rate; look for an exact match. */ |
2712 | for (i = 0; i < ARRAY_SIZE(srs); i++) | 2728 | for (i = 0; i < ARRAY_SIZE(srs); i++) |
2713 | if (srs[i].rate == params_rate(params)) | 2729 | if (srs[i].rate == params_rate(params)) |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index f142ec198db3..ccbce5791e95 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -77,6 +77,7 @@ struct wm8994_priv { | |||
77 | int sysclk_rate[2]; | 77 | int sysclk_rate[2]; |
78 | int mclk[2]; | 78 | int mclk[2]; |
79 | int aifclk[2]; | 79 | int aifclk[2]; |
80 | int channels[2]; | ||
80 | struct wm8994_fll_config fll[2], fll_suspend[2]; | 81 | struct wm8994_fll_config fll[2], fll_suspend[2]; |
81 | struct completion fll_locked[2]; | 82 | struct completion fll_locked[2]; |
82 | bool fll_locked_irq; | 83 | bool fll_locked_irq; |
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index dc0ee7626626..d8e96b2cd03e 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c | |||
@@ -575,56 +575,53 @@ static struct snd_soc_card ams_delta_audio_card = { | |||
575 | }; | 575 | }; |
576 | 576 | ||
577 | /* Module init/exit */ | 577 | /* Module init/exit */ |
578 | static struct platform_device *ams_delta_audio_platform_device; | 578 | static __devinit int ams_delta_probe(struct platform_device *pdev) |
579 | static struct platform_device *cx20442_platform_device; | ||
580 | |||
581 | static int __init ams_delta_module_init(void) | ||
582 | { | 579 | { |
580 | struct snd_soc_card *card = &ams_delta_audio_card; | ||
583 | int ret; | 581 | int ret; |
584 | 582 | ||
585 | if (!(machine_is_ams_delta())) | 583 | card->dev = &pdev->dev; |
586 | return -ENODEV; | ||
587 | |||
588 | ams_delta_audio_platform_device = | ||
589 | platform_device_alloc("soc-audio", -1); | ||
590 | if (!ams_delta_audio_platform_device) | ||
591 | return -ENOMEM; | ||
592 | 584 | ||
593 | platform_set_drvdata(ams_delta_audio_platform_device, | 585 | ret = snd_soc_register_card(card); |
594 | &ams_delta_audio_card); | 586 | if (ret) { |
595 | 587 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | |
596 | ret = platform_device_add(ams_delta_audio_platform_device); | 588 | card->dev = NULL; |
597 | if (ret) | 589 | return ret; |
598 | goto err; | 590 | } |
599 | |||
600 | /* | ||
601 | * Codec platform device could be registered from elsewhere (board?), | ||
602 | * but I do it here as it makes sense only if used with the card. | ||
603 | */ | ||
604 | cx20442_platform_device = | ||
605 | platform_device_register_simple("cx20442-codec", -1, NULL, 0); | ||
606 | return 0; | 591 | return 0; |
607 | err: | ||
608 | platform_device_put(ams_delta_audio_platform_device); | ||
609 | return ret; | ||
610 | } | 592 | } |
611 | late_initcall(ams_delta_module_init); | ||
612 | 593 | ||
613 | static void __exit ams_delta_module_exit(void) | 594 | static int __devexit ams_delta_remove(struct platform_device *pdev) |
614 | { | 595 | { |
596 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
597 | |||
615 | if (tty_unregister_ldisc(N_V253) != 0) | 598 | if (tty_unregister_ldisc(N_V253) != 0) |
616 | dev_warn(&ams_delta_audio_platform_device->dev, | 599 | dev_warn(&pdev->dev, |
617 | "failed to unregister V253 line discipline\n"); | 600 | "failed to unregister V253 line discipline\n"); |
618 | 601 | ||
619 | snd_soc_jack_free_gpios(&ams_delta_hook_switch, | 602 | snd_soc_jack_free_gpios(&ams_delta_hook_switch, |
620 | ARRAY_SIZE(ams_delta_hook_switch_gpios), | 603 | ARRAY_SIZE(ams_delta_hook_switch_gpios), |
621 | ams_delta_hook_switch_gpios); | 604 | ams_delta_hook_switch_gpios); |
622 | 605 | ||
623 | platform_device_unregister(cx20442_platform_device); | 606 | snd_soc_unregister_card(card); |
624 | platform_device_unregister(ams_delta_audio_platform_device); | 607 | card->dev = NULL; |
608 | return 0; | ||
625 | } | 609 | } |
626 | module_exit(ams_delta_module_exit); | 610 | |
611 | #define DRV_NAME "ams-delta-audio" | ||
612 | |||
613 | static struct platform_driver ams_delta_driver = { | ||
614 | .driver = { | ||
615 | .name = DRV_NAME, | ||
616 | .owner = THIS_MODULE, | ||
617 | }, | ||
618 | .probe = ams_delta_probe, | ||
619 | .remove = __devexit_p(ams_delta_remove), | ||
620 | }; | ||
621 | |||
622 | module_platform_driver(ams_delta_driver); | ||
627 | 623 | ||
628 | MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>"); | 624 | MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>"); |
629 | MODULE_DESCRIPTION("ALSA SoC driver for Amstrad E3 (Delta) videophone"); | 625 | MODULE_DESCRIPTION("ALSA SoC driver for Amstrad E3 (Delta) videophone"); |
630 | MODULE_LICENSE("GPL"); | 626 | MODULE_LICENSE("GPL"); |
627 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index 4a73ef3ae12f..a57a4e68dcc6 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c | |||
@@ -216,7 +216,7 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) | |||
216 | twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); | 216 | twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); |
217 | twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); | 217 | twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); |
218 | twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); | 218 | twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); |
219 | twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); | 219 | twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vibrator"); |
220 | twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); | 220 | twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); |
221 | twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); | 221 | twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); |
222 | twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); | 222 | twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); |
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/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index c02b001ee4b5..56965bb3275c 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <sound/pcm_params.h> | 40 | #include <sound/pcm_params.h> |
41 | #include <sound/soc.h> | 41 | #include <sound/soc.h> |
42 | 42 | ||
43 | #include <plat/omap_hwmod.h> | ||
44 | #include "omap-mcpdm.h" | 43 | #include "omap-mcpdm.h" |
45 | #include "omap-pcm.h" | 44 | #include "omap-pcm.h" |
46 | 45 | ||
@@ -260,13 +259,9 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, | |||
260 | mutex_lock(&mcpdm->mutex); | 259 | mutex_lock(&mcpdm->mutex); |
261 | 260 | ||
262 | if (!dai->active) { | 261 | if (!dai->active) { |
263 | /* Enable watch dog for ES above ES 1.0 to avoid saturation */ | 262 | u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); |
264 | if (omap_rev() != OMAP4430_REV_ES1_0) { | ||
265 | u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); | ||
266 | 263 | ||
267 | omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, | 264 | omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl | MCPDM_WD_EN); |
268 | ctrl | MCPDM_WD_EN); | ||
269 | } | ||
270 | omap_mcpdm_open_streams(mcpdm); | 265 | omap_mcpdm_open_streams(mcpdm); |
271 | } | 266 | } |
272 | mutex_unlock(&mcpdm->mutex); | 267 | mutex_unlock(&mcpdm->mutex); |
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/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c index 73ac5463c9e4..e834faf859fd 100644 --- a/sound/soc/pxa/mmp-pcm.c +++ b/sound/soc/pxa/mmp-pcm.c | |||
@@ -15,13 +15,13 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/dma-mapping.h> | 16 | #include <linux/dma-mapping.h> |
17 | #include <linux/dmaengine.h> | 17 | #include <linux/dmaengine.h> |
18 | #include <linux/platform_data/dma-mmp_tdma.h> | ||
18 | #include <linux/platform_data/mmp_audio.h> | 19 | #include <linux/platform_data/mmp_audio.h> |
19 | #include <sound/pxa2xx-lib.h> | 20 | #include <sound/pxa2xx-lib.h> |
20 | #include <sound/core.h> | 21 | #include <sound/core.h> |
21 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
22 | #include <sound/pcm_params.h> | 23 | #include <sound/pcm_params.h> |
23 | #include <sound/soc.h> | 24 | #include <sound/soc.h> |
24 | #include <mach/sram.h> | ||
25 | #include <sound/dmaengine_pcm.h> | 25 | #include <sound/dmaengine_pcm.h> |
26 | 26 | ||
27 | struct mmp_dma_data { | 27 | struct mmp_dma_data { |
diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c index 5dc10dfc0d42..b0d46d63d55e 100644 --- a/sound/soc/samsung/bells.c +++ b/sound/soc/samsung/bells.c | |||
@@ -212,7 +212,7 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = { | |||
212 | { | 212 | { |
213 | .name = "Sub", | 213 | .name = "Sub", |
214 | .stream_name = "Sub", | 214 | .stream_name = "Sub", |
215 | .cpu_dai_name = "wm5102-aif3", | 215 | .cpu_dai_name = "wm5110-aif3", |
216 | .codec_dai_name = "wm9081-hifi", | 216 | .codec_dai_name = "wm9081-hifi", |
217 | .codec_name = "wm9081.1-006c", | 217 | .codec_name = "wm9081.1-006c", |
218 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 218 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
@@ -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 = "wm5102-aif3", | 250 | .cpu_dai_name = "wm5110-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/sh/fsi.c b/sound/soc/sh/fsi.c index 5328ae5539f1..9d7f30774a44 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/sh_dma.h> | 20 | #include <linux/sh_dma.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/workqueue.h> | ||
23 | #include <sound/soc.h> | 24 | #include <sound/soc.h> |
24 | #include <sound/sh_fsi.h> | 25 | #include <sound/sh_fsi.h> |
25 | 26 | ||
@@ -223,7 +224,7 @@ struct fsi_stream { | |||
223 | */ | 224 | */ |
224 | struct dma_chan *chan; | 225 | struct dma_chan *chan; |
225 | struct sh_dmae_slave slave; /* see fsi_handler_init() */ | 226 | struct sh_dmae_slave slave; /* see fsi_handler_init() */ |
226 | struct tasklet_struct tasklet; | 227 | struct work_struct work; |
227 | dma_addr_t dma; | 228 | dma_addr_t dma; |
228 | }; | 229 | }; |
229 | 230 | ||
@@ -1085,9 +1086,9 @@ static void fsi_dma_complete(void *data) | |||
1085 | snd_pcm_period_elapsed(io->substream); | 1086 | snd_pcm_period_elapsed(io->substream); |
1086 | } | 1087 | } |
1087 | 1088 | ||
1088 | static void fsi_dma_do_tasklet(unsigned long data) | 1089 | static void fsi_dma_do_work(struct work_struct *work) |
1089 | { | 1090 | { |
1090 | struct fsi_stream *io = (struct fsi_stream *)data; | 1091 | struct fsi_stream *io = container_of(work, struct fsi_stream, work); |
1091 | struct fsi_priv *fsi = fsi_stream_to_priv(io); | 1092 | struct fsi_priv *fsi = fsi_stream_to_priv(io); |
1092 | struct snd_soc_dai *dai; | 1093 | struct snd_soc_dai *dai; |
1093 | struct dma_async_tx_descriptor *desc; | 1094 | struct dma_async_tx_descriptor *desc; |
@@ -1129,7 +1130,7 @@ static void fsi_dma_do_tasklet(unsigned long data) | |||
1129 | * FIXME | 1130 | * FIXME |
1130 | * | 1131 | * |
1131 | * In DMAEngine case, codec and FSI cannot be started simultaneously | 1132 | * In DMAEngine case, codec and FSI cannot be started simultaneously |
1132 | * since FSI is using tasklet. | 1133 | * since FSI is using the scheduler work queue. |
1133 | * Therefore, in capture case, probably FSI FIFO will have got | 1134 | * Therefore, in capture case, probably FSI FIFO will have got |
1134 | * overflow error in this point. | 1135 | * overflow error in this point. |
1135 | * in that case, DMA cannot start transfer until error was cleared. | 1136 | * in that case, DMA cannot start transfer until error was cleared. |
@@ -1153,7 +1154,7 @@ static bool fsi_dma_filter(struct dma_chan *chan, void *param) | |||
1153 | 1154 | ||
1154 | static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) | 1155 | static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) |
1155 | { | 1156 | { |
1156 | tasklet_schedule(&io->tasklet); | 1157 | schedule_work(&io->work); |
1157 | 1158 | ||
1158 | return 0; | 1159 | return 0; |
1159 | } | 1160 | } |
@@ -1195,14 +1196,14 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev | |||
1195 | return fsi_stream_probe(fsi, dev); | 1196 | return fsi_stream_probe(fsi, dev); |
1196 | } | 1197 | } |
1197 | 1198 | ||
1198 | tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io); | 1199 | INIT_WORK(&io->work, fsi_dma_do_work); |
1199 | 1200 | ||
1200 | return 0; | 1201 | return 0; |
1201 | } | 1202 | } |
1202 | 1203 | ||
1203 | static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) | 1204 | static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) |
1204 | { | 1205 | { |
1205 | tasklet_kill(&io->tasklet); | 1206 | cancel_work_sync(&io->work); |
1206 | 1207 | ||
1207 | fsi_stream_stop(fsi, io); | 1208 | fsi_stream_stop(fsi, io); |
1208 | 1209 | ||
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index fa0fd8ddae90..1ab5fe04bfcc 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c | |||
@@ -22,7 +22,7 @@ | |||
22 | 22 | ||
23 | /** | 23 | /** |
24 | * snd_soc_jack_new - Create a new jack | 24 | * snd_soc_jack_new - Create a new jack |
25 | * @card: ASoC card | 25 | * @codec: ASoC codec |
26 | * @id: an identifying string for this jack | 26 | * @id: an identifying string for this jack |
27 | * @type: a bitmask of enum snd_jack_type values that can be detected by | 27 | * @type: a bitmask of enum snd_jack_type values that can be detected by |
28 | * this jack | 28 | * this jack |
@@ -133,12 +133,13 @@ EXPORT_SYMBOL_GPL(snd_soc_jack_add_zones); | |||
133 | 133 | ||
134 | /** | 134 | /** |
135 | * snd_soc_jack_get_type - Based on the mic bias value, this function returns | 135 | * snd_soc_jack_get_type - Based on the mic bias value, this function returns |
136 | * the type of jack from the zones delcared in the jack type | 136 | * the type of jack from the zones declared in the jack type |
137 | * | 137 | * |
138 | * @jack: ASoC jack | ||
138 | * @micbias_voltage: mic bias voltage at adc channel when jack is plugged in | 139 | * @micbias_voltage: mic bias voltage at adc channel when jack is plugged in |
139 | * | 140 | * |
140 | * Based on the mic bias value passed, this function helps identify | 141 | * Based on the mic bias value passed, this function helps identify |
141 | * the type of jack from the already delcared jack zones | 142 | * the type of jack from the already declared jack zones |
142 | */ | 143 | */ |
143 | int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage) | 144 | int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage) |
144 | { | 145 | { |
diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 356611d9654d..54f7e25b6f7d 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c | |||
@@ -57,6 +57,20 @@ static struct snd_soc_card mop500_card = { | |||
57 | .num_links = ARRAY_SIZE(mop500_dai_links), | 57 | .num_links = ARRAY_SIZE(mop500_dai_links), |
58 | }; | 58 | }; |
59 | 59 | ||
60 | static void mop500_of_node_put(void) | ||
61 | { | ||
62 | int i; | ||
63 | |||
64 | for (i = 0; i < 2; i++) { | ||
65 | if (mop500_dai_links[i].cpu_of_node) | ||
66 | of_node_put((struct device_node *) | ||
67 | mop500_dai_links[i].cpu_of_node); | ||
68 | if (mop500_dai_links[i].codec_of_node) | ||
69 | of_node_put((struct device_node *) | ||
70 | mop500_dai_links[i].codec_of_node); | ||
71 | } | ||
72 | } | ||
73 | |||
60 | static int __devinit mop500_of_probe(struct platform_device *pdev, | 74 | static int __devinit mop500_of_probe(struct platform_device *pdev, |
61 | struct device_node *np) | 75 | struct device_node *np) |
62 | { | 76 | { |
@@ -69,6 +83,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev, | |||
69 | 83 | ||
70 | if (!(msp_np[0] && msp_np[1] && codec_np)) { | 84 | if (!(msp_np[0] && msp_np[1] && codec_np)) { |
71 | dev_err(&pdev->dev, "Phandle missing or invalid\n"); | 85 | dev_err(&pdev->dev, "Phandle missing or invalid\n"); |
86 | mop500_of_node_put(); | ||
72 | return -EINVAL; | 87 | return -EINVAL; |
73 | } | 88 | } |
74 | 89 | ||
@@ -83,6 +98,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev, | |||
83 | 98 | ||
84 | return 0; | 99 | return 0; |
85 | } | 100 | } |
101 | |||
86 | static int __devinit mop500_probe(struct platform_device *pdev) | 102 | static int __devinit mop500_probe(struct platform_device *pdev) |
87 | { | 103 | { |
88 | struct device_node *np = pdev->dev.of_node; | 104 | struct device_node *np = pdev->dev.of_node; |
@@ -128,6 +144,7 @@ static int __devexit mop500_remove(struct platform_device *pdev) | |||
128 | 144 | ||
129 | snd_soc_unregister_card(mop500_card); | 145 | snd_soc_unregister_card(mop500_card); |
130 | mop500_ab8500_remove(mop500_card); | 146 | mop500_ab8500_remove(mop500_card); |
147 | mop500_of_node_put(); | ||
131 | 148 | ||
132 | return 0; | 149 | return 0; |
133 | } | 150 | } |
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index b7c996e77570..a26c6bf0a29b 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/pinctrl/consumer.h> | 18 | #include <linux/pinctrl/consumer.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/io.h> | ||
21 | #include <linux/of.h> | 22 | #include <linux/of.h> |
22 | 23 | ||
23 | #include <mach/hardware.h> | 24 | #include <mach/hardware.h> |
@@ -697,14 +698,11 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, | |||
697 | platform_data = devm_kzalloc(&pdev->dev, | 698 | platform_data = devm_kzalloc(&pdev->dev, |
698 | sizeof(struct msp_i2s_platform_data), GFP_KERNEL); | 699 | sizeof(struct msp_i2s_platform_data), GFP_KERNEL); |
699 | if (!platform_data) | 700 | if (!platform_data) |
700 | ret = -ENOMEM; | 701 | return -ENOMEM; |
701 | } | 702 | } |
702 | } else | 703 | } else |
703 | if (!platform_data) | 704 | if (!platform_data) |
704 | ret = -EINVAL; | 705 | return -EINVAL; |
705 | |||
706 | if (ret) | ||
707 | goto err_res; | ||
708 | 706 | ||
709 | dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__, | 707 | dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__, |
710 | pdev->name, platform_data->id); | 708 | pdev->name, platform_data->id); |
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/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..37428f74dbb6 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,19 @@ 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 | } | ||
557 | 570 | ||
558 | ret = set_format(subs, subs->cur_audiofmt); | 571 | ret = set_format(subs, subs->cur_audiofmt); |
559 | if (ret < 0) | 572 | if (ret < 0) |
560 | return ret; | 573 | goto unlock; |
561 | 574 | ||
562 | iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); | 575 | iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); |
563 | alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; | 576 | alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; |
@@ -567,12 +580,12 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) | |||
567 | subs->cur_audiofmt, | 580 | subs->cur_audiofmt, |
568 | subs->cur_rate); | 581 | subs->cur_rate); |
569 | if (ret < 0) | 582 | if (ret < 0) |
570 | return ret; | 583 | goto unlock; |
571 | 584 | ||
572 | if (subs->need_setup_ep) { | 585 | if (subs->need_setup_ep) { |
573 | ret = configure_endpoint(subs); | 586 | ret = configure_endpoint(subs); |
574 | if (ret < 0) | 587 | if (ret < 0) |
575 | return ret; | 588 | goto unlock; |
576 | subs->need_setup_ep = false; | 589 | subs->need_setup_ep = false; |
577 | } | 590 | } |
578 | 591 | ||
@@ -592,9 +605,11 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) | |||
592 | /* for playback, submit the URBs now; otherwise, the first hwptr_done | 605 | /* for playback, submit the URBs now; otherwise, the first hwptr_done |
593 | * updates for all URBs would happen at the same time when starting */ | 606 | * updates for all URBs would happen at the same time when starting */ |
594 | if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) | 607 | if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) |
595 | return start_endpoints(subs, 1); | 608 | ret = start_endpoints(subs, 1); |
596 | 609 | ||
597 | return 0; | 610 | unlock: |
611 | up_read(&subs->stream->chip->shutdown_rwsem); | ||
612 | return ret; | ||
598 | } | 613 | } |
599 | 614 | ||
600 | static struct snd_pcm_hardware snd_usb_hardware = | 615 | static struct snd_pcm_hardware snd_usb_hardware = |
@@ -647,7 +662,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs, | |||
647 | return 0; | 662 | return 0; |
648 | } | 663 | } |
649 | /* check whether the period time is >= the data packet interval */ | 664 | /* check whether the period time is >= the data packet interval */ |
650 | if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) { | 665 | if (subs->speed != USB_SPEED_FULL) { |
651 | ptime = 125 * (1 << fp->datainterval); | 666 | ptime = 125 * (1 << fp->datainterval); |
652 | if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { | 667 | if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { |
653 | hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); | 668 | hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); |
@@ -925,7 +940,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre | |||
925 | return err; | 940 | return err; |
926 | 941 | ||
927 | param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; | 942 | param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; |
928 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) | 943 | if (subs->speed == USB_SPEED_FULL) |
929 | /* full speed devices have fixed data packet interval */ | 944 | /* full speed devices have fixed data packet interval */ |
930 | ptmin = 1000; | 945 | ptmin = 1000; |
931 | if (ptmin == 1000) | 946 | 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; |