diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-22 14:53:56 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-22 14:53:56 -0500 |
commit | e7cc3edd1758f9aab39f5afcd988ffed55cb26ca (patch) | |
tree | 25baf439dbaeebc5cbc7229f03bcdbb4406c1395 /sound | |
parent | 2101ae42899a14fe7caa73114e2161e778328661 (diff) | |
parent | 40ed9444cd2421cceedb35bb8d8ff913a5ae1ac3 (diff) |
Merge tag 'sound-fix-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai:
"Here are lots of small fixes that have been collected since the
previous pull. This time, not only trivial ones but fixes for some
serious bugs are included:
- Fix for CPU lockups by snd-hrtimer accesses
- Fix for unsafe disconnection handling in ALSA timer code
- Fix for Oops due to race at HD-audio module removal
- Fixes for possible memory corruption via 32bit PCM and sequencer
compat ioctls
- Fix for regression in HD-audio generic model handling
- Suppress kernel warnings for invalid TLV ioctls that may flood up
- Fix the missing SSC clock handling for at73c213
- A pin fixup for ASUS N550JX"
* tag 'sound-fix-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
ALSA: timer: Introduce disconnect op to snd_timer_instance
ALSA: timer: Handle disconnection more safely
ALSA: hda - Flush the pending probe work at remove
ALSA: hda - Fix missing module loading with model=generic option
ALSA: hda - Degrade i915 binding failure message
ALSA: at73c213: manage SSC clock
ALSA: control: Avoid kernel warnings from tlv ioctl with numid 0
ALSA: seq: Fix snd_seq_call_port_info_ioctl in compat mode
ALSA: pcm: Fix snd_pcm_hw_params struct copy in compat mode
ALSA: hrtimer: Fix stall by hrtimer_cancel()
ALSA: hda - Fix bass pin fixup for ASUS N550JX
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/control.c | 2 | ||||
-rw-r--r-- | sound/core/hrtimer.c | 3 | ||||
-rw-r--r-- | sound/core/pcm_compat.c | 13 | ||||
-rw-r--r-- | sound/core/seq/seq_compat.c | 9 | ||||
-rw-r--r-- | sound/core/timer.c | 47 | ||||
-rw-r--r-- | sound/hda/hdac_i915.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_bind.c | 42 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 16 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 1 | ||||
-rw-r--r-- | sound/spi/at73c213.c | 11 |
10 files changed, 123 insertions, 23 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index 196a6fe100ca..a85d45595d02 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -1405,6 +1405,8 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file, | |||
1405 | return -EFAULT; | 1405 | return -EFAULT; |
1406 | if (tlv.length < sizeof(unsigned int) * 2) | 1406 | if (tlv.length < sizeof(unsigned int) * 2) |
1407 | return -EINVAL; | 1407 | return -EINVAL; |
1408 | if (!tlv.numid) | ||
1409 | return -EINVAL; | ||
1408 | down_read(&card->controls_rwsem); | 1410 | down_read(&card->controls_rwsem); |
1409 | kctl = snd_ctl_find_numid(card, tlv.numid); | 1411 | kctl = snd_ctl_find_numid(card, tlv.numid); |
1410 | if (kctl == NULL) { | 1412 | if (kctl == NULL) { |
diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index f845ecf7e172..656d9a9032dc 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c | |||
@@ -90,7 +90,7 @@ static int snd_hrtimer_start(struct snd_timer *t) | |||
90 | struct snd_hrtimer *stime = t->private_data; | 90 | struct snd_hrtimer *stime = t->private_data; |
91 | 91 | ||
92 | atomic_set(&stime->running, 0); | 92 | atomic_set(&stime->running, 0); |
93 | hrtimer_cancel(&stime->hrt); | 93 | hrtimer_try_to_cancel(&stime->hrt); |
94 | hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution), | 94 | hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution), |
95 | HRTIMER_MODE_REL); | 95 | HRTIMER_MODE_REL); |
96 | atomic_set(&stime->running, 1); | 96 | atomic_set(&stime->running, 1); |
@@ -101,6 +101,7 @@ static int snd_hrtimer_stop(struct snd_timer *t) | |||
101 | { | 101 | { |
102 | struct snd_hrtimer *stime = t->private_data; | 102 | struct snd_hrtimer *stime = t->private_data; |
103 | atomic_set(&stime->running, 0); | 103 | atomic_set(&stime->running, 0); |
104 | hrtimer_try_to_cancel(&stime->hrt); | ||
104 | return 0; | 105 | return 0; |
105 | } | 106 | } |
106 | 107 | ||
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index b48b434444ed..9630e9f72b7b 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c | |||
@@ -255,10 +255,15 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, | |||
255 | if (! (runtime = substream->runtime)) | 255 | if (! (runtime = substream->runtime)) |
256 | return -ENOTTY; | 256 | return -ENOTTY; |
257 | 257 | ||
258 | /* only fifo_size is different, so just copy all */ | 258 | data = kmalloc(sizeof(*data), GFP_KERNEL); |
259 | data = memdup_user(data32, sizeof(*data32)); | 259 | if (!data) |
260 | if (IS_ERR(data)) | 260 | return -ENOMEM; |
261 | return PTR_ERR(data); | 261 | |
262 | /* only fifo_size (RO from userspace) is different, so just copy all */ | ||
263 | if (copy_from_user(data, data32, sizeof(*data32))) { | ||
264 | err = -EFAULT; | ||
265 | goto error; | ||
266 | } | ||
262 | 267 | ||
263 | if (refine) | 268 | if (refine) |
264 | err = snd_pcm_hw_refine(substream, data); | 269 | err = snd_pcm_hw_refine(substream, data); |
diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c index 81f7c109dc46..65175902a68a 100644 --- a/sound/core/seq/seq_compat.c +++ b/sound/core/seq/seq_compat.c | |||
@@ -49,11 +49,12 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned | |||
49 | struct snd_seq_port_info *data; | 49 | struct snd_seq_port_info *data; |
50 | mm_segment_t fs; | 50 | mm_segment_t fs; |
51 | 51 | ||
52 | data = memdup_user(data32, sizeof(*data32)); | 52 | data = kmalloc(sizeof(*data), GFP_KERNEL); |
53 | if (IS_ERR(data)) | 53 | if (!data) |
54 | return PTR_ERR(data); | 54 | return -ENOMEM; |
55 | 55 | ||
56 | if (get_user(data->flags, &data32->flags) || | 56 | if (copy_from_user(data, data32, sizeof(*data32)) || |
57 | get_user(data->flags, &data32->flags) || | ||
57 | get_user(data->time_queue, &data32->time_queue)) | 58 | get_user(data->time_queue, &data32->time_queue)) |
58 | goto error; | 59 | goto error; |
59 | data->kernel = NULL; | 60 | data->kernel = NULL; |
diff --git a/sound/core/timer.c b/sound/core/timer.c index cb25aded5349..af1f68f7e315 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -65,6 +65,7 @@ struct snd_timer_user { | |||
65 | int qtail; | 65 | int qtail; |
66 | int qused; | 66 | int qused; |
67 | int queue_size; | 67 | int queue_size; |
68 | bool disconnected; | ||
68 | struct snd_timer_read *queue; | 69 | struct snd_timer_read *queue; |
69 | struct snd_timer_tread *tqueue; | 70 | struct snd_timer_tread *tqueue; |
70 | spinlock_t qlock; | 71 | spinlock_t qlock; |
@@ -290,6 +291,9 @@ int snd_timer_open(struct snd_timer_instance **ti, | |||
290 | mutex_unlock(®ister_mutex); | 291 | mutex_unlock(®ister_mutex); |
291 | return -ENOMEM; | 292 | return -ENOMEM; |
292 | } | 293 | } |
294 | /* take a card refcount for safe disconnection */ | ||
295 | if (timer->card) | ||
296 | get_device(&timer->card->card_dev); | ||
293 | timeri->slave_class = tid->dev_sclass; | 297 | timeri->slave_class = tid->dev_sclass; |
294 | timeri->slave_id = slave_id; | 298 | timeri->slave_id = slave_id; |
295 | if (list_empty(&timer->open_list_head) && timer->hw.open) | 299 | if (list_empty(&timer->open_list_head) && timer->hw.open) |
@@ -359,6 +363,9 @@ int snd_timer_close(struct snd_timer_instance *timeri) | |||
359 | } | 363 | } |
360 | spin_unlock(&timer->lock); | 364 | spin_unlock(&timer->lock); |
361 | spin_unlock_irq(&slave_active_lock); | 365 | spin_unlock_irq(&slave_active_lock); |
366 | /* release a card refcount for safe disconnection */ | ||
367 | if (timer->card) | ||
368 | put_device(&timer->card->card_dev); | ||
362 | mutex_unlock(®ister_mutex); | 369 | mutex_unlock(®ister_mutex); |
363 | } | 370 | } |
364 | out: | 371 | out: |
@@ -474,6 +481,8 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks) | |||
474 | timer = timeri->timer; | 481 | timer = timeri->timer; |
475 | if (timer == NULL) | 482 | if (timer == NULL) |
476 | return -EINVAL; | 483 | return -EINVAL; |
484 | if (timer->card && timer->card->shutdown) | ||
485 | return -ENODEV; | ||
477 | spin_lock_irqsave(&timer->lock, flags); | 486 | spin_lock_irqsave(&timer->lock, flags); |
478 | timeri->ticks = timeri->cticks = ticks; | 487 | timeri->ticks = timeri->cticks = ticks; |
479 | timeri->pticks = 0; | 488 | timeri->pticks = 0; |
@@ -505,6 +514,10 @@ static int _snd_timer_stop(struct snd_timer_instance *timeri, int event) | |||
505 | spin_lock_irqsave(&timer->lock, flags); | 514 | spin_lock_irqsave(&timer->lock, flags); |
506 | list_del_init(&timeri->ack_list); | 515 | list_del_init(&timeri->ack_list); |
507 | list_del_init(&timeri->active_list); | 516 | list_del_init(&timeri->active_list); |
517 | if (timer->card && timer->card->shutdown) { | ||
518 | spin_unlock_irqrestore(&timer->lock, flags); | ||
519 | return 0; | ||
520 | } | ||
508 | if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) && | 521 | if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) && |
509 | !(--timer->running)) { | 522 | !(--timer->running)) { |
510 | timer->hw.stop(timer); | 523 | timer->hw.stop(timer); |
@@ -565,6 +578,8 @@ int snd_timer_continue(struct snd_timer_instance *timeri) | |||
565 | timer = timeri->timer; | 578 | timer = timeri->timer; |
566 | if (! timer) | 579 | if (! timer) |
567 | return -EINVAL; | 580 | return -EINVAL; |
581 | if (timer->card && timer->card->shutdown) | ||
582 | return -ENODEV; | ||
568 | spin_lock_irqsave(&timer->lock, flags); | 583 | spin_lock_irqsave(&timer->lock, flags); |
569 | if (!timeri->cticks) | 584 | if (!timeri->cticks) |
570 | timeri->cticks = 1; | 585 | timeri->cticks = 1; |
@@ -628,6 +643,9 @@ static void snd_timer_tasklet(unsigned long arg) | |||
628 | unsigned long resolution, ticks; | 643 | unsigned long resolution, ticks; |
629 | unsigned long flags; | 644 | unsigned long flags; |
630 | 645 | ||
646 | if (timer->card && timer->card->shutdown) | ||
647 | return; | ||
648 | |||
631 | spin_lock_irqsave(&timer->lock, flags); | 649 | spin_lock_irqsave(&timer->lock, flags); |
632 | /* now process all callbacks */ | 650 | /* now process all callbacks */ |
633 | while (!list_empty(&timer->sack_list_head)) { | 651 | while (!list_empty(&timer->sack_list_head)) { |
@@ -668,6 +686,9 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) | |||
668 | if (timer == NULL) | 686 | if (timer == NULL) |
669 | return; | 687 | return; |
670 | 688 | ||
689 | if (timer->card && timer->card->shutdown) | ||
690 | return; | ||
691 | |||
671 | spin_lock_irqsave(&timer->lock, flags); | 692 | spin_lock_irqsave(&timer->lock, flags); |
672 | 693 | ||
673 | /* remember the current resolution */ | 694 | /* remember the current resolution */ |
@@ -881,8 +902,15 @@ static int snd_timer_dev_register(struct snd_device *dev) | |||
881 | static int snd_timer_dev_disconnect(struct snd_device *device) | 902 | static int snd_timer_dev_disconnect(struct snd_device *device) |
882 | { | 903 | { |
883 | struct snd_timer *timer = device->device_data; | 904 | struct snd_timer *timer = device->device_data; |
905 | struct snd_timer_instance *ti; | ||
906 | |||
884 | mutex_lock(®ister_mutex); | 907 | mutex_lock(®ister_mutex); |
885 | list_del_init(&timer->device_list); | 908 | list_del_init(&timer->device_list); |
909 | /* wake up pending sleepers */ | ||
910 | list_for_each_entry(ti, &timer->open_list_head, open_list) { | ||
911 | if (ti->disconnect) | ||
912 | ti->disconnect(ti); | ||
913 | } | ||
886 | mutex_unlock(®ister_mutex); | 914 | mutex_unlock(®ister_mutex); |
887 | return 0; | 915 | return 0; |
888 | } | 916 | } |
@@ -893,6 +921,8 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam | |||
893 | unsigned long resolution = 0; | 921 | unsigned long resolution = 0; |
894 | struct snd_timer_instance *ti, *ts; | 922 | struct snd_timer_instance *ti, *ts; |
895 | 923 | ||
924 | if (timer->card && timer->card->shutdown) | ||
925 | return; | ||
896 | if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)) | 926 | if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)) |
897 | return; | 927 | return; |
898 | if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_MSTART || | 928 | if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_MSTART || |
@@ -1051,6 +1081,8 @@ static void snd_timer_proc_read(struct snd_info_entry *entry, | |||
1051 | 1081 | ||
1052 | mutex_lock(®ister_mutex); | 1082 | mutex_lock(®ister_mutex); |
1053 | list_for_each_entry(timer, &snd_timer_list, device_list) { | 1083 | list_for_each_entry(timer, &snd_timer_list, device_list) { |
1084 | if (timer->card && timer->card->shutdown) | ||
1085 | continue; | ||
1054 | switch (timer->tmr_class) { | 1086 | switch (timer->tmr_class) { |
1055 | case SNDRV_TIMER_CLASS_GLOBAL: | 1087 | case SNDRV_TIMER_CLASS_GLOBAL: |
1056 | snd_iprintf(buffer, "G%i: ", timer->tmr_device); | 1088 | snd_iprintf(buffer, "G%i: ", timer->tmr_device); |
@@ -1185,6 +1217,14 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, | |||
1185 | wake_up(&tu->qchange_sleep); | 1217 | wake_up(&tu->qchange_sleep); |
1186 | } | 1218 | } |
1187 | 1219 | ||
1220 | static void snd_timer_user_disconnect(struct snd_timer_instance *timeri) | ||
1221 | { | ||
1222 | struct snd_timer_user *tu = timeri->callback_data; | ||
1223 | |||
1224 | tu->disconnected = true; | ||
1225 | wake_up(&tu->qchange_sleep); | ||
1226 | } | ||
1227 | |||
1188 | static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, | 1228 | static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, |
1189 | unsigned long resolution, | 1229 | unsigned long resolution, |
1190 | unsigned long ticks) | 1230 | unsigned long ticks) |
@@ -1558,6 +1598,7 @@ static int snd_timer_user_tselect(struct file *file, | |||
1558 | ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; | 1598 | ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; |
1559 | tu->timeri->ccallback = snd_timer_user_ccallback; | 1599 | tu->timeri->ccallback = snd_timer_user_ccallback; |
1560 | tu->timeri->callback_data = (void *)tu; | 1600 | tu->timeri->callback_data = (void *)tu; |
1601 | tu->timeri->disconnect = snd_timer_user_disconnect; | ||
1561 | } | 1602 | } |
1562 | 1603 | ||
1563 | __err: | 1604 | __err: |
@@ -1876,6 +1917,10 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, | |||
1876 | 1917 | ||
1877 | remove_wait_queue(&tu->qchange_sleep, &wait); | 1918 | remove_wait_queue(&tu->qchange_sleep, &wait); |
1878 | 1919 | ||
1920 | if (tu->disconnected) { | ||
1921 | err = -ENODEV; | ||
1922 | break; | ||
1923 | } | ||
1879 | if (signal_pending(current)) { | 1924 | if (signal_pending(current)) { |
1880 | err = -ERESTARTSYS; | 1925 | err = -ERESTARTSYS; |
1881 | break; | 1926 | break; |
@@ -1925,6 +1970,8 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait) | |||
1925 | mask = 0; | 1970 | mask = 0; |
1926 | if (tu->qused) | 1971 | if (tu->qused) |
1927 | mask |= POLLIN | POLLRDNORM; | 1972 | mask |= POLLIN | POLLRDNORM; |
1973 | if (tu->disconnected) | ||
1974 | mask |= POLLERR; | ||
1928 | 1975 | ||
1929 | return mask; | 1976 | return mask; |
1930 | } | 1977 | } |
diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index c50177fb469f..f6854dbd7d8d 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c | |||
@@ -306,7 +306,7 @@ out_master_del: | |||
306 | out_err: | 306 | out_err: |
307 | kfree(acomp); | 307 | kfree(acomp); |
308 | bus->audio_component = NULL; | 308 | bus->audio_component = NULL; |
309 | dev_err(dev, "failed to add i915 component master (%d)\n", ret); | 309 | dev_info(dev, "failed to add i915 component master (%d)\n", ret); |
310 | 310 | ||
311 | return ret; | 311 | return ret; |
312 | } | 312 | } |
diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c index 70671ad65d24..6efadbfb3fe3 100644 --- a/sound/pci/hda/hda_bind.c +++ b/sound/pci/hda/hda_bind.c | |||
@@ -174,14 +174,40 @@ static inline bool codec_probed(struct hda_codec *codec) | |||
174 | return device_attach(hda_codec_dev(codec)) > 0 && codec->preset; | 174 | return device_attach(hda_codec_dev(codec)) > 0 && codec->preset; |
175 | } | 175 | } |
176 | 176 | ||
177 | /* try to auto-load and bind the codec module */ | 177 | /* try to auto-load codec module */ |
178 | static void codec_bind_module(struct hda_codec *codec) | 178 | static void request_codec_module(struct hda_codec *codec) |
179 | { | 179 | { |
180 | #ifdef MODULE | 180 | #ifdef MODULE |
181 | char modalias[32]; | 181 | char modalias[32]; |
182 | const char *mod = NULL; | ||
183 | |||
184 | switch (codec->probe_id) { | ||
185 | case HDA_CODEC_ID_GENERIC_HDMI: | ||
186 | #if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI) | ||
187 | mod = "snd-hda-codec-hdmi"; | ||
188 | #endif | ||
189 | break; | ||
190 | case HDA_CODEC_ID_GENERIC: | ||
191 | #if IS_MODULE(CONFIG_SND_HDA_GENERIC) | ||
192 | mod = "snd-hda-codec-generic"; | ||
193 | #endif | ||
194 | break; | ||
195 | default: | ||
196 | snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias)); | ||
197 | mod = modalias; | ||
198 | break; | ||
199 | } | ||
200 | |||
201 | if (mod) | ||
202 | request_module(mod); | ||
203 | #endif /* MODULE */ | ||
204 | } | ||
182 | 205 | ||
183 | snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias)); | 206 | /* try to auto-load and bind the codec module */ |
184 | request_module(modalias); | 207 | static void codec_bind_module(struct hda_codec *codec) |
208 | { | ||
209 | #ifdef MODULE | ||
210 | request_codec_module(codec); | ||
185 | if (codec_probed(codec)) | 211 | if (codec_probed(codec)) |
186 | return; | 212 | return; |
187 | #endif | 213 | #endif |
@@ -218,17 +244,13 @@ static int codec_bind_generic(struct hda_codec *codec) | |||
218 | 244 | ||
219 | if (is_likely_hdmi_codec(codec)) { | 245 | if (is_likely_hdmi_codec(codec)) { |
220 | codec->probe_id = HDA_CODEC_ID_GENERIC_HDMI; | 246 | codec->probe_id = HDA_CODEC_ID_GENERIC_HDMI; |
221 | #if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI) | 247 | request_codec_module(codec); |
222 | request_module("snd-hda-codec-hdmi"); | ||
223 | #endif | ||
224 | if (codec_probed(codec)) | 248 | if (codec_probed(codec)) |
225 | return 0; | 249 | return 0; |
226 | } | 250 | } |
227 | 251 | ||
228 | codec->probe_id = HDA_CODEC_ID_GENERIC; | 252 | codec->probe_id = HDA_CODEC_ID_GENERIC; |
229 | #if IS_MODULE(CONFIG_SND_HDA_GENERIC) | 253 | request_codec_module(codec); |
230 | request_module("snd-hda-codec-generic"); | ||
231 | #endif | ||
232 | if (codec_probed(codec)) | 254 | if (codec_probed(codec)) |
233 | return 0; | 255 | return 0; |
234 | return -ENODEV; | 256 | return -ENODEV; |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c0bef11afa7e..256e6cda218f 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -2078,9 +2078,11 @@ static int azx_probe_continue(struct azx *chip) | |||
2078 | * for other chips, still continue probing as other | 2078 | * for other chips, still continue probing as other |
2079 | * codecs can be on the same link. | 2079 | * codecs can be on the same link. |
2080 | */ | 2080 | */ |
2081 | if (CONTROLLER_IN_GPU(pci)) | 2081 | if (CONTROLLER_IN_GPU(pci)) { |
2082 | dev_err(chip->card->dev, | ||
2083 | "HSW/BDW HD-audio HDMI/DP requires binding with gfx driver\n"); | ||
2082 | goto out_free; | 2084 | goto out_free; |
2083 | else | 2085 | } else |
2084 | goto skip_i915; | 2086 | goto skip_i915; |
2085 | } | 2087 | } |
2086 | 2088 | ||
@@ -2149,9 +2151,17 @@ i915_power_fail: | |||
2149 | static void azx_remove(struct pci_dev *pci) | 2151 | static void azx_remove(struct pci_dev *pci) |
2150 | { | 2152 | { |
2151 | struct snd_card *card = pci_get_drvdata(pci); | 2153 | struct snd_card *card = pci_get_drvdata(pci); |
2154 | struct azx *chip; | ||
2155 | struct hda_intel *hda; | ||
2156 | |||
2157 | if (card) { | ||
2158 | /* flush the pending probing work */ | ||
2159 | chip = card->private_data; | ||
2160 | hda = container_of(chip, struct hda_intel, chip); | ||
2161 | flush_work(&hda->probe_work); | ||
2152 | 2162 | ||
2153 | if (card) | ||
2154 | snd_card_free(card); | 2163 | snd_card_free(card); |
2164 | } | ||
2155 | } | 2165 | } |
2156 | 2166 | ||
2157 | static void azx_shutdown(struct pci_dev *pci) | 2167 | static void azx_shutdown(struct pci_dev *pci) |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8143c0e24a27..33753244f48f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -6566,6 +6566,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { | |||
6566 | SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 6566 | SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
6567 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), | 6567 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), |
6568 | SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A), | 6568 | SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A), |
6569 | SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A), | ||
6569 | SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), | 6570 | SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), |
6570 | SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16), | 6571 | SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16), |
6571 | SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16), | 6572 | SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16), |
diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c index 39522367897c..fac7e6eb9529 100644 --- a/sound/spi/at73c213.c +++ b/sound/spi/at73c213.c | |||
@@ -221,6 +221,8 @@ static int snd_at73c213_pcm_open(struct snd_pcm_substream *substream) | |||
221 | runtime->hw = snd_at73c213_playback_hw; | 221 | runtime->hw = snd_at73c213_playback_hw; |
222 | chip->substream = substream; | 222 | chip->substream = substream; |
223 | 223 | ||
224 | clk_enable(chip->ssc->clk); | ||
225 | |||
224 | return 0; | 226 | return 0; |
225 | } | 227 | } |
226 | 228 | ||
@@ -228,6 +230,7 @@ static int snd_at73c213_pcm_close(struct snd_pcm_substream *substream) | |||
228 | { | 230 | { |
229 | struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); | 231 | struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); |
230 | chip->substream = NULL; | 232 | chip->substream = NULL; |
233 | clk_disable(chip->ssc->clk); | ||
231 | return 0; | 234 | return 0; |
232 | } | 235 | } |
233 | 236 | ||
@@ -897,6 +900,8 @@ static int snd_at73c213_dev_init(struct snd_card *card, | |||
897 | chip->card = card; | 900 | chip->card = card; |
898 | chip->irq = -1; | 901 | chip->irq = -1; |
899 | 902 | ||
903 | clk_enable(chip->ssc->clk); | ||
904 | |||
900 | retval = request_irq(irq, snd_at73c213_interrupt, 0, "at73c213", chip); | 905 | retval = request_irq(irq, snd_at73c213_interrupt, 0, "at73c213", chip); |
901 | if (retval) { | 906 | if (retval) { |
902 | dev_dbg(&chip->spi->dev, "unable to request irq %d\n", irq); | 907 | dev_dbg(&chip->spi->dev, "unable to request irq %d\n", irq); |
@@ -935,6 +940,8 @@ out_irq: | |||
935 | free_irq(chip->irq, chip); | 940 | free_irq(chip->irq, chip); |
936 | chip->irq = -1; | 941 | chip->irq = -1; |
937 | out: | 942 | out: |
943 | clk_disable(chip->ssc->clk); | ||
944 | |||
938 | return retval; | 945 | return retval; |
939 | } | 946 | } |
940 | 947 | ||
@@ -1012,7 +1019,9 @@ static int snd_at73c213_remove(struct spi_device *spi) | |||
1012 | int retval; | 1019 | int retval; |
1013 | 1020 | ||
1014 | /* Stop playback. */ | 1021 | /* Stop playback. */ |
1022 | clk_enable(chip->ssc->clk); | ||
1015 | ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS)); | 1023 | ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS)); |
1024 | clk_disable(chip->ssc->clk); | ||
1016 | 1025 | ||
1017 | /* Mute sound. */ | 1026 | /* Mute sound. */ |
1018 | retval = snd_at73c213_write_reg(chip, DAC_LMPG, 0x3f); | 1027 | retval = snd_at73c213_write_reg(chip, DAC_LMPG, 0x3f); |
@@ -1080,6 +1089,7 @@ static int snd_at73c213_suspend(struct device *dev) | |||
1080 | struct snd_at73c213 *chip = card->private_data; | 1089 | struct snd_at73c213 *chip = card->private_data; |
1081 | 1090 | ||
1082 | ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS)); | 1091 | ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS)); |
1092 | clk_disable(chip->ssc->clk); | ||
1083 | clk_disable(chip->board->dac_clk); | 1093 | clk_disable(chip->board->dac_clk); |
1084 | 1094 | ||
1085 | return 0; | 1095 | return 0; |
@@ -1091,6 +1101,7 @@ static int snd_at73c213_resume(struct device *dev) | |||
1091 | struct snd_at73c213 *chip = card->private_data; | 1101 | struct snd_at73c213 *chip = card->private_data; |
1092 | 1102 | ||
1093 | clk_enable(chip->board->dac_clk); | 1103 | clk_enable(chip->board->dac_clk); |
1104 | clk_enable(chip->ssc->clk); | ||
1094 | ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXEN)); | 1105 | ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXEN)); |
1095 | 1106 | ||
1096 | return 0; | 1107 | return 0; |