mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 11:19:37 +00:00
Merge branch 'topic/div64-cleanup' into for-linus
* topic/div64-cleanup: ALSA: Clean up 64bit division functions
This commit is contained in:
commit
19b1a15a3d
5 changed files with 9 additions and 84 deletions
|
@ -486,80 +486,6 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream);
|
|||
void snd_pcm_vma_notify_data(void *client, void *data);
|
||||
int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area);
|
||||
|
||||
#if BITS_PER_LONG >= 64
|
||||
|
||||
static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem)
|
||||
{
|
||||
*rem = *n % div;
|
||||
*n /= div;
|
||||
}
|
||||
|
||||
#elif defined(i386)
|
||||
|
||||
static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem)
|
||||
{
|
||||
u_int32_t low, high;
|
||||
low = *n & 0xffffffff;
|
||||
high = *n >> 32;
|
||||
if (high) {
|
||||
u_int32_t high1 = high % div;
|
||||
high /= div;
|
||||
asm("divl %2":"=a" (low), "=d" (*rem):"rm" (div), "a" (low), "d" (high1));
|
||||
*n = (u_int64_t)high << 32 | low;
|
||||
} else {
|
||||
*n = low / div;
|
||||
*rem = low % div;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
static inline void divl(u_int32_t high, u_int32_t low,
|
||||
u_int32_t div,
|
||||
u_int32_t *q, u_int32_t *r)
|
||||
{
|
||||
u_int64_t n = (u_int64_t)high << 32 | low;
|
||||
u_int64_t d = (u_int64_t)div << 31;
|
||||
u_int32_t q1 = 0;
|
||||
int c = 32;
|
||||
while (n > 0xffffffffU) {
|
||||
q1 <<= 1;
|
||||
if (n >= d) {
|
||||
n -= d;
|
||||
q1 |= 1;
|
||||
}
|
||||
d >>= 1;
|
||||
c--;
|
||||
}
|
||||
q1 <<= c;
|
||||
if (n) {
|
||||
low = n;
|
||||
*q = q1 | (low / div);
|
||||
*r = low % div;
|
||||
} else {
|
||||
*r = 0;
|
||||
*q = q1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem)
|
||||
{
|
||||
u_int32_t low, high;
|
||||
low = *n & 0xffffffff;
|
||||
high = *n >> 32;
|
||||
if (high) {
|
||||
u_int32_t high1 = high % div;
|
||||
u_int32_t low1 = low;
|
||||
high /= div;
|
||||
divl(high1, low1, div, &low, rem);
|
||||
*n = (u_int64_t)high << 32 | low;
|
||||
} else {
|
||||
*n = low / div;
|
||||
*rem = low % div;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PCM library
|
||||
*/
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/time.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/string.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/minors.h>
|
||||
|
@ -617,9 +618,7 @@ static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames)
|
|||
#else
|
||||
{
|
||||
u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes;
|
||||
u32 rem;
|
||||
div64_32(&bsize, buffer_size, &rem);
|
||||
return (long)bsize;
|
||||
return div_u64(bsize, buffer_size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/math64.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/info.h>
|
||||
|
@ -452,7 +453,7 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b,
|
|||
*r = 0;
|
||||
return UINT_MAX;
|
||||
}
|
||||
div64_32(&n, c, r);
|
||||
n = div_u64_rem(n, c, r);
|
||||
if (n >= UINT_MAX) {
|
||||
*r = 0;
|
||||
return UINT_MAX;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/math64.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/control.h>
|
||||
|
@ -1047,7 +1048,6 @@ static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames)
|
|||
static void hdsp_set_dds_value(struct hdsp *hdsp, int rate)
|
||||
{
|
||||
u64 n;
|
||||
u32 r;
|
||||
|
||||
if (rate >= 112000)
|
||||
rate /= 4;
|
||||
|
@ -1055,7 +1055,7 @@ static void hdsp_set_dds_value(struct hdsp *hdsp, int rate)
|
|||
rate /= 2;
|
||||
|
||||
n = DDS_NUMERATOR;
|
||||
div64_32(&n, rate, &r);
|
||||
n = div_u64(n, rate);
|
||||
/* n should be less than 2^32 for being written to FREQ register */
|
||||
snd_BUG_ON(n >> 32);
|
||||
/* HDSP_freqReg and HDSP_resetPointer are the same, so keep the DDS
|
||||
|
@ -3097,7 +3097,6 @@ static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct sn
|
|||
static int hdsp_dds_offset(struct hdsp *hdsp)
|
||||
{
|
||||
u64 n;
|
||||
u32 r;
|
||||
unsigned int dds_value = hdsp->dds_value;
|
||||
int system_sample_rate = hdsp->system_sample_rate;
|
||||
|
||||
|
@ -3109,7 +3108,7 @@ static int hdsp_dds_offset(struct hdsp *hdsp)
|
|||
* dds_value = n / rate
|
||||
* rate = n / dds_value
|
||||
*/
|
||||
div64_32(&n, dds_value, &r);
|
||||
n = div_u64(n, dds_value);
|
||||
if (system_sample_rate >= 112000)
|
||||
n *= 4;
|
||||
else if (system_sample_rate >= 56000)
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/moduleparam.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/math64.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
|
@ -831,7 +832,6 @@ static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames)
|
|||
static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
|
||||
{
|
||||
u64 n;
|
||||
u32 r;
|
||||
|
||||
if (rate >= 112000)
|
||||
rate /= 4;
|
||||
|
@ -844,7 +844,7 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
|
|||
*/
|
||||
/* n = 104857600000000ULL; */ /* = 2^20 * 10^8 */
|
||||
n = 110100480000000ULL; /* Value checked for AES32 and MADI */
|
||||
div64_32(&n, rate, &r);
|
||||
n = div_u64(n, rate);
|
||||
/* n should be less than 2^32 for being written to FREQ register */
|
||||
snd_BUG_ON(n >> 32);
|
||||
hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
|
||||
|
|
Loading…
Reference in a new issue