diff options
-rw-r--r-- | sound/core/control_compat.c | 90 | ||||
-rw-r--r-- | sound/core/pcm_compat.c | 177 | ||||
-rw-r--r-- | sound/core/rawmidi_compat.c | 56 | ||||
-rw-r--r-- | sound/core/seq/oss/seq_oss.c | 2 | ||||
-rw-r--r-- | sound/core/seq/oss/seq_oss_device.h | 1 | ||||
-rw-r--r-- | sound/core/seq/oss/seq_oss_init.c | 16 | ||||
-rw-r--r-- | sound/core/timer_compat.c | 18 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 19 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 1 | ||||
-rw-r--r-- | sound/pci/rme9652/hdsp.c | 4 | ||||
-rw-r--r-- | sound/pci/rme9652/hdspm.c | 16 | ||||
-rw-r--r-- | sound/usb/quirks.c | 1 |
12 files changed, 348 insertions, 53 deletions
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index b9c0910fb8c4..0608f216f359 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c | |||
@@ -170,6 +170,19 @@ struct snd_ctl_elem_value32 { | |||
170 | unsigned char reserved[128]; | 170 | unsigned char reserved[128]; |
171 | }; | 171 | }; |
172 | 172 | ||
173 | #ifdef CONFIG_X86_X32 | ||
174 | /* x32 has a different alignment for 64bit values from ia32 */ | ||
175 | struct snd_ctl_elem_value_x32 { | ||
176 | struct snd_ctl_elem_id id; | ||
177 | unsigned int indirect; /* bit-field causes misalignment */ | ||
178 | union { | ||
179 | s32 integer[128]; | ||
180 | unsigned char data[512]; | ||
181 | s64 integer64[64]; | ||
182 | } value; | ||
183 | unsigned char reserved[128]; | ||
184 | }; | ||
185 | #endif /* CONFIG_X86_X32 */ | ||
173 | 186 | ||
174 | /* get the value type and count of the control */ | 187 | /* get the value type and count of the control */ |
175 | static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, | 188 | static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, |
@@ -219,9 +232,11 @@ static int get_elem_size(int type, int count) | |||
219 | 232 | ||
220 | static int copy_ctl_value_from_user(struct snd_card *card, | 233 | static int copy_ctl_value_from_user(struct snd_card *card, |
221 | struct snd_ctl_elem_value *data, | 234 | struct snd_ctl_elem_value *data, |
222 | struct snd_ctl_elem_value32 __user *data32, | 235 | void __user *userdata, |
236 | void __user *valuep, | ||
223 | int *typep, int *countp) | 237 | int *typep, int *countp) |
224 | { | 238 | { |
239 | struct snd_ctl_elem_value32 __user *data32 = userdata; | ||
225 | int i, type, size; | 240 | int i, type, size; |
226 | int uninitialized_var(count); | 241 | int uninitialized_var(count); |
227 | unsigned int indirect; | 242 | unsigned int indirect; |
@@ -239,8 +254,9 @@ static int copy_ctl_value_from_user(struct snd_card *card, | |||
239 | if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || | 254 | if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || |
240 | type == SNDRV_CTL_ELEM_TYPE_INTEGER) { | 255 | type == SNDRV_CTL_ELEM_TYPE_INTEGER) { |
241 | for (i = 0; i < count; i++) { | 256 | for (i = 0; i < count; i++) { |
257 | s32 __user *intp = valuep; | ||
242 | int val; | 258 | int val; |
243 | if (get_user(val, &data32->value.integer[i])) | 259 | if (get_user(val, &intp[i])) |
244 | return -EFAULT; | 260 | return -EFAULT; |
245 | data->value.integer.value[i] = val; | 261 | data->value.integer.value[i] = val; |
246 | } | 262 | } |
@@ -250,8 +266,7 @@ static int copy_ctl_value_from_user(struct snd_card *card, | |||
250 | dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); | 266 | dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); |
251 | return -EINVAL; | 267 | return -EINVAL; |
252 | } | 268 | } |
253 | if (copy_from_user(data->value.bytes.data, | 269 | if (copy_from_user(data->value.bytes.data, valuep, size)) |
254 | data32->value.data, size)) | ||
255 | return -EFAULT; | 270 | return -EFAULT; |
256 | } | 271 | } |
257 | 272 | ||
@@ -261,7 +276,8 @@ static int copy_ctl_value_from_user(struct snd_card *card, | |||
261 | } | 276 | } |
262 | 277 | ||
263 | /* restore the value to 32bit */ | 278 | /* restore the value to 32bit */ |
264 | static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32, | 279 | static int copy_ctl_value_to_user(void __user *userdata, |
280 | void __user *valuep, | ||
265 | struct snd_ctl_elem_value *data, | 281 | struct snd_ctl_elem_value *data, |
266 | int type, int count) | 282 | int type, int count) |
267 | { | 283 | { |
@@ -270,22 +286,22 @@ static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32, | |||
270 | if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || | 286 | if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || |
271 | type == SNDRV_CTL_ELEM_TYPE_INTEGER) { | 287 | type == SNDRV_CTL_ELEM_TYPE_INTEGER) { |
272 | for (i = 0; i < count; i++) { | 288 | for (i = 0; i < count; i++) { |
289 | s32 __user *intp = valuep; | ||
273 | int val; | 290 | int val; |
274 | val = data->value.integer.value[i]; | 291 | val = data->value.integer.value[i]; |
275 | if (put_user(val, &data32->value.integer[i])) | 292 | if (put_user(val, &intp[i])) |
276 | return -EFAULT; | 293 | return -EFAULT; |
277 | } | 294 | } |
278 | } else { | 295 | } else { |
279 | size = get_elem_size(type, count); | 296 | size = get_elem_size(type, count); |
280 | if (copy_to_user(data32->value.data, | 297 | if (copy_to_user(valuep, data->value.bytes.data, size)) |
281 | data->value.bytes.data, size)) | ||
282 | return -EFAULT; | 298 | return -EFAULT; |
283 | } | 299 | } |
284 | return 0; | 300 | return 0; |
285 | } | 301 | } |
286 | 302 | ||
287 | static int snd_ctl_elem_read_user_compat(struct snd_card *card, | 303 | static int ctl_elem_read_user(struct snd_card *card, |
288 | struct snd_ctl_elem_value32 __user *data32) | 304 | void __user *userdata, void __user *valuep) |
289 | { | 305 | { |
290 | struct snd_ctl_elem_value *data; | 306 | struct snd_ctl_elem_value *data; |
291 | int err, type, count; | 307 | int err, type, count; |
@@ -294,7 +310,9 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card, | |||
294 | if (data == NULL) | 310 | if (data == NULL) |
295 | return -ENOMEM; | 311 | return -ENOMEM; |
296 | 312 | ||
297 | if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0) | 313 | err = copy_ctl_value_from_user(card, data, userdata, valuep, |
314 | &type, &count); | ||
315 | if (err < 0) | ||
298 | goto error; | 316 | goto error; |
299 | 317 | ||
300 | snd_power_lock(card); | 318 | snd_power_lock(card); |
@@ -303,14 +321,15 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card, | |||
303 | err = snd_ctl_elem_read(card, data); | 321 | err = snd_ctl_elem_read(card, data); |
304 | snd_power_unlock(card); | 322 | snd_power_unlock(card); |
305 | if (err >= 0) | 323 | if (err >= 0) |
306 | err = copy_ctl_value_to_user(data32, data, type, count); | 324 | err = copy_ctl_value_to_user(userdata, valuep, data, |
325 | type, count); | ||
307 | error: | 326 | error: |
308 | kfree(data); | 327 | kfree(data); |
309 | return err; | 328 | return err; |
310 | } | 329 | } |
311 | 330 | ||
312 | static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, | 331 | static int ctl_elem_write_user(struct snd_ctl_file *file, |
313 | struct snd_ctl_elem_value32 __user *data32) | 332 | void __user *userdata, void __user *valuep) |
314 | { | 333 | { |
315 | struct snd_ctl_elem_value *data; | 334 | struct snd_ctl_elem_value *data; |
316 | struct snd_card *card = file->card; | 335 | struct snd_card *card = file->card; |
@@ -320,7 +339,9 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, | |||
320 | if (data == NULL) | 339 | if (data == NULL) |
321 | return -ENOMEM; | 340 | return -ENOMEM; |
322 | 341 | ||
323 | if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0) | 342 | err = copy_ctl_value_from_user(card, data, userdata, valuep, |
343 | &type, &count); | ||
344 | if (err < 0) | ||
324 | goto error; | 345 | goto error; |
325 | 346 | ||
326 | snd_power_lock(card); | 347 | snd_power_lock(card); |
@@ -329,12 +350,39 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, | |||
329 | err = snd_ctl_elem_write(card, file, data); | 350 | err = snd_ctl_elem_write(card, file, data); |
330 | snd_power_unlock(card); | 351 | snd_power_unlock(card); |
331 | if (err >= 0) | 352 | if (err >= 0) |
332 | err = copy_ctl_value_to_user(data32, data, type, count); | 353 | err = copy_ctl_value_to_user(userdata, valuep, data, |
354 | type, count); | ||
333 | error: | 355 | error: |
334 | kfree(data); | 356 | kfree(data); |
335 | return err; | 357 | return err; |
336 | } | 358 | } |
337 | 359 | ||
360 | static int snd_ctl_elem_read_user_compat(struct snd_card *card, | ||
361 | struct snd_ctl_elem_value32 __user *data32) | ||
362 | { | ||
363 | return ctl_elem_read_user(card, data32, &data32->value); | ||
364 | } | ||
365 | |||
366 | static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, | ||
367 | struct snd_ctl_elem_value32 __user *data32) | ||
368 | { | ||
369 | return ctl_elem_write_user(file, data32, &data32->value); | ||
370 | } | ||
371 | |||
372 | #ifdef CONFIG_X86_X32 | ||
373 | static int snd_ctl_elem_read_user_x32(struct snd_card *card, | ||
374 | struct snd_ctl_elem_value_x32 __user *data32) | ||
375 | { | ||
376 | return ctl_elem_read_user(card, data32, &data32->value); | ||
377 | } | ||
378 | |||
379 | static int snd_ctl_elem_write_user_x32(struct snd_ctl_file *file, | ||
380 | struct snd_ctl_elem_value_x32 __user *data32) | ||
381 | { | ||
382 | return ctl_elem_write_user(file, data32, &data32->value); | ||
383 | } | ||
384 | #endif /* CONFIG_X86_X32 */ | ||
385 | |||
338 | /* add or replace a user control */ | 386 | /* add or replace a user control */ |
339 | static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, | 387 | static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, |
340 | struct snd_ctl_elem_info32 __user *data32, | 388 | struct snd_ctl_elem_info32 __user *data32, |
@@ -393,6 +441,10 @@ enum { | |||
393 | SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32), | 441 | SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32), |
394 | SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32), | 442 | SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32), |
395 | SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32), | 443 | SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32), |
444 | #ifdef CONFIG_X86_X32 | ||
445 | SNDRV_CTL_IOCTL_ELEM_READ_X32 = _IOWR('U', 0x12, struct snd_ctl_elem_value_x32), | ||
446 | SNDRV_CTL_IOCTL_ELEM_WRITE_X32 = _IOWR('U', 0x13, struct snd_ctl_elem_value_x32), | ||
447 | #endif /* CONFIG_X86_X32 */ | ||
396 | }; | 448 | }; |
397 | 449 | ||
398 | static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) | 450 | static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) |
@@ -431,6 +483,12 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns | |||
431 | return snd_ctl_elem_add_compat(ctl, argp, 0); | 483 | return snd_ctl_elem_add_compat(ctl, argp, 0); |
432 | case SNDRV_CTL_IOCTL_ELEM_REPLACE32: | 484 | case SNDRV_CTL_IOCTL_ELEM_REPLACE32: |
433 | return snd_ctl_elem_add_compat(ctl, argp, 1); | 485 | return snd_ctl_elem_add_compat(ctl, argp, 1); |
486 | #ifdef CONFIG_X86_X32 | ||
487 | case SNDRV_CTL_IOCTL_ELEM_READ_X32: | ||
488 | return snd_ctl_elem_read_user_x32(ctl->card, argp); | ||
489 | case SNDRV_CTL_IOCTL_ELEM_WRITE_X32: | ||
490 | return snd_ctl_elem_write_user_x32(ctl, argp); | ||
491 | #endif /* CONFIG_X86_X32 */ | ||
434 | } | 492 | } |
435 | 493 | ||
436 | down_read(&snd_ioctl_rwsem); | 494 | down_read(&snd_ioctl_rwsem); |
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 9630e9f72b7b..1f64ab0c2a95 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c | |||
@@ -183,6 +183,14 @@ static int snd_pcm_ioctl_channel_info_compat(struct snd_pcm_substream *substream | |||
183 | return err; | 183 | return err; |
184 | } | 184 | } |
185 | 185 | ||
186 | #ifdef CONFIG_X86_X32 | ||
187 | /* X32 ABI has the same struct as x86-64 for snd_pcm_channel_info */ | ||
188 | static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream, | ||
189 | struct snd_pcm_channel_info __user *src); | ||
190 | #define snd_pcm_ioctl_channel_info_x32(s, p) \ | ||
191 | snd_pcm_channel_info_user(s, p) | ||
192 | #endif /* CONFIG_X86_X32 */ | ||
193 | |||
186 | struct snd_pcm_status32 { | 194 | struct snd_pcm_status32 { |
187 | s32 state; | 195 | s32 state; |
188 | struct compat_timespec trigger_tstamp; | 196 | struct compat_timespec trigger_tstamp; |
@@ -243,6 +251,71 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, | |||
243 | return err; | 251 | return err; |
244 | } | 252 | } |
245 | 253 | ||
254 | #ifdef CONFIG_X86_X32 | ||
255 | /* X32 ABI has 64bit timespec and 64bit alignment */ | ||
256 | struct snd_pcm_status_x32 { | ||
257 | s32 state; | ||
258 | u32 rsvd; /* alignment */ | ||
259 | struct timespec trigger_tstamp; | ||
260 | struct timespec tstamp; | ||
261 | u32 appl_ptr; | ||
262 | u32 hw_ptr; | ||
263 | s32 delay; | ||
264 | u32 avail; | ||
265 | u32 avail_max; | ||
266 | u32 overrange; | ||
267 | s32 suspended_state; | ||
268 | u32 audio_tstamp_data; | ||
269 | struct timespec audio_tstamp; | ||
270 | struct timespec driver_tstamp; | ||
271 | u32 audio_tstamp_accuracy; | ||
272 | unsigned char reserved[52-2*sizeof(struct timespec)]; | ||
273 | } __packed; | ||
274 | |||
275 | #define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst)) | ||
276 | |||
277 | static int snd_pcm_status_user_x32(struct snd_pcm_substream *substream, | ||
278 | struct snd_pcm_status_x32 __user *src, | ||
279 | bool ext) | ||
280 | { | ||
281 | struct snd_pcm_status status; | ||
282 | int err; | ||
283 | |||
284 | memset(&status, 0, sizeof(status)); | ||
285 | /* | ||
286 | * with extension, parameters are read/write, | ||
287 | * get audio_tstamp_data from user, | ||
288 | * ignore rest of status structure | ||
289 | */ | ||
290 | if (ext && get_user(status.audio_tstamp_data, | ||
291 | (u32 __user *)(&src->audio_tstamp_data))) | ||
292 | return -EFAULT; | ||
293 | err = snd_pcm_status(substream, &status); | ||
294 | if (err < 0) | ||
295 | return err; | ||
296 | |||
297 | if (clear_user(src, sizeof(*src))) | ||
298 | return -EFAULT; | ||
299 | if (put_user(status.state, &src->state) || | ||
300 | put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || | ||
301 | put_timespec(&status.tstamp, &src->tstamp) || | ||
302 | put_user(status.appl_ptr, &src->appl_ptr) || | ||
303 | put_user(status.hw_ptr, &src->hw_ptr) || | ||
304 | put_user(status.delay, &src->delay) || | ||
305 | put_user(status.avail, &src->avail) || | ||
306 | put_user(status.avail_max, &src->avail_max) || | ||
307 | put_user(status.overrange, &src->overrange) || | ||
308 | put_user(status.suspended_state, &src->suspended_state) || | ||
309 | put_user(status.audio_tstamp_data, &src->audio_tstamp_data) || | ||
310 | put_timespec(&status.audio_tstamp, &src->audio_tstamp) || | ||
311 | put_timespec(&status.driver_tstamp, &src->driver_tstamp) || | ||
312 | put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy)) | ||
313 | return -EFAULT; | ||
314 | |||
315 | return err; | ||
316 | } | ||
317 | #endif /* CONFIG_X86_X32 */ | ||
318 | |||
246 | /* both for HW_PARAMS and HW_REFINE */ | 319 | /* both for HW_PARAMS and HW_REFINE */ |
247 | static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, | 320 | static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, |
248 | int refine, | 321 | int refine, |
@@ -469,6 +542,93 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, | |||
469 | return 0; | 542 | return 0; |
470 | } | 543 | } |
471 | 544 | ||
545 | #ifdef CONFIG_X86_X32 | ||
546 | /* X32 ABI has 64bit timespec and 64bit alignment */ | ||
547 | struct snd_pcm_mmap_status_x32 { | ||
548 | s32 state; | ||
549 | s32 pad1; | ||
550 | u32 hw_ptr; | ||
551 | u32 pad2; /* alignment */ | ||
552 | struct timespec tstamp; | ||
553 | s32 suspended_state; | ||
554 | struct timespec audio_tstamp; | ||
555 | } __packed; | ||
556 | |||
557 | struct snd_pcm_mmap_control_x32 { | ||
558 | u32 appl_ptr; | ||
559 | u32 avail_min; | ||
560 | }; | ||
561 | |||
562 | struct snd_pcm_sync_ptr_x32 { | ||
563 | u32 flags; | ||
564 | u32 rsvd; /* alignment */ | ||
565 | union { | ||
566 | struct snd_pcm_mmap_status_x32 status; | ||
567 | unsigned char reserved[64]; | ||
568 | } s; | ||
569 | union { | ||
570 | struct snd_pcm_mmap_control_x32 control; | ||
571 | unsigned char reserved[64]; | ||
572 | } c; | ||
573 | } __packed; | ||
574 | |||
575 | static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream, | ||
576 | struct snd_pcm_sync_ptr_x32 __user *src) | ||
577 | { | ||
578 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
579 | volatile struct snd_pcm_mmap_status *status; | ||
580 | volatile struct snd_pcm_mmap_control *control; | ||
581 | u32 sflags; | ||
582 | struct snd_pcm_mmap_control scontrol; | ||
583 | struct snd_pcm_mmap_status sstatus; | ||
584 | snd_pcm_uframes_t boundary; | ||
585 | int err; | ||
586 | |||
587 | if (snd_BUG_ON(!runtime)) | ||
588 | return -EINVAL; | ||
589 | |||
590 | if (get_user(sflags, &src->flags) || | ||
591 | get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || | ||
592 | get_user(scontrol.avail_min, &src->c.control.avail_min)) | ||
593 | return -EFAULT; | ||
594 | if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) { | ||
595 | err = snd_pcm_hwsync(substream); | ||
596 | if (err < 0) | ||
597 | return err; | ||
598 | } | ||
599 | status = runtime->status; | ||
600 | control = runtime->control; | ||
601 | boundary = recalculate_boundary(runtime); | ||
602 | if (!boundary) | ||
603 | boundary = 0x7fffffff; | ||
604 | snd_pcm_stream_lock_irq(substream); | ||
605 | /* FIXME: we should consider the boundary for the sync from app */ | ||
606 | if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) | ||
607 | control->appl_ptr = scontrol.appl_ptr; | ||
608 | else | ||
609 | scontrol.appl_ptr = control->appl_ptr % boundary; | ||
610 | if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) | ||
611 | control->avail_min = scontrol.avail_min; | ||
612 | else | ||
613 | scontrol.avail_min = control->avail_min; | ||
614 | sstatus.state = status->state; | ||
615 | sstatus.hw_ptr = status->hw_ptr % boundary; | ||
616 | sstatus.tstamp = status->tstamp; | ||
617 | sstatus.suspended_state = status->suspended_state; | ||
618 | sstatus.audio_tstamp = status->audio_tstamp; | ||
619 | snd_pcm_stream_unlock_irq(substream); | ||
620 | if (put_user(sstatus.state, &src->s.status.state) || | ||
621 | put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) || | ||
622 | put_timespec(&sstatus.tstamp, &src->s.status.tstamp) || | ||
623 | put_user(sstatus.suspended_state, &src->s.status.suspended_state) || | ||
624 | put_timespec(&sstatus.audio_tstamp, &src->s.status.audio_tstamp) || | ||
625 | put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || | ||
626 | put_user(scontrol.avail_min, &src->c.control.avail_min)) | ||
627 | return -EFAULT; | ||
628 | |||
629 | return 0; | ||
630 | } | ||
631 | #endif /* CONFIG_X86_X32 */ | ||
472 | 632 | ||
473 | /* | 633 | /* |
474 | */ | 634 | */ |
@@ -487,7 +647,12 @@ enum { | |||
487 | SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32), | 647 | SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32), |
488 | SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32), | 648 | SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32), |
489 | SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32), | 649 | SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32), |
490 | 650 | #ifdef CONFIG_X86_X32 | |
651 | SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info), | ||
652 | SNDRV_PCM_IOCTL_STATUS_X32 = _IOR('A', 0x20, struct snd_pcm_status_x32), | ||
653 | SNDRV_PCM_IOCTL_STATUS_EXT_X32 = _IOWR('A', 0x24, struct snd_pcm_status_x32), | ||
654 | SNDRV_PCM_IOCTL_SYNC_PTR_X32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr_x32), | ||
655 | #endif /* CONFIG_X86_X32 */ | ||
491 | }; | 656 | }; |
492 | 657 | ||
493 | static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) | 658 | static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) |
@@ -559,6 +724,16 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l | |||
559 | return snd_pcm_ioctl_rewind_compat(substream, argp); | 724 | return snd_pcm_ioctl_rewind_compat(substream, argp); |
560 | case SNDRV_PCM_IOCTL_FORWARD32: | 725 | case SNDRV_PCM_IOCTL_FORWARD32: |
561 | return snd_pcm_ioctl_forward_compat(substream, argp); | 726 | return snd_pcm_ioctl_forward_compat(substream, argp); |
727 | #ifdef CONFIG_X86_X32 | ||
728 | case SNDRV_PCM_IOCTL_STATUS_X32: | ||
729 | return snd_pcm_status_user_x32(substream, argp, false); | ||
730 | case SNDRV_PCM_IOCTL_STATUS_EXT_X32: | ||
731 | return snd_pcm_status_user_x32(substream, argp, true); | ||
732 | case SNDRV_PCM_IOCTL_SYNC_PTR_X32: | ||
733 | return snd_pcm_ioctl_sync_ptr_x32(substream, argp); | ||
734 | case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32: | ||
735 | return snd_pcm_ioctl_channel_info_x32(substream, argp); | ||
736 | #endif /* CONFIG_X86_X32 */ | ||
562 | } | 737 | } |
563 | 738 | ||
564 | return -ENOIOCTLCMD; | 739 | return -ENOIOCTLCMD; |
diff --git a/sound/core/rawmidi_compat.c b/sound/core/rawmidi_compat.c index 5268c1f58c25..f69764d7cdd7 100644 --- a/sound/core/rawmidi_compat.c +++ b/sound/core/rawmidi_compat.c | |||
@@ -85,8 +85,7 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, | |||
85 | if (err < 0) | 85 | if (err < 0) |
86 | return err; | 86 | return err; |
87 | 87 | ||
88 | if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || | 88 | if (compat_put_timespec(&status.tstamp, &src->tstamp) || |
89 | put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || | ||
90 | put_user(status.avail, &src->avail) || | 89 | put_user(status.avail, &src->avail) || |
91 | put_user(status.xruns, &src->xruns)) | 90 | put_user(status.xruns, &src->xruns)) |
92 | return -EFAULT; | 91 | return -EFAULT; |
@@ -94,9 +93,58 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, | |||
94 | return 0; | 93 | return 0; |
95 | } | 94 | } |
96 | 95 | ||
96 | #ifdef CONFIG_X86_X32 | ||
97 | /* X32 ABI has 64bit timespec and 64bit alignment */ | ||
98 | struct snd_rawmidi_status_x32 { | ||
99 | s32 stream; | ||
100 | u32 rsvd; /* alignment */ | ||
101 | struct timespec tstamp; | ||
102 | u32 avail; | ||
103 | u32 xruns; | ||
104 | unsigned char reserved[16]; | ||
105 | } __attribute__((packed)); | ||
106 | |||
107 | #define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst)) | ||
108 | |||
109 | static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile, | ||
110 | struct snd_rawmidi_status_x32 __user *src) | ||
111 | { | ||
112 | int err; | ||
113 | struct snd_rawmidi_status status; | ||
114 | |||
115 | if (rfile->output == NULL) | ||
116 | return -EINVAL; | ||
117 | if (get_user(status.stream, &src->stream)) | ||
118 | return -EFAULT; | ||
119 | |||
120 | switch (status.stream) { | ||
121 | case SNDRV_RAWMIDI_STREAM_OUTPUT: | ||
122 | err = snd_rawmidi_output_status(rfile->output, &status); | ||
123 | break; | ||
124 | case SNDRV_RAWMIDI_STREAM_INPUT: | ||
125 | err = snd_rawmidi_input_status(rfile->input, &status); | ||
126 | break; | ||
127 | default: | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | if (err < 0) | ||
131 | return err; | ||
132 | |||
133 | if (put_timespec(&status.tstamp, &src->tstamp) || | ||
134 | put_user(status.avail, &src->avail) || | ||
135 | put_user(status.xruns, &src->xruns)) | ||
136 | return -EFAULT; | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | #endif /* CONFIG_X86_X32 */ | ||
141 | |||
97 | enum { | 142 | enum { |
98 | SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), | 143 | SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), |
99 | SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), | 144 | SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), |
145 | #ifdef CONFIG_X86_X32 | ||
146 | SNDRV_RAWMIDI_IOCTL_STATUS_X32 = _IOWR('W', 0x20, struct snd_rawmidi_status_x32), | ||
147 | #endif /* CONFIG_X86_X32 */ | ||
100 | }; | 148 | }; |
101 | 149 | ||
102 | static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) | 150 | static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) |
@@ -115,6 +163,10 @@ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsign | |||
115 | return snd_rawmidi_ioctl_params_compat(rfile, argp); | 163 | return snd_rawmidi_ioctl_params_compat(rfile, argp); |
116 | case SNDRV_RAWMIDI_IOCTL_STATUS32: | 164 | case SNDRV_RAWMIDI_IOCTL_STATUS32: |
117 | return snd_rawmidi_ioctl_status_compat(rfile, argp); | 165 | return snd_rawmidi_ioctl_status_compat(rfile, argp); |
166 | #ifdef CONFIG_X86_X32 | ||
167 | case SNDRV_RAWMIDI_IOCTL_STATUS_X32: | ||
168 | return snd_rawmidi_ioctl_status_x32(rfile, argp); | ||
169 | #endif /* CONFIG_X86_X32 */ | ||
118 | } | 170 | } |
119 | return -ENOIOCTLCMD; | 171 | return -ENOIOCTLCMD; |
120 | } | 172 | } |
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index 8db156b207f1..8cdf489df80e 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c | |||
@@ -149,8 +149,6 @@ odev_release(struct inode *inode, struct file *file) | |||
149 | if ((dp = file->private_data) == NULL) | 149 | if ((dp = file->private_data) == NULL) |
150 | return 0; | 150 | return 0; |
151 | 151 | ||
152 | snd_seq_oss_drain_write(dp); | ||
153 | |||
154 | mutex_lock(®ister_mutex); | 152 | mutex_lock(®ister_mutex); |
155 | snd_seq_oss_release(dp); | 153 | snd_seq_oss_release(dp); |
156 | mutex_unlock(®ister_mutex); | 154 | mutex_unlock(®ister_mutex); |
diff --git a/sound/core/seq/oss/seq_oss_device.h b/sound/core/seq/oss/seq_oss_device.h index b43924325249..d7b4d016b547 100644 --- a/sound/core/seq/oss/seq_oss_device.h +++ b/sound/core/seq/oss/seq_oss_device.h | |||
@@ -127,7 +127,6 @@ int snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int co | |||
127 | unsigned int snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_table * wait); | 127 | unsigned int snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_table * wait); |
128 | 128 | ||
129 | void snd_seq_oss_reset(struct seq_oss_devinfo *dp); | 129 | void snd_seq_oss_reset(struct seq_oss_devinfo *dp); |
130 | void snd_seq_oss_drain_write(struct seq_oss_devinfo *dp); | ||
131 | 130 | ||
132 | /* */ | 131 | /* */ |
133 | void snd_seq_oss_process_queue(struct seq_oss_devinfo *dp, abstime_t time); | 132 | void snd_seq_oss_process_queue(struct seq_oss_devinfo *dp, abstime_t time); |
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c index 6779e82b46dd..92c96a95a903 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c | |||
@@ -436,22 +436,6 @@ snd_seq_oss_release(struct seq_oss_devinfo *dp) | |||
436 | 436 | ||
437 | 437 | ||
438 | /* | 438 | /* |
439 | * Wait until the queue is empty (if we don't have nonblock) | ||
440 | */ | ||
441 | void | ||
442 | snd_seq_oss_drain_write(struct seq_oss_devinfo *dp) | ||
443 | { | ||
444 | if (! dp->timer->running) | ||
445 | return; | ||
446 | if (is_write_mode(dp->file_mode) && !is_nonblock_mode(dp->file_mode) && | ||
447 | dp->writeq) { | ||
448 | while (snd_seq_oss_writeq_sync(dp->writeq)) | ||
449 | ; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | |||
454 | /* | ||
455 | * reset sequencer devices | 439 | * reset sequencer devices |
456 | */ | 440 | */ |
457 | void | 441 | void |
diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c index e05802ae6e1b..2e908225d754 100644 --- a/sound/core/timer_compat.c +++ b/sound/core/timer_compat.c | |||
@@ -70,13 +70,14 @@ static int snd_timer_user_status_compat(struct file *file, | |||
70 | struct snd_timer_status32 __user *_status) | 70 | struct snd_timer_status32 __user *_status) |
71 | { | 71 | { |
72 | struct snd_timer_user *tu; | 72 | struct snd_timer_user *tu; |
73 | struct snd_timer_status status; | 73 | struct snd_timer_status32 status; |
74 | 74 | ||
75 | tu = file->private_data; | 75 | tu = file->private_data; |
76 | if (snd_BUG_ON(!tu->timeri)) | 76 | if (snd_BUG_ON(!tu->timeri)) |
77 | return -ENXIO; | 77 | return -ENXIO; |
78 | memset(&status, 0, sizeof(status)); | 78 | memset(&status, 0, sizeof(status)); |
79 | status.tstamp = tu->tstamp; | 79 | status.tstamp.tv_sec = tu->tstamp.tv_sec; |
80 | status.tstamp.tv_nsec = tu->tstamp.tv_nsec; | ||
80 | status.resolution = snd_timer_resolution(tu->timeri); | 81 | status.resolution = snd_timer_resolution(tu->timeri); |
81 | status.lost = tu->timeri->lost; | 82 | status.lost = tu->timeri->lost; |
82 | status.overrun = tu->overrun; | 83 | status.overrun = tu->overrun; |
@@ -88,12 +89,21 @@ static int snd_timer_user_status_compat(struct file *file, | |||
88 | return 0; | 89 | return 0; |
89 | } | 90 | } |
90 | 91 | ||
92 | #ifdef CONFIG_X86_X32 | ||
93 | /* X32 ABI has the same struct as x86-64 */ | ||
94 | #define snd_timer_user_status_x32(file, s) \ | ||
95 | snd_timer_user_status(file, s) | ||
96 | #endif /* CONFIG_X86_X32 */ | ||
97 | |||
91 | /* | 98 | /* |
92 | */ | 99 | */ |
93 | 100 | ||
94 | enum { | 101 | enum { |
95 | SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32), | 102 | SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32), |
96 | SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32), | 103 | SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32), |
104 | #ifdef CONFIG_X86_X32 | ||
105 | SNDRV_TIMER_IOCTL_STATUS_X32 = _IOW('T', 0x14, struct snd_timer_status), | ||
106 | #endif /* CONFIG_X86_X32 */ | ||
97 | }; | 107 | }; |
98 | 108 | ||
99 | static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) | 109 | static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) |
@@ -122,6 +132,10 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns | |||
122 | return snd_timer_user_info_compat(file, argp); | 132 | return snd_timer_user_info_compat(file, argp); |
123 | case SNDRV_TIMER_IOCTL_STATUS32: | 133 | case SNDRV_TIMER_IOCTL_STATUS32: |
124 | return snd_timer_user_status_compat(file, argp); | 134 | return snd_timer_user_status_compat(file, argp); |
135 | #ifdef CONFIG_X86_X32 | ||
136 | case SNDRV_TIMER_IOCTL_STATUS_X32: | ||
137 | return snd_timer_user_status_x32(file, argp); | ||
138 | #endif /* CONFIG_X86_X32 */ | ||
125 | } | 139 | } |
126 | return -ENOIOCTLCMD; | 140 | return -ENOIOCTLCMD; |
127 | } | 141 | } |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 8ee78dbd4c60..bcbc4ee10130 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -2477,13 +2477,6 @@ static int patch_generic_hdmi(struct hda_codec *codec) | |||
2477 | is_broxton(codec)) | 2477 | is_broxton(codec)) |
2478 | codec->core.link_power_control = 1; | 2478 | codec->core.link_power_control = 1; |
2479 | 2479 | ||
2480 | if (codec_has_acomp(codec)) { | ||
2481 | codec->depop_delay = 0; | ||
2482 | spec->i915_audio_ops.audio_ptr = codec; | ||
2483 | spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify; | ||
2484 | snd_hdac_i915_register_notifier(&spec->i915_audio_ops); | ||
2485 | } | ||
2486 | |||
2487 | if (hdmi_parse_codec(codec) < 0) { | 2480 | if (hdmi_parse_codec(codec) < 0) { |
2488 | if (spec->i915_bound) | 2481 | if (spec->i915_bound) |
2489 | snd_hdac_i915_exit(&codec->bus->core); | 2482 | snd_hdac_i915_exit(&codec->bus->core); |
@@ -2505,6 +2498,18 @@ static int patch_generic_hdmi(struct hda_codec *codec) | |||
2505 | 2498 | ||
2506 | init_channel_allocations(); | 2499 | init_channel_allocations(); |
2507 | 2500 | ||
2501 | if (codec_has_acomp(codec)) { | ||
2502 | codec->depop_delay = 0; | ||
2503 | spec->i915_audio_ops.audio_ptr = codec; | ||
2504 | /* intel_audio_codec_enable() or intel_audio_codec_disable() | ||
2505 | * will call pin_eld_notify with using audio_ptr pointer | ||
2506 | * We need make sure audio_ptr is really setup | ||
2507 | */ | ||
2508 | wmb(); | ||
2509 | spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify; | ||
2510 | snd_hdac_i915_register_notifier(&spec->i915_audio_ops); | ||
2511 | } | ||
2512 | |||
2508 | return 0; | 2513 | return 0; |
2509 | } | 2514 | } |
2510 | 2515 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1f357cd72d9c..93d2156b6241 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -5412,6 +5412,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
5412 | SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC), | 5412 | SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC), |
5413 | SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK), | 5413 | SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK), |
5414 | SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), | 5414 | SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), |
5415 | SND_PCI_QUIRK(0x1025, 0x0762, "Acer Aspire E1-472", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), | ||
5415 | SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), | 5416 | SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), |
5416 | SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS), | 5417 | SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS), |
5417 | SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK), | 5418 | SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK), |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 2875b4f6d8c9..7c8941b8b2de 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -2879,7 +2879,7 @@ static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
2879 | { | 2879 | { |
2880 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | 2880 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); |
2881 | 2881 | ||
2882 | ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp); | 2882 | ucontrol->value.integer.value[0] = hdsp_dds_offset(hdsp); |
2883 | return 0; | 2883 | return 0; |
2884 | } | 2884 | } |
2885 | 2885 | ||
@@ -2891,7 +2891,7 @@ static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
2891 | 2891 | ||
2892 | if (!snd_hdsp_use_is_exclusive(hdsp)) | 2892 | if (!snd_hdsp_use_is_exclusive(hdsp)) |
2893 | return -EBUSY; | 2893 | return -EBUSY; |
2894 | val = ucontrol->value.enumerated.item[0]; | 2894 | val = ucontrol->value.integer.value[0]; |
2895 | spin_lock_irq(&hdsp->lock); | 2895 | spin_lock_irq(&hdsp->lock); |
2896 | if (val != hdsp_dds_offset(hdsp)) | 2896 | if (val != hdsp_dds_offset(hdsp)) |
2897 | change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0; | 2897 | change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0; |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 8bc8016c173d..a4a999a0317e 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -1601,6 +1601,9 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) | |||
1601 | { | 1601 | { |
1602 | u64 n; | 1602 | u64 n; |
1603 | 1603 | ||
1604 | if (snd_BUG_ON(rate <= 0)) | ||
1605 | return; | ||
1606 | |||
1604 | if (rate >= 112000) | 1607 | if (rate >= 112000) |
1605 | rate /= 4; | 1608 | rate /= 4; |
1606 | else if (rate >= 56000) | 1609 | else if (rate >= 56000) |
@@ -2215,6 +2218,8 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm) | |||
2215 | } else { | 2218 | } else { |
2216 | /* slave mode, return external sample rate */ | 2219 | /* slave mode, return external sample rate */ |
2217 | rate = hdspm_external_sample_rate(hdspm); | 2220 | rate = hdspm_external_sample_rate(hdspm); |
2221 | if (!rate) | ||
2222 | rate = hdspm->system_sample_rate; | ||
2218 | } | 2223 | } |
2219 | } | 2224 | } |
2220 | 2225 | ||
@@ -2260,8 +2265,11 @@ static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol, | |||
2260 | ucontrol) | 2265 | ucontrol) |
2261 | { | 2266 | { |
2262 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 2267 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
2268 | int rate = ucontrol->value.integer.value[0]; | ||
2263 | 2269 | ||
2264 | hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]); | 2270 | if (rate < 27000 || rate > 207000) |
2271 | return -EINVAL; | ||
2272 | hdspm_set_dds_value(hdspm, ucontrol->value.integer.value[0]); | ||
2265 | return 0; | 2273 | return 0; |
2266 | } | 2274 | } |
2267 | 2275 | ||
@@ -4449,7 +4457,7 @@ static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol, | |||
4449 | { | 4457 | { |
4450 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 4458 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
4451 | 4459 | ||
4452 | ucontrol->value.enumerated.item[0] = hdspm->tco->term; | 4460 | ucontrol->value.integer.value[0] = hdspm->tco->term; |
4453 | 4461 | ||
4454 | return 0; | 4462 | return 0; |
4455 | } | 4463 | } |
@@ -4460,8 +4468,8 @@ static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol, | |||
4460 | { | 4468 | { |
4461 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 4469 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
4462 | 4470 | ||
4463 | if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) { | 4471 | if (hdspm->tco->term != ucontrol->value.integer.value[0]) { |
4464 | hdspm->tco->term = ucontrol->value.enumerated.item[0]; | 4472 | hdspm->tco->term = ucontrol->value.integer.value[0]; |
4465 | 4473 | ||
4466 | hdspm_tco_write(hdspm); | 4474 | hdspm_tco_write(hdspm); |
4467 | 4475 | ||
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 4f6ce1cac8e2..c458d60d5030 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
@@ -1124,6 +1124,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) | |||
1124 | case USB_ID(0x045E, 0x076F): /* MS Lifecam HD-6000 */ | 1124 | case USB_ID(0x045E, 0x076F): /* MS Lifecam HD-6000 */ |
1125 | case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */ | 1125 | case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */ |
1126 | case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */ | 1126 | case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */ |
1127 | case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */ | ||
1127 | case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */ | 1128 | case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */ |
1128 | case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */ | 1129 | case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */ |
1129 | case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */ | 1130 | case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */ |