diff options
author | Takashi Iwai <tiwai@suse.de> | 2010-02-01 09:46:00 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-02-01 09:46:00 -0500 |
commit | 30ede1b9f08204db178bf17bb1800dfee8327caa (patch) | |
tree | b06ed97d2dea54eabd854044f58fe1b5ee85eca4 | |
parent | d0d2c38e3963f4f86a9e62d74f45a371458f2787 (diff) | |
parent | 6123637fafbf445cc9ce5774dc9516da0b2daa88 (diff) |
Merge remote branch 'alsa/devel' into topic/misc
-rw-r--r-- | sound/core/control.c | 7 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 39 |
2 files changed, 40 insertions, 6 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index 268ab7471224..439ce64f9d82 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -237,8 +237,9 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, | |||
237 | access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : | 237 | access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : |
238 | (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| | 238 | (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| |
239 | SNDRV_CTL_ELEM_ACCESS_INACTIVE| | 239 | SNDRV_CTL_ELEM_ACCESS_INACTIVE| |
240 | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE| | 240 | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE| |
241 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)); | 241 | SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND| |
242 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)); | ||
242 | kctl.info = ncontrol->info; | 243 | kctl.info = ncontrol->info; |
243 | kctl.get = ncontrol->get; | 244 | kctl.get = ncontrol->get; |
244 | kctl.put = ncontrol->put; | 245 | kctl.put = ncontrol->put; |
@@ -1099,7 +1100,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file, | |||
1099 | 1100 | ||
1100 | if (copy_from_user(&tlv, _tlv, sizeof(tlv))) | 1101 | if (copy_from_user(&tlv, _tlv, sizeof(tlv))) |
1101 | return -EFAULT; | 1102 | return -EFAULT; |
1102 | if (tlv.length < sizeof(unsigned int) * 3) | 1103 | if (tlv.length < sizeof(unsigned int) * 2) |
1103 | return -EINVAL; | 1104 | return -EINVAL; |
1104 | down_read(&card->controls_rwsem); | 1105 | down_read(&card->controls_rwsem); |
1105 | kctl = snd_ctl_find_numid(card, tlv.numid); | 1106 | kctl = snd_ctl_find_numid(card, tlv.numid); |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index b79c777d2118..17935746eb18 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/pm_qos_params.h> | 27 | #include <linux/pm_qos_params.h> |
28 | #include <linux/uio.h> | 28 | #include <linux/uio.h> |
29 | #include <linux/dma-mapping.h> | 29 | #include <linux/dma-mapping.h> |
30 | #include <linux/math64.h> | ||
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/control.h> | 32 | #include <sound/control.h> |
32 | #include <sound/info.h> | 33 | #include <sound/info.h> |
@@ -366,6 +367,38 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime) | |||
366 | return usecs; | 367 | return usecs; |
367 | } | 368 | } |
368 | 369 | ||
370 | static int calc_boundary(struct snd_pcm_runtime *runtime) | ||
371 | { | ||
372 | u_int64_t boundary; | ||
373 | |||
374 | boundary = (u_int64_t)runtime->buffer_size * | ||
375 | (u_int64_t)runtime->period_size; | ||
376 | #if BITS_PER_LONG < 64 | ||
377 | /* try to find lowest common multiple for buffer and period */ | ||
378 | if (boundary > LONG_MAX - runtime->buffer_size) { | ||
379 | u_int32_t remainder = -1; | ||
380 | u_int32_t divident = runtime->buffer_size; | ||
381 | u_int32_t divisor = runtime->period_size; | ||
382 | while (remainder) { | ||
383 | remainder = divident % divisor; | ||
384 | if (remainder) { | ||
385 | divident = divisor; | ||
386 | divisor = remainder; | ||
387 | } | ||
388 | } | ||
389 | boundary = div_u64(boundary, divisor); | ||
390 | if (boundary > LONG_MAX - runtime->buffer_size) | ||
391 | return -ERANGE; | ||
392 | } | ||
393 | #endif | ||
394 | if (boundary == 0) | ||
395 | return -ERANGE; | ||
396 | runtime->boundary = boundary; | ||
397 | while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size) | ||
398 | runtime->boundary *= 2; | ||
399 | return 0; | ||
400 | } | ||
401 | |||
369 | static int snd_pcm_hw_params(struct snd_pcm_substream *substream, | 402 | static int snd_pcm_hw_params(struct snd_pcm_substream *substream, |
370 | struct snd_pcm_hw_params *params) | 403 | struct snd_pcm_hw_params *params) |
371 | { | 404 | { |
@@ -441,9 +474,9 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, | |||
441 | runtime->stop_threshold = runtime->buffer_size; | 474 | runtime->stop_threshold = runtime->buffer_size; |
442 | runtime->silence_threshold = 0; | 475 | runtime->silence_threshold = 0; |
443 | runtime->silence_size = 0; | 476 | runtime->silence_size = 0; |
444 | runtime->boundary = runtime->buffer_size; | 477 | err = calc_boundary(runtime); |
445 | while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size) | 478 | if (err < 0) |
446 | runtime->boundary *= 2; | 479 | goto _error; |
447 | 480 | ||
448 | snd_pcm_timer_resolution_change(substream); | 481 | snd_pcm_timer_resolution_change(substream); |
449 | runtime->status->state = SNDRV_PCM_STATE_SETUP; | 482 | runtime->status->state = SNDRV_PCM_STATE_SETUP; |