access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
(ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
SNDRV_CTL_ELEM_ACCESS_INACTIVE|
- SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE|
- SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK));
+ SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE|
+ SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND|
+ SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK));
kctl.info = ncontrol->info;
kctl.get = ncontrol->get;
kctl.put = ncontrol->put;
if (copy_from_user(&tlv, _tlv, sizeof(tlv)))
return -EFAULT;
- if (tlv.length < sizeof(unsigned int) * 3)
+ if (tlv.length < sizeof(unsigned int) * 2)
return -EINVAL;
down_read(&card->controls_rwsem);
kctl = snd_ctl_find_numid(card, tlv.numid);
#include <linux/pm_qos_params.h>
#include <linux/uio.h>
#include <linux/dma-mapping.h>
+#include <linux/math64.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/info.h>
return usecs;
}
+static int calc_boundary(struct snd_pcm_runtime *runtime)
+{
+ u_int64_t boundary;
+
+ boundary = (u_int64_t)runtime->buffer_size *
+ (u_int64_t)runtime->period_size;
+#if BITS_PER_LONG < 64
+ /* try to find lowest common multiple for buffer and period */
+ if (boundary > LONG_MAX - runtime->buffer_size) {
+ u_int32_t remainder = -1;
+ u_int32_t divident = runtime->buffer_size;
+ u_int32_t divisor = runtime->period_size;
+ while (remainder) {
+ remainder = divident % divisor;
+ if (remainder) {
+ divident = divisor;
+ divisor = remainder;
+ }
+ }
+ boundary = div_u64(boundary, divisor);
+ if (boundary > LONG_MAX - runtime->buffer_size)
+ return -ERANGE;
+ }
+#endif
+ if (boundary == 0)
+ return -ERANGE;
+ runtime->boundary = boundary;
+ while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
+ runtime->boundary *= 2;
+ return 0;
+}
+
static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
runtime->stop_threshold = runtime->buffer_size;
runtime->silence_threshold = 0;
runtime->silence_size = 0;
- runtime->boundary = runtime->buffer_size;
- while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
- runtime->boundary *= 2;
+ err = calc_boundary(runtime);
+ if (err < 0)
+ goto _error;
snd_pcm_timer_resolution_change(substream);
runtime->status->state = SNDRV_PCM_STATE_SETUP;