Commit 113ba560 authored by Jaroslav Kysela's avatar Jaroslav Kysela Committed by Linus Torvalds

[PATCH] ALSA update [2/10] - 2002/06/26

  - Enhanced bitmasks in PCM - added support for more formats by Takashi and me
  - RME32 driver - added support for ADAT (Digi 32/8)
parent e41ecb2c
......@@ -128,7 +128,7 @@ enum {
* *
*****************************************************************************/
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 1)
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 2)
typedef unsigned long sndrv_pcm_uframes_t;
typedef long sndrv_pcm_sframes_t;
......@@ -191,7 +191,19 @@ enum sndrv_pcm_format {
SNDRV_PCM_FORMAT_MPEG,
SNDRV_PCM_FORMAT_GSM,
SNDRV_PCM_FORMAT_SPECIAL = 31,
SNDRV_PCM_FORMAT_LAST = 31,
SNDRV_PCM_FORMAT_S24_3LE = 32, /* in three bytes */
SNDRV_PCM_FORMAT_S24_3BE, /* in three bytes */
SNDRV_PCM_FORMAT_U24_3LE, /* in three bytes */
SNDRV_PCM_FORMAT_U24_3BE, /* in three bytes */
SNDRV_PCM_FORMAT_S20_3LE, /* in three bytes */
SNDRV_PCM_FORMAT_S20_3BE, /* in three bytes */
SNDRV_PCM_FORMAT_U20_3LE, /* in three bytes */
SNDRV_PCM_FORMAT_U20_3BE, /* in three bytes */
SNDRV_PCM_FORMAT_S18_3LE, /* in three bytes */
SNDRV_PCM_FORMAT_S18_3BE, /* in three bytes */
SNDRV_PCM_FORMAT_U18_3LE, /* in three bytes */
SNDRV_PCM_FORMAT_U18_3BE, /* in three bytes */
SNDRV_PCM_FORMAT_LAST = SNDRV_PCM_FORMAT_U18_3BE,
#ifdef SNDRV_LITTLE_ENDIAN
SNDRV_PCM_FORMAT_S16 = SNDRV_PCM_FORMAT_S16_LE,
......@@ -284,7 +296,7 @@ enum sndrv_pcm_hw_param {
SNDRV_PCM_HW_PARAM_SUBFORMAT, /* Subformat */
SNDRV_PCM_HW_PARAM_LAST_MASK = SNDRV_PCM_HW_PARAM_SUBFORMAT,
SNDRV_PCM_HW_PARAM_SAMPLE_BITS, /* Bits per sample */
SNDRV_PCM_HW_PARAM_SAMPLE_BITS = 8, /* Bits per sample */
SNDRV_PCM_HW_PARAM_FIRST_INTERVAL = SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
SNDRV_PCM_HW_PARAM_FRAME_BITS, /* Bits per frame */
SNDRV_PCM_HW_PARAM_CHANNELS, /* Channels */
......@@ -298,8 +310,7 @@ enum sndrv_pcm_hw_param {
SNDRV_PCM_HW_PARAM_BUFFER_SIZE, /* Size of buffer in frames */
SNDRV_PCM_HW_PARAM_BUFFER_BYTES, /* Size of buffer in bytes */
SNDRV_PCM_HW_PARAM_TICK_TIME, /* Approx tick duration in us */
SNDRV_PCM_HW_PARAM_LAST_INTERVAL = SNDRV_PCM_HW_PARAM_TICK_TIME,
SNDRV_PCM_HW_PARAM_LAST = SNDRV_PCM_HW_PARAM_LAST_INTERVAL,
SNDRV_PCM_HW_PARAM_LAST_INTERVAL = SNDRV_PCM_HW_PARAM_TICK_TIME
};
#define SNDRV_PCM_HW_PARAMS_RUNTIME (1<<0)
......@@ -312,20 +323,28 @@ struct sndrv_interval {
empty:1;
};
#define SNDRV_MASK_MAX 256
struct sndrv_mask {
u_int32_t bits[(SNDRV_MASK_MAX+31)/32];
};
struct sndrv_pcm_hw_params {
unsigned int flags;
unsigned int masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
struct sndrv_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
struct sndrv_mask mres[5]; /* reserved masks */
struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
unsigned int rmask;
unsigned int cmask;
struct sndrv_interval ires[9]; /* reserved intervals */
unsigned int rmask; /* W: requested masks */
unsigned int cmask; /* R: changed masks */
unsigned int info; /* R: Info flags for returned setup */
unsigned int msbits; /* R: used most significant bits */
unsigned int rate_num; /* R: rate numerator */
unsigned int rate_den; /* R: rate denominator */
sndrv_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */
unsigned char reserved[64];
unsigned char reserved[64]; /* reserved for future */
};
enum sndrv_pcm_tstamp {
......@@ -345,7 +364,7 @@ struct sndrv_pcm_sw_params {
sndrv_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */
sndrv_pcm_uframes_t silence_size; /* silence block size */
sndrv_pcm_uframes_t boundary; /* pointers wrap point */
unsigned char reserved[64];
unsigned char reserved[64]; /* reserved for future */
};
struct sndrv_pcm_channel_info {
......
......@@ -48,6 +48,7 @@ typedef struct sndrv_pcm_channel_info snd_pcm_channel_info_t;
typedef struct sndrv_pcm_status snd_pcm_status_t;
typedef struct sndrv_pcm_mmap_status snd_pcm_mmap_status_t;
typedef struct sndrv_pcm_mmap_control snd_pcm_mmap_control_t;
typedef struct sndrv_mask snd_mask_t;
#define _snd_pcm_substream_chip(substream) ((substream)->pcm->private_data)
#define snd_pcm_substream_chip(substream) snd_magic_cast1(chip_t, _snd_pcm_substream_chip(substream), return -ENXIO)
......@@ -67,7 +68,7 @@ typedef struct _snd_pcm_runtime snd_pcm_runtime_t;
typedef struct _snd_pcm_hardware {
unsigned int info; /* SNDRV_PCM_INFO_* */
unsigned int formats; /* SNDRV_PCM_FMTBIT_* */
u64 formats; /* SNDRV_PCM_FMTBIT_* */
unsigned int rates; /* SNDRV_PCM_RATE_* */
unsigned int rate_min; /* min rate */
unsigned int rate_max; /* max rate */
......@@ -148,32 +149,44 @@ typedef struct _snd_pcm_ops {
SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000)
#define SNDRV_PCM_RATE_8000_192000 (SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\
SNDRV_PCM_RATE_192000)
#define SNDRV_PCM_FMTBIT_S8 (1 << SNDRV_PCM_FORMAT_S8)
#define SNDRV_PCM_FMTBIT_U8 (1 << SNDRV_PCM_FORMAT_U8)
#define SNDRV_PCM_FMTBIT_S16_LE (1 << SNDRV_PCM_FORMAT_S16_LE)
#define SNDRV_PCM_FMTBIT_S16_BE (1 << SNDRV_PCM_FORMAT_S16_BE)
#define SNDRV_PCM_FMTBIT_U16_LE (1 << SNDRV_PCM_FORMAT_U16_LE)
#define SNDRV_PCM_FMTBIT_U16_BE (1 << SNDRV_PCM_FORMAT_U16_BE)
#define SNDRV_PCM_FMTBIT_S24_LE (1 << SNDRV_PCM_FORMAT_S24_LE)
#define SNDRV_PCM_FMTBIT_S24_BE (1 << SNDRV_PCM_FORMAT_S24_BE)
#define SNDRV_PCM_FMTBIT_U24_LE (1 << SNDRV_PCM_FORMAT_U24_LE)
#define SNDRV_PCM_FMTBIT_U24_BE (1 << SNDRV_PCM_FORMAT_U24_BE)
#define SNDRV_PCM_FMTBIT_S32_LE (1 << SNDRV_PCM_FORMAT_S32_LE)
#define SNDRV_PCM_FMTBIT_S32_BE (1 << SNDRV_PCM_FORMAT_S32_BE)
#define SNDRV_PCM_FMTBIT_U32_LE (1 << SNDRV_PCM_FORMAT_U32_LE)
#define SNDRV_PCM_FMTBIT_U32_BE (1 << SNDRV_PCM_FORMAT_U32_BE)
#define SNDRV_PCM_FMTBIT_FLOAT_LE (1 << SNDRV_PCM_FORMAT_FLOAT_LE)
#define SNDRV_PCM_FMTBIT_FLOAT_BE (1 << SNDRV_PCM_FORMAT_FLOAT_BE)
#define SNDRV_PCM_FMTBIT_FLOAT64_LE (1 << SNDRV_PCM_FORMAT_FLOAT64_LE)
#define SNDRV_PCM_FMTBIT_FLOAT64_BE (1 << SNDRV_PCM_FORMAT_FLOAT64_BE)
#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE (1 << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE)
#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE (1 << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE)
#define SNDRV_PCM_FMTBIT_MU_LAW (1 << SNDRV_PCM_FORMAT_MU_LAW)
#define SNDRV_PCM_FMTBIT_A_LAW (1 << SNDRV_PCM_FORMAT_A_LAW)
#define SNDRV_PCM_FMTBIT_IMA_ADPCM (1 << SNDRV_PCM_FORMAT_IMA_ADPCM)
#define SNDRV_PCM_FMTBIT_MPEG (1 << SNDRV_PCM_FORMAT_MPEG)
#define SNDRV_PCM_FMTBIT_GSM (1 << SNDRV_PCM_FORMAT_GSM)
#define SNDRV_PCM_FMTBIT_SPECIAL (1 << SNDRV_PCM_FORMAT_SPECIAL)
#define SNDRV_PCM_FMTBIT_S8 (1ULL << SNDRV_PCM_FORMAT_S8)
#define SNDRV_PCM_FMTBIT_U8 (1ULL << SNDRV_PCM_FORMAT_U8)
#define SNDRV_PCM_FMTBIT_S16_LE (1ULL << SNDRV_PCM_FORMAT_S16_LE)
#define SNDRV_PCM_FMTBIT_S16_BE (1ULL << SNDRV_PCM_FORMAT_S16_BE)
#define SNDRV_PCM_FMTBIT_U16_LE (1ULL << SNDRV_PCM_FORMAT_U16_LE)
#define SNDRV_PCM_FMTBIT_U16_BE (1ULL << SNDRV_PCM_FORMAT_U16_BE)
#define SNDRV_PCM_FMTBIT_S24_LE (1ULL << SNDRV_PCM_FORMAT_S24_LE)
#define SNDRV_PCM_FMTBIT_S24_BE (1ULL << SNDRV_PCM_FORMAT_S24_BE)
#define SNDRV_PCM_FMTBIT_U24_LE (1ULL << SNDRV_PCM_FORMAT_U24_LE)
#define SNDRV_PCM_FMTBIT_U24_BE (1ULL << SNDRV_PCM_FORMAT_U24_BE)
#define SNDRV_PCM_FMTBIT_S32_LE (1ULL << SNDRV_PCM_FORMAT_S32_LE)
#define SNDRV_PCM_FMTBIT_S32_BE (1ULL << SNDRV_PCM_FORMAT_S32_BE)
#define SNDRV_PCM_FMTBIT_U32_LE (1ULL << SNDRV_PCM_FORMAT_U32_LE)
#define SNDRV_PCM_FMTBIT_U32_BE (1ULL << SNDRV_PCM_FORMAT_U32_BE)
#define SNDRV_PCM_FMTBIT_FLOAT_LE (1ULL << SNDRV_PCM_FORMAT_FLOAT_LE)
#define SNDRV_PCM_FMTBIT_FLOAT_BE (1ULL << SNDRV_PCM_FORMAT_FLOAT_BE)
#define SNDRV_PCM_FMTBIT_FLOAT64_LE (1ULL << SNDRV_PCM_FORMAT_FLOAT64_LE)
#define SNDRV_PCM_FMTBIT_FLOAT64_BE (1ULL << SNDRV_PCM_FORMAT_FLOAT64_BE)
#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE)
#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE)
#define SNDRV_PCM_FMTBIT_MU_LAW (1ULL << SNDRV_PCM_FORMAT_MU_LAW)
#define SNDRV_PCM_FMTBIT_A_LAW (1ULL << SNDRV_PCM_FORMAT_A_LAW)
#define SNDRV_PCM_FMTBIT_IMA_ADPCM (1ULL << SNDRV_PCM_FORMAT_IMA_ADPCM)
#define SNDRV_PCM_FMTBIT_MPEG (1ULL << SNDRV_PCM_FORMAT_MPEG)
#define SNDRV_PCM_FMTBIT_GSM (1ULL << SNDRV_PCM_FORMAT_GSM)
#define SNDRV_PCM_FMTBIT_SPECIAL (1ULL << SNDRV_PCM_FORMAT_SPECIAL)
#define SNDRV_PCM_FMTBIT_S24_3LE (1ULL << SNDRV_PCM_FORMAT_S24_3LE)
#define SNDRV_PCM_FMTBIT_U24_3LE (1ULL << SNDRV_PCM_FORMAT_U24_3LE)
#define SNDRV_PCM_FMTBIT_S24_3BE (1ULL << SNDRV_PCM_FORMAT_S24_3BE)
#define SNDRV_PCM_FMTBIT_U24_3BE (1ULL << SNDRV_PCM_FORMAT_U24_3BE)
#define SNDRV_PCM_FMTBIT_S20_3LE (1ULL << SNDRV_PCM_FORMAT_S20_3LE)
#define SNDRV_PCM_FMTBIT_U20_3LE (1ULL << SNDRV_PCM_FORMAT_U20_3LE)
#define SNDRV_PCM_FMTBIT_S20_3BE (1ULL << SNDRV_PCM_FORMAT_S20_3BE)
#define SNDRV_PCM_FMTBIT_U20_3BE (1ULL << SNDRV_PCM_FORMAT_U20_3BE)
#define SNDRV_PCM_FMTBIT_S18_3LE (1ULL << SNDRV_PCM_FORMAT_S18_3LE)
#define SNDRV_PCM_FMTBIT_U18_3LE (1ULL << SNDRV_PCM_FORMAT_U18_3LE)
#define SNDRV_PCM_FMTBIT_S18_3BE (1ULL << SNDRV_PCM_FORMAT_S18_3BE)
#define SNDRV_PCM_FMTBIT_U18_3BE (1ULL << SNDRV_PCM_FORMAT_U18_3BE)
#ifdef SNDRV_LITTLE_ENDIAN
#define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE
......@@ -217,8 +230,8 @@ struct _snd_pcm_hw_rule {
};
typedef struct _snd_pcm_hw_constraints {
unsigned int masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
snd_mask_t masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
snd_interval_t intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
unsigned int rules_num;
......@@ -226,8 +239,8 @@ typedef struct _snd_pcm_hw_constraints {
snd_pcm_hw_rule_t *rules;
} snd_pcm_hw_constraints_t;
static inline unsigned int *constrs_mask(snd_pcm_hw_constraints_t *constrs,
snd_pcm_hw_param_t var)
static inline snd_mask_t *constrs_mask(snd_pcm_hw_constraints_t *constrs,
snd_pcm_hw_param_t var)
{
return &constrs->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK];
}
......@@ -648,13 +661,10 @@ static inline int hw_is_interval(int var)
var <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL;
}
typedef unsigned int snd_mask_t;
#define SND_MASK_MAX 32
static inline snd_mask_t *hw_param_mask(snd_pcm_hw_params_t *params,
snd_pcm_hw_param_t var)
{
return (snd_mask_t*)&params->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK];
return &params->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK];
}
static inline snd_interval_t *hw_param_interval(snd_pcm_hw_params_t *params,
......@@ -675,9 +685,9 @@ static inline const snd_interval_t *hw_param_interval_c(const snd_pcm_hw_params_
return (const snd_interval_t *)hw_param_interval((snd_pcm_hw_params_t*) params, var);
}
#define params_access(p) (ffs(*hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS)) - 1)
#define params_format(p) (ffs(*hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT)) - 1)
#define params_subformat(p) (ffs(*hw_param_mask((p), SNDRV_PCM_HW_PARAM_SUBFORMAT)) - 1)
#define params_access(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS))
#define params_format(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT))
#define params_subformat(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_SUBFORMAT))
#define params_channels(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_CHANNELS)->min
#define params_rate(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_RATE)->min
#define params_period_size(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->min
......@@ -735,7 +745,9 @@ int snd_pcm_hw_constraints_init(snd_pcm_substream_t *substream);
int snd_pcm_hw_constraints_complete(snd_pcm_substream_t *substream);
int snd_pcm_hw_constraint_mask(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
unsigned int mask);
u_int32_t mask);
int snd_pcm_hw_constraint_mask64(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
u_int64_t mask);
int snd_pcm_hw_constraint_minmax(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
unsigned int min, unsigned int max);
int snd_pcm_hw_constraint_integer(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var);
......
......@@ -36,10 +36,14 @@ extern int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params,
snd_pcm_hw_param_t var, unsigned int val, int dir);
/* To share the same code we have alsa-lib */
#define snd_mask_bits(mask) (*(mask))
#define INLINE static inline
#define assert(a) (void)(a)
#define SNDRV_MASK_BITS 64 /* we use so far 64bits only */
#define SNDRV_MASK_SIZE (SNDRV_MASK_BITS / 32)
#define MASK_OFS(i) ((i) >> 5)
#define MASK_BIT(i) (1U << ((i) & 31))
INLINE unsigned int ld2(u_int32_t v)
{
unsigned r = 0;
......@@ -72,91 +76,119 @@ INLINE size_t snd_mask_sizeof(void)
INLINE void snd_mask_none(snd_mask_t *mask)
{
snd_mask_bits(mask) = 0;
memset(mask, 0, sizeof(*mask));
}
INLINE void snd_mask_any(snd_mask_t *mask)
{
snd_mask_bits(mask) = ~0U;
}
INLINE void snd_mask_load(snd_mask_t *mask, unsigned int msk)
{
snd_mask_bits(mask) = msk;
memset(mask, 0xff, SNDRV_MASK_SIZE * sizeof(u_int32_t));
}
INLINE int snd_mask_empty(const snd_mask_t *mask)
{
return snd_mask_bits(mask) == 0;
int i;
for (i = 0; i < SNDRV_MASK_SIZE; i++)
if (mask->bits[i])
return 0;
return 1;
}
INLINE unsigned int snd_mask_min(const snd_mask_t *mask)
{
int i;
assert(!snd_mask_empty(mask));
return ffs(snd_mask_bits(mask)) - 1;
for (i = 0; i < SNDRV_MASK_SIZE; i++) {
if (mask->bits[i])
return ffs(mask->bits[i]) - 1 + (i << 5);
}
return 0;
}
INLINE unsigned int snd_mask_max(const snd_mask_t *mask)
{
int i;
assert(!snd_mask_empty(mask));
return ld2(snd_mask_bits(mask));
for (i = SNDRV_MASK_SIZE - 1; i >= 0; i--) {
if (mask->bits[i])
return ld2(mask->bits[i]) + (i << 5);
}
return 0;
}
INLINE void snd_mask_set(snd_mask_t *mask, unsigned int val)
{
assert(val <= SND_MASK_MAX);
snd_mask_bits(mask) |= (1U << val);
assert(val <= SNDRV_MASK_BITS);
mask->bits[MASK_OFS(val)] |= MASK_BIT(val);
}
INLINE void snd_mask_reset(snd_mask_t *mask, unsigned int val)
{
assert(val <= SND_MASK_MAX);
snd_mask_bits(mask) &= ~(1U << val);
assert(val <= SNDRV_MASK_BITS);
mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val);
}
INLINE void snd_mask_set_range(snd_mask_t *mask, unsigned int from, unsigned int to)
{
assert(to <= SND_MASK_MAX && from <= to);
snd_mask_bits(mask) |= ((1U << (from - to + 1)) - 1) << from;
int i;
assert(to <= SNDRV_MASK_BITS && from <= to);
for (i = from; i <= to; i++)
mask->bits[MASK_OFS(i)] |= MASK_BIT(i);
}
INLINE void snd_mask_reset_range(snd_mask_t *mask, unsigned int from, unsigned int to)
{
assert(to <= SND_MASK_MAX && from <= to);
snd_mask_bits(mask) &= ~(((1U << (from - to + 1)) - 1) << from);
int i;
assert(to <= SNDRV_MASK_BITS && from <= to);
for (i = from; i <= to; i++)
mask->bits[MASK_OFS(i)] &= ~MASK_BIT(i);
}
INLINE void snd_mask_leave(snd_mask_t *mask, unsigned int val)
{
assert(val <= SND_MASK_MAX);
snd_mask_bits(mask) &= 1U << val;
unsigned int v;
assert(val <= SNDRV_MASK_BITS);
v = mask->bits[MASK_OFS(val)] & MASK_BIT(val);
snd_mask_none(mask);
mask->bits[MASK_OFS(val)] = v;
}
INLINE void snd_mask_intersect(snd_mask_t *mask, const snd_mask_t *v)
{
snd_mask_bits(mask) &= snd_mask_bits(v);
int i;
for (i = 0; i < SNDRV_MASK_SIZE; i++)
mask->bits[i] &= v->bits[i];
}
INLINE int snd_mask_eq(const snd_mask_t *mask, const snd_mask_t *v)
{
return snd_mask_bits(mask) == snd_mask_bits(v);
return ! memcmp(mask, v, SNDRV_MASK_SIZE * sizeof(u_int32_t));
}
INLINE void snd_mask_copy(snd_mask_t *mask, const snd_mask_t *v)
{
snd_mask_bits(mask) = snd_mask_bits(v);
*mask = *v;
}
INLINE int snd_mask_test(const snd_mask_t *mask, unsigned int val)
{
assert(val <= SND_MASK_MAX);
return snd_mask_bits(mask) & (1U << val);
assert(val <= SNDRV_MASK_BITS);
return mask->bits[MASK_OFS(val)] & MASK_BIT(val);
}
INLINE int snd_mask_single(const snd_mask_t *mask)
{
int i, c = 0;
assert(!snd_mask_empty(mask));
return !(snd_mask_bits(mask) & (snd_mask_bits(mask) - 1));
for (i = 0; i < SNDRV_MASK_SIZE; i++) {
if (! mask->bits[i])
continue;
if (mask->bits[i] & (mask->bits[i] - 1))
return 0;
if (c)
return 0;
c++;
}
return 1;
}
INLINE int snd_mask_refine(snd_mask_t *mask, const snd_mask_t *v)
......@@ -204,7 +236,7 @@ INLINE int snd_mask_refine_max(snd_mask_t *mask, unsigned int val)
assert(!snd_mask_empty(mask));
if (snd_mask_max(mask) <= val)
return 0;
snd_mask_reset_range(mask, val + 1, SND_MASK_MAX);
snd_mask_reset_range(mask, val + 1, SNDRV_MASK_BITS);
if (snd_mask_empty(mask))
return -EINVAL;
return 1;
......
/* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0rc2"
#define CONFIG_SND_DATE " (Fri Jun 21 12:21:17 2002 UTC)"
#define CONFIG_SND_DATE " (Wed Jun 26 18:12:42 2002 UTC)"
......@@ -303,12 +303,94 @@ static int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long a
}
struct sndrv_pcm_hw_params_old32 {
u32 flags;
u32 masks[SNDRV_PCM_HW_PARAM_SUBFORMAT -
SNDRV_PCM_HW_PARAM_ACCESS + 1];
struct sndrv_interval32 intervals[SNDRV_PCM_HW_PARAM_TICK_TIME -
SNDRV_PCM_HW_PARAM_SAMPLE_BITS + 1];
u32 rmask;
u32 cmask;
u32 info;
u32 msbits;
u32 rate_num;
u32 rate_den;
u32 fifo_size;
unsigned char reserved[64];
} __attribute__((packed));
#define __OLD_TO_NEW_MASK(x) ((x&7)|((x&0x07fffff8)<<5))
#define __NEW_TO_OLD_MASK(x) ((x&7)|((x&0xffffff00)>>5))
static void snd_pcm_hw_convert_from_old_params(snd_pcm_hw_params_t *params, struct sndrv_pcm_hw_params_old32 *oparams)
{
unsigned int i;
memset(params, 0, sizeof(*params));
params->flags = oparams->flags;
for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++)
params->masks[i].bits[0] = oparams->masks[i];
memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals));
params->rmask = __OLD_TO_NEW_MASK(oparams->rmask);
params->cmask = __OLD_TO_NEW_MASK(oparams->cmask);
params->info = oparams->info;
params->msbits = oparams->msbits;
params->rate_num = oparams->rate_num;
params->rate_den = oparams->rate_den;
params->fifo_size = oparams->fifo_size;
}
static void snd_pcm_hw_convert_to_old_params(struct sndrv_pcm_hw_params_old32 *oparams, snd_pcm_hw_params_t *params)
{
unsigned int i;
memset(oparams, 0, sizeof(*oparams));
oparams->flags = params->flags;
for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++)
oparams->masks[i] = params->masks[i].bits[0];
memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals));
oparams->rmask = __NEW_TO_OLD_MASK(params->rmask);
oparams->cmask = __NEW_TO_OLD_MASK(params->cmask);
oparams->info = params->info;
oparams->msbits = params->msbits;
oparams->rate_num = params->rate_num;
oparams->rate_den = params->rate_den;
oparams->fifo_size = params->fifo_size;
}
static int _snd_ioctl32_pcm_hw_params_old(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
{
struct sndrv_pcm_hw_params_old32 data32;
struct sndrv_pcm_hw_params data;
mm_segment_t oldseg = get_fs();
int err;
set_fs(KERNEL_DS);
if (copy_from_user(&data32, (void*)arg, sizeof(data32))) {
err = -EFAULT;
goto __err;
}
snd_pcm_hw_convert_from_old_params(&data, &data32);
err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
if (err < 0)
goto __err;
snd_pcm_hw_convert_to_old_params(&data32, &data);
if (copy_to_user((void*)arg, &data32, sizeof(data32))) {
err = -EFAULT;
goto __err;
}
__err: set_fs(oldseg);
return err;
}
/*
*/
DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_refine, pcm_hw_params, SNDRV_PCM_IOCTL_HW_REFINE);
DEFINE_ALSA_IOCTL_ENTRY(pcm_sw_params, pcm_sw_params, SNDRV_PCM_IOCTL_SW_PARAMS);
DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_params, pcm_hw_params, SNDRV_PCM_IOCTL_HW_PARAMS);
DEFINE_ALSA_IOCTL_ENTRY(pcm_sw_params, pcm_sw_params, SNDRV_PCM_IOCTL_SW_PARAMS);
DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_refine_old, pcm_hw_params_old, SNDRV_PCM_IOCTL_HW_REFINE);
DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_params_old, pcm_hw_params_old, SNDRV_PCM_IOCTL_HW_PARAMS);
DEFINE_ALSA_IOCTL_ENTRY(pcm_status, pcm_status, SNDRV_PCM_IOCTL_STATUS);
DEFINE_ALSA_IOCTL_ENTRY(pcm_delay, pcm_sframes_str, SNDRV_PCM_IOCTL_DELAY);
DEFINE_ALSA_IOCTL_ENTRY(pcm_channel_info, pcm_channel_info, SNDRV_PCM_IOCTL_CHANNEL_INFO);
......@@ -335,6 +417,9 @@ enum {
SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct sndrv_xferi32),
SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct sndrv_xfern32),
SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct sndrv_xfern32),
SNDRV_PCM_IOCTL_HW_REFINE_OLD32 = _IOWR('A', 0x10, struct sndrv_pcm_hw_params_old32),
SNDRV_PCM_IOCTL_HW_PARAMS_OLD32 = _IOWR('A', 0x11, struct sndrv_pcm_hw_params_old32),
};
struct ioctl32_mapper pcm_mappers[] = {
......@@ -342,6 +427,8 @@ struct ioctl32_mapper pcm_mappers[] = {
{ SNDRV_PCM_IOCTL_INFO, NULL },
{ SNDRV_PCM_IOCTL_HW_REFINE32, AP(pcm_hw_refine) },
{ SNDRV_PCM_IOCTL_HW_PARAMS32, AP(pcm_hw_params) },
{ SNDRV_PCM_IOCTL_HW_REFINE_OLD32, AP(pcm_hw_refine_old) },
{ SNDRV_PCM_IOCTL_HW_PARAMS_OLD32, AP(pcm_hw_params_old) },
{ SNDRV_PCM_IOCTL_HW_FREE, NULL },
{ SNDRV_PCM_IOCTL_SW_PARAMS32, AP(pcm_sw_params) },
{ SNDRV_PCM_IOCTL_STATUS32, AP(pcm_status) },
......
......@@ -24,6 +24,7 @@
#include <linux/time.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include "pcm_plugin.h"
#define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1)
......
......@@ -267,8 +267,8 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream)
int err;
int direct;
int format, sformat, n;
unsigned int sformat_mask;
unsigned int mask;
snd_mask_t sformat_mask;
snd_mask_t mask;
if (atomic_read(&runtime->mmap_count)) {
direct = 1;
......@@ -280,12 +280,13 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream)
_snd_pcm_hw_params_any(&sparams);
_snd_pcm_hw_param_setinteger(&sparams, SNDRV_PCM_HW_PARAM_PERIODS);
_snd_pcm_hw_param_min(&sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0);
snd_mask_none(&mask);
if (atomic_read(&runtime->mmap_count))
mask = 1 << SNDRV_PCM_ACCESS_MMAP_INTERLEAVED;
snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
else {
mask = 1 << SNDRV_PCM_ACCESS_RW_INTERLEAVED;
snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED);
if (!direct)
mask |= 1 << SNDRV_PCM_ACCESS_RW_NONINTERLEAVED;
snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
}
err = snd_pcm_hw_param_mask(substream, &sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask);
if (err < 0) {
......@@ -301,11 +302,11 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream)
if (direct)
sformat = format;
else
sformat = snd_pcm_plug_slave_format(format, sformat_mask);
sformat = snd_pcm_plug_slave_format(format, &sformat_mask);
if (sformat < 0 || !(sformat_mask & (1 << sformat))) {
if (sformat < 0 || !snd_mask_test(&sformat_mask, sformat)) {
for (sformat = 0; sformat <= SNDRV_PCM_FORMAT_LAST; sformat++) {
if ((sformat_mask & (1 << sformat)) &&
if (snd_mask_test(&sformat_mask, sformat) &&
snd_pcm_oss_format_to(sformat) >= 0)
break;
}
......@@ -935,7 +936,7 @@ static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file)
int direct;
snd_pcm_hw_params_t params;
unsigned int formats = 0;
unsigned int format_mask;
snd_mask_t format_mask;
int fmt;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
return err;
......@@ -955,7 +956,7 @@ static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file)
snd_assert(err >= 0, return err);
format_mask = *hw_param_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT);
for (fmt = 0; fmt < 32; ++fmt) {
if (format_mask & (1 << fmt)) {
if (snd_mask_test(&format_mask, fmt)) {
int f = snd_pcm_oss_format_to(fmt);
if (f >= 0)
formats |= f;
......
......@@ -31,6 +31,7 @@
#include <linux/vmalloc.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include "pcm_plugin.h"
#define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first)
......@@ -280,20 +281,23 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(snd_pcm_plug_t *plug, snd_pcm_uframes_
return frames;
}
unsigned int snd_pcm_plug_formats(unsigned int formats)
static int snd_pcm_plug_formats(snd_mask_t *mask, int format)
{
int linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
snd_mask_t formats = *mask;
u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |
SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE |
SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |
SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE);
formats |= SNDRV_PCM_FMTBIT_MU_LAW;
snd_mask_set(&formats, SNDRV_PCM_FORMAT_MU_LAW);
if (formats & linfmts)
formats |= linfmts;
return formats;
if (formats.bits[0] & (u32)linfmts)
formats.bits[0] |= (u32)linfmts;
if (formats.bits[1] & (u32)(linfmts >> 32))
formats.bits[1] |= (u32)(linfmts >> 32);
return snd_mask_test(&formats, format);
}
static int preferred_formats[] = {
......@@ -313,11 +317,11 @@ static int preferred_formats[] = {
SNDRV_PCM_FORMAT_U8
};
int snd_pcm_plug_slave_format(int format, unsigned int format_mask)
int snd_pcm_plug_slave_format(int format, snd_mask_t *format_mask)
{
if (format_mask & (1 << format))
if (snd_mask_test(format_mask, format))
return format;
if ((snd_pcm_plug_formats(format_mask) & (1 << format)) == 0)
if (! snd_pcm_plug_formats(format_mask, format))
return -EINVAL;
if (snd_pcm_format_linear(format)) {
int width = snd_pcm_format_width(format);
......@@ -333,7 +337,7 @@ int snd_pcm_plug_slave_format(int format, unsigned int format_mask)
for (sgn = 0; sgn < 2; ++sgn) {
format1 = snd_pcm_build_linear_format(width1, unsignd1, big1);
if (format1 >= 0 &&
format_mask & (1 << format1))
snd_mask_test(format_mask, format1))
goto _found;
unsignd1 = !unsignd1;
}
......@@ -354,7 +358,7 @@ int snd_pcm_plug_slave_format(int format, unsigned int format_mask)
case SNDRV_PCM_FORMAT_MU_LAW:
for (i = 0; i < sizeof(preferred_formats) / sizeof(preferred_formats[0]); ++i) {
int format1 = preferred_formats[i];
if (format_mask & (1 << format1))
if (snd_mask_test(format_mask, format1))
return format1;
}
default:
......
......@@ -197,13 +197,11 @@ int snd_pcm_plugin_build_copy(snd_pcm_plug_t *handle,
snd_pcm_plugin_format_t *dst_format,
snd_pcm_plugin_t **r_plugin);
unsigned int snd_pcm_plug_formats(unsigned int formats);
int snd_pcm_plug_format_plugins(snd_pcm_plug_t *substream,
snd_pcm_hw_params_t *params,
snd_pcm_hw_params_t *slave_params);
int snd_pcm_plug_slave_format(int format, unsigned int format_mask);
int snd_pcm_plug_slave_format(int format, snd_mask_t *format_mask);
int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin);
......
......@@ -184,6 +184,18 @@ char *snd_pcm_format_names[] = {
FORMAT(MPEG),
FORMAT(GSM),
FORMAT(SPECIAL),
FORMAT(S24_3LE),
FORMAT(S24_3BE),
FORMAT(U24_3LE),
FORMAT(U24_3BE),
FORMAT(S20_3LE),
FORMAT(S20_3BE),
FORMAT(U20_3LE),
FORMAT(U20_3BE),
FORMAT(S18_3LE),
FORMAT(S18_3BE),
FORMAT(U18_3LE),
FORMAT(U18_3BE),
};
char *snd_pcm_subformat_names[] = {
......
......@@ -810,12 +810,26 @@ int snd_pcm_hw_rule_add(snd_pcm_runtime_t *runtime, unsigned int cond,
}
int snd_pcm_hw_constraint_mask(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
unsigned int mask)
u_int32_t mask)
{
snd_pcm_hw_constraints_t *constrs = &runtime->hw_constraints;
unsigned int *maskp = constrs_mask(constrs, var);
*maskp &= mask;
if (*maskp == 0)
snd_mask_t *maskp = constrs_mask(constrs, var);
*maskp->bits &= mask;
memset(maskp->bits + 1, 0, (SNDRV_MASK_MAX-32) / 8); /* clear rest */
if (*maskp->bits == 0)
return -EINVAL;
return 0;
}
int snd_pcm_hw_constraint_mask64(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
u_int64_t mask)
{
snd_pcm_hw_constraints_t *constrs = &runtime->hw_constraints;
snd_mask_t *maskp = constrs_mask(constrs, var);
maskp->bits[0] &= (u_int32_t)mask;
maskp->bits[1] &= (u_int32_t)(mask >> 32);
memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX-64) / 8); /* clear rest */
if (! maskp->bits[0] && ! maskp->bits[1])
return -EINVAL;
return 0;
}
......@@ -982,7 +996,9 @@ void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
{
unsigned int k;
memset(params, 0, sizeof(*params));
for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST; k++)
for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++)
_snd_pcm_hw_param_any(params, k);
for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
_snd_pcm_hw_param_any(params, k);
params->info = ~0U;
}
......
......@@ -41,6 +41,12 @@ int snd_pcm_format_signed(snd_pcm_format_t format)
case SNDRV_PCM_FORMAT_S24_BE:
case SNDRV_PCM_FORMAT_S32_LE:
case SNDRV_PCM_FORMAT_S32_BE:
case SNDRV_PCM_FORMAT_S24_3LE:
case SNDRV_PCM_FORMAT_S24_3BE:
case SNDRV_PCM_FORMAT_S20_3LE:
case SNDRV_PCM_FORMAT_S20_3BE:
case SNDRV_PCM_FORMAT_S18_3LE:
case SNDRV_PCM_FORMAT_S18_3BE:
return 1;
case SNDRV_PCM_FORMAT_U8:
case SNDRV_PCM_FORMAT_U16_LE:
......@@ -49,6 +55,12 @@ int snd_pcm_format_signed(snd_pcm_format_t format)
case SNDRV_PCM_FORMAT_U24_BE:
case SNDRV_PCM_FORMAT_U32_LE:
case SNDRV_PCM_FORMAT_U32_BE:
case SNDRV_PCM_FORMAT_U24_3LE:
case SNDRV_PCM_FORMAT_U24_3BE:
case SNDRV_PCM_FORMAT_U20_3LE:
case SNDRV_PCM_FORMAT_U20_3BE:
case SNDRV_PCM_FORMAT_U18_3LE:
case SNDRV_PCM_FORMAT_U18_3BE:
return 0;
default:
return -EINVAL;
......@@ -82,6 +94,12 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format)
case SNDRV_PCM_FORMAT_FLOAT_LE:
case SNDRV_PCM_FORMAT_FLOAT64_LE:
case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
case SNDRV_PCM_FORMAT_S24_3LE:
case SNDRV_PCM_FORMAT_S20_3LE:
case SNDRV_PCM_FORMAT_S18_3LE:
case SNDRV_PCM_FORMAT_U24_3LE:
case SNDRV_PCM_FORMAT_U20_3LE:
case SNDRV_PCM_FORMAT_U18_3LE:
return 1;
case SNDRV_PCM_FORMAT_S16_BE:
case SNDRV_PCM_FORMAT_U16_BE:
......@@ -92,6 +110,12 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format)
case SNDRV_PCM_FORMAT_FLOAT_BE:
case SNDRV_PCM_FORMAT_FLOAT64_BE:
case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
case SNDRV_PCM_FORMAT_S24_3BE:
case SNDRV_PCM_FORMAT_S20_3BE:
case SNDRV_PCM_FORMAT_S18_3BE:
case SNDRV_PCM_FORMAT_U24_3BE:
case SNDRV_PCM_FORMAT_U20_3BE:
case SNDRV_PCM_FORMAT_U18_3BE:
return 0;
default:
return -EINVAL;
......@@ -128,10 +152,24 @@ int snd_pcm_format_width(snd_pcm_format_t format)
case SNDRV_PCM_FORMAT_U16_LE:
case SNDRV_PCM_FORMAT_U16_BE:
return 16;
case SNDRV_PCM_FORMAT_S18_3LE:
case SNDRV_PCM_FORMAT_S18_3BE:
case SNDRV_PCM_FORMAT_U18_3LE:
case SNDRV_PCM_FORMAT_U18_3BE:
return 18;
case SNDRV_PCM_FORMAT_S20_3LE:
case SNDRV_PCM_FORMAT_S20_3BE:
case SNDRV_PCM_FORMAT_U20_3LE:
case SNDRV_PCM_FORMAT_U20_3BE:
return 20;
case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S24_BE:
case SNDRV_PCM_FORMAT_U24_LE:
case SNDRV_PCM_FORMAT_U24_BE:
case SNDRV_PCM_FORMAT_S24_3LE:
case SNDRV_PCM_FORMAT_S24_3BE:
case SNDRV_PCM_FORMAT_U24_3LE:
case SNDRV_PCM_FORMAT_U24_3BE:
return 24;
case SNDRV_PCM_FORMAT_S32_LE:
case SNDRV_PCM_FORMAT_S32_BE:
......@@ -167,6 +205,19 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format)
case SNDRV_PCM_FORMAT_U16_LE:
case SNDRV_PCM_FORMAT_U16_BE:
return 16;
case SNDRV_PCM_FORMAT_S18_3LE:
case SNDRV_PCM_FORMAT_S18_3BE:
case SNDRV_PCM_FORMAT_U18_3LE:
case SNDRV_PCM_FORMAT_U18_3BE:
case SNDRV_PCM_FORMAT_S20_3LE:
case SNDRV_PCM_FORMAT_S20_3BE:
case SNDRV_PCM_FORMAT_U20_3LE:
case SNDRV_PCM_FORMAT_U20_3BE:
case SNDRV_PCM_FORMAT_S24_3LE:
case SNDRV_PCM_FORMAT_S24_3BE:
case SNDRV_PCM_FORMAT_U24_3LE:
case SNDRV_PCM_FORMAT_U24_3BE:
return 24;
case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S24_BE:
case SNDRV_PCM_FORMAT_U24_LE:
......@@ -204,6 +255,19 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
case SNDRV_PCM_FORMAT_U16_LE:
case SNDRV_PCM_FORMAT_U16_BE:
return samples * 2;
case SNDRV_PCM_FORMAT_S18_3LE:
case SNDRV_PCM_FORMAT_S18_3BE:
case SNDRV_PCM_FORMAT_U18_3LE:
case SNDRV_PCM_FORMAT_U18_3BE:
case SNDRV_PCM_FORMAT_S20_3LE:
case SNDRV_PCM_FORMAT_S20_3BE:
case SNDRV_PCM_FORMAT_U20_3LE:
case SNDRV_PCM_FORMAT_U20_3BE:
case SNDRV_PCM_FORMAT_S24_3LE:
case SNDRV_PCM_FORMAT_S24_3BE:
case SNDRV_PCM_FORMAT_U24_3LE:
case SNDRV_PCM_FORMAT_U24_3BE:
return samples * 3;
case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S24_BE:
case SNDRV_PCM_FORMAT_U24_LE:
......@@ -243,6 +307,12 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format)
case SNDRV_PCM_FORMAT_S24_BE:
case SNDRV_PCM_FORMAT_S32_LE:
case SNDRV_PCM_FORMAT_S32_BE:
case SNDRV_PCM_FORMAT_S24_3LE:
case SNDRV_PCM_FORMAT_S24_3BE:
case SNDRV_PCM_FORMAT_S20_3LE:
case SNDRV_PCM_FORMAT_S20_3BE:
case SNDRV_PCM_FORMAT_S18_3LE:
case SNDRV_PCM_FORMAT_S18_3BE:
return 0;
case SNDRV_PCM_FORMAT_U8:
return 0x8080808080808080ULL;
......@@ -273,6 +343,15 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format)
case SNDRV_PCM_FORMAT_U32_BE:
return 0x8000000080000000ULL;
#endif
case SNDRV_PCM_FORMAT_U24_3LE:
case SNDRV_PCM_FORMAT_U24_3BE:
return 0x0000800000800000ULL;
case SNDRV_PCM_FORMAT_U20_3LE:
case SNDRV_PCM_FORMAT_U20_3BE:
return 0x0000080000080000ULL;
case SNDRV_PCM_FORMAT_U18_3LE:
case SNDRV_PCM_FORMAT_U18_3BE:
return 0x0000020000020000ULL;
case SNDRV_PCM_FORMAT_FLOAT_LE:
{
union {
......@@ -379,20 +458,45 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
}
case 16: {
u_int16_t silence = snd_pcm_format_silence_64(format);
while (samples-- > 0)
*((u_int16_t *)data)++ = silence;
if (! silence)
memset(data, 0, samples * 2);
else {
while (samples-- > 0)
*((u_int16_t *)data)++ = silence;
}
break;
}
case 24: {
u_int32_t silence = snd_pcm_format_silence_64(format);
if (! silence)
memset(data, 0, samples * 3);
else {
/* FIXME: rewrite in the more better way.. */
int i;
while (samples-- > 0) {
for (i = 0; i < 3; i++)
*((u_int8_t *)data)++ = silence >> (i * 8);
}
}
}
case 32: {
u_int32_t silence = snd_pcm_format_silence_64(format);
while (samples-- > 0)
*((u_int32_t *)data)++ = silence;
if (! silence)
memset(data, 0, samples * 4);
else {
while (samples-- > 0)
*((u_int32_t *)data)++ = silence;
}
break;
}
case 64: {
u_int64_t silence = snd_pcm_format_silence_64(format);
while (samples-- > 0)
*((u_int64_t *)data)++ = silence;
if (! silence)
memset(data, 0, samples * 8);
else {
while (samples-- > 0)
*((u_int64_t *)data)++ = silence;
}
break;
}
default:
......
......@@ -32,6 +32,36 @@
#include <sound/pcm_params.h>
#include <sound/minors.h>
/*
* Compatibility
*/
struct sndrv_pcm_hw_params_old {
unsigned int flags;
unsigned int masks[SNDRV_PCM_HW_PARAM_SUBFORMAT -
SNDRV_PCM_HW_PARAM_ACCESS + 1];
struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_TICK_TIME -
SNDRV_PCM_HW_PARAM_SAMPLE_BITS + 1];
unsigned int rmask;
unsigned int cmask;
unsigned int info;
unsigned int msbits;
unsigned int rate_num;
unsigned int rate_den;
sndrv_pcm_uframes_t fifo_size;
unsigned char reserved[64];
};
#define SNDRV_PCM_IOCTL_HW_REFINE_OLD _IOWR('A', 0x10, struct sndrv_pcm_hw_params_old)
#define SNDRV_PCM_IOCTL_HW_PARAMS_OLD _IOWR('A', 0x11, struct sndrv_pcm_hw_params_old)
static int snd_pcm_hw_refine_old_user(snd_pcm_substream_t * substream, struct sndrv_pcm_hw_params_old * _oparams);
static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sndrv_pcm_hw_params_old * _oparams);
/*
*
*/
static rwlock_t pcm_link_lock = RW_LOCK_UNLOCKED;
static inline mm_segment_t snd_enter_user(void)
......@@ -52,6 +82,8 @@ static inline void dec_mod_count(struct module *module)
__MOD_DEC_USE_COUNT(module);
}
int snd_pcm_info(snd_pcm_substream_t * substream, snd_pcm_info_t *info)
{
snd_pcm_runtime_t * runtime;
......@@ -121,7 +153,7 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream,
snd_mask_t *m = NULL;
snd_pcm_hw_constraints_t *constrs = &substream->runtime->hw_constraints;
unsigned int rstamps[constrs->rules_num];
unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST + 1];
unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
unsigned int stamp = 2;
int changed, again;
......@@ -187,7 +219,7 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream,
for (k = 0; k < constrs->rules_num; k++)
rstamps[k] = 0;
for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST; k++)
for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
do {
again = 0;
......@@ -211,7 +243,7 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream,
printk("%s = ", snd_pcm_hw_param_names[r->var]);
if (hw_is_mask(r->var)) {
m = hw_param_mask(params, r->var);
printk("%x", *m);
printk("%x", *m->bits);
} else {
i = hw_param_interval(params, r->var);
if (i->empty)
......@@ -228,7 +260,7 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream,
if (r->var >= 0) {
printk(" -> ");
if (hw_is_mask(r->var))
printk("%x", *m);
printk("%x", *m->bits);
else {
if (i->empty)
printk("empty");
......@@ -1369,16 +1401,17 @@ static int snd_pcm_hw_rule_format(snd_pcm_hw_params_t *params,
{
unsigned int k;
snd_interval_t *i = hw_param_interval(params, rule->deps[0]);
unsigned int m = ~0U;
unsigned int *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
snd_mask_t m;
snd_mask_t *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
snd_mask_any(&m);
for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
int bits;
if (!(*mask & (1U << k)))
if (! snd_mask_test(mask, k))
continue;
bits = snd_pcm_format_physical_width(k);
snd_assert(bits > 0, continue);
if ((unsigned)bits < i->min || (unsigned)bits > i->max)
m &= ~(1U << k);
snd_mask_reset(&m, k);
}
return snd_mask_refine(mask, &m);
}
......@@ -1394,7 +1427,7 @@ static int snd_pcm_hw_rule_sample_bits(snd_pcm_hw_params_t *params,
t.openmax = 0;
for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
int bits;
if (!(*hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT) & (1U << k)))
if (! snd_mask_test(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), k))
continue;
bits = snd_pcm_format_physical_width(k);
snd_assert(bits > 0, continue);
......@@ -1582,7 +1615,8 @@ int snd_pcm_hw_constraints_complete(snd_pcm_substream_t *substream)
err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_ACCESS, mask);
snd_assert(err >= 0, return -EINVAL);
err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats);
err = snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats);
//err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats);
snd_assert(err >= 0, return -EINVAL);
err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD);
......@@ -1808,12 +1842,7 @@ int snd_pcm_release(struct inode *inode, struct file *file)
snd_assert(substream != NULL, return -ENXIO);
snd_assert(!atomic_read(&substream->runtime->mmap_count), );
pcm = substream->pcm;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if ((substream->ffile->f_flags & O_NONBLOCK) ||
snd_pcm_playback_drain(substream) == -ERESTARTSYS)
snd_pcm_playback_drop(substream);
} else
snd_pcm_capture_drop(substream);
snd_pcm_capture_drop(substream);
fasync_helper(-1, file, 0, &substream->runtime->fasync);
down(&pcm->open_mutex);
snd_pcm_release_file(pcm_file);
......@@ -2053,6 +2082,10 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_resume(substream);
case SNDRV_PCM_IOCTL_XRUN:
return snd_pcm_xrun(substream);
case SNDRV_PCM_IOCTL_HW_REFINE_OLD:
return snd_pcm_hw_refine_old_user(substream, (struct sndrv_pcm_hw_params_old *) arg);
case SNDRV_PCM_IOCTL_HW_PARAMS_OLD:
return snd_pcm_hw_params_old_user(substream, (struct sndrv_pcm_hw_params_old *) arg);
}
snd_printd("unknown ioctl = 0x%x\n", cmd);
return -ENOTTY;
......@@ -2725,6 +2758,79 @@ static int snd_pcm_fasync(int fd, struct file * file, int on)
return 0;
}
/*
* To be removed helpers to keep binary compatibility
*/
#define __OLD_TO_NEW_MASK(x) ((x&7)|((x&0x07fffff8)<<5))
#define __NEW_TO_OLD_MASK(x) ((x&7)|((x&0xffffff00)>>5))
static void snd_pcm_hw_convert_from_old_params(snd_pcm_hw_params_t *params, struct sndrv_pcm_hw_params_old *oparams)
{
unsigned int i;
memset(params, 0, sizeof(*params));
params->flags = oparams->flags;
for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++)
params->masks[i].bits[0] = oparams->masks[i];
memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals));
params->rmask = __OLD_TO_NEW_MASK(oparams->rmask);
params->cmask = __OLD_TO_NEW_MASK(oparams->cmask);
params->info = oparams->info;
params->msbits = oparams->msbits;
params->rate_num = oparams->rate_num;
params->rate_den = oparams->rate_den;
params->fifo_size = oparams->fifo_size;
}
static void snd_pcm_hw_convert_to_old_params(struct sndrv_pcm_hw_params_old *oparams, snd_pcm_hw_params_t *params)
{
unsigned int i;
memset(oparams, 0, sizeof(*oparams));
oparams->flags = params->flags;
for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++)
oparams->masks[i] = params->masks[i].bits[0];
memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals));
oparams->rmask = __NEW_TO_OLD_MASK(params->rmask);
oparams->cmask = __NEW_TO_OLD_MASK(params->cmask);
oparams->info = params->info;
oparams->msbits = params->msbits;
oparams->rate_num = params->rate_num;
oparams->rate_den = params->rate_den;
oparams->fifo_size = params->fifo_size;
}
static int snd_pcm_hw_refine_old_user(snd_pcm_substream_t * substream, struct sndrv_pcm_hw_params_old * _oparams)
{
snd_pcm_hw_params_t params;
struct sndrv_pcm_hw_params_old oparams;
int err;
if (copy_from_user(&oparams, _oparams, sizeof(oparams)))
return -EFAULT;
snd_pcm_hw_convert_from_old_params(&params, &oparams);
err = snd_pcm_hw_refine(substream, &params);
snd_pcm_hw_convert_to_old_params(&oparams, &params);
if (copy_to_user(_oparams, &oparams, sizeof(oparams)))
return -EFAULT;
return err;
}
static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sndrv_pcm_hw_params_old * _oparams)
{
snd_pcm_hw_params_t params;
struct sndrv_pcm_hw_params_old oparams;
int err;
if (copy_from_user(&oparams, _oparams, sizeof(oparams)))
return -EFAULT;
snd_pcm_hw_convert_from_old_params(&params, &oparams);
err = snd_pcm_hw_params(substream, &params);
snd_pcm_hw_convert_to_old_params(&oparams, &params);
if (copy_to_user(_oparams, &oparams, sizeof(oparams)))
return -EFAULT;
return err;
}
/*
* Register section
*/
......
......@@ -7,8 +7,8 @@ snd-seq-oss-objs := seq_oss.o seq_oss_init.o seq_oss_timer.o seq_oss_ioctl.o \
seq_oss_event.o seq_oss_rw.o seq_oss_synth.o \
seq_oss_midi.o seq_oss_readq.o seq_oss_writeq.o
obj-$(CONFIG_SND_SEQUENCER) += snd-seq-oss.o
ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
include $(TOPDIR)/Rules.make
obj-$(CONFIG_SND_SEQUENCER) += snd-seq-oss.o
endif
include $(TOPDIR)/Rules.make
......@@ -3,8 +3,6 @@
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
#
mod-subdirs := ad1816a ad1848 cs423x es1688 gus opti9xx sb wavefront
snd-als100-objs := als100.o
snd-azt2320-objs := azt2320.o
snd-cmi8330-objs := cmi8330.o
......
......@@ -24,11 +24,13 @@
#include <asm/io.h>
#include <asm/dma.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <sound/core.h>
#include <sound/ad1848.h>
#include <sound/pcm_params.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248");
......
......@@ -35,6 +35,7 @@
#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/cs4231.h>
#include <sound/pcm_params.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips");
......
......@@ -78,6 +78,7 @@
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/mpu401.h>
#include <sound/opl3.h>
#define SNDRV_LEGACY_AUTO_PROBE
......
......@@ -32,6 +32,7 @@
#include <sound/core.h>
#include <sound/control.h>
#include <sound/gus.h>
#include <sound/pcm_params.h>
#include "gus_tables.h"
#define chip_t snd_gus_card_t
......
......@@ -29,6 +29,7 @@
#include <sound/info.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#define SNDRV_GET_ID
#include <sound/initval.h>
......
......@@ -23,8 +23,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* ToDo: - ADAT (32/8)
* - full duplex (32, 32/8, 32Pro)
* ToDo: full duplex (32, 32/8, 32Pro)
*/
#include <sound/driver.h>
......@@ -37,6 +36,7 @@
#include <sound/info.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/asoundef.h>
#define SNDRV_GET_ID
#include <sound/initval.h>
......@@ -327,6 +327,54 @@ static snd_pcm_hardware_t snd_rme32_capture_spdif_info = {
fifo_size: 0,
};
/*
* Digital output capabilites (ADAT)
*/
static snd_pcm_hardware_t snd_rme32_playback_adat_info =
{
info: (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE),
formats: SNDRV_PCM_FMTBIT_S16_LE,
rates: (SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000),
rate_min: 44100,
rate_max: 48000,
channels_min: 8,
channels_max: 8,
buffer_bytes_max: RME32_BUFFER_SIZE,
period_bytes_min: RME32_BLOCK_SIZE,
period_bytes_max: RME32_BLOCK_SIZE,
periods_min: RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
periods_max: RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
fifo_size: 0,
};
/*
* Digital input capabilites (ADAT)
*/
static snd_pcm_hardware_t snd_rme32_capture_adat_info =
{
info: (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE),
formats: SNDRV_PCM_FMTBIT_S16_LE,
rates: (SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000),
rate_min: 44100,
rate_max: 48000,
channels_min: 8,
channels_max: 8,
buffer_bytes_max: RME32_BUFFER_SIZE,
period_bytes_min: RME32_BLOCK_SIZE,
period_bytes_max: RME32_BLOCK_SIZE,
periods_min: RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
periods_max: RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
fifo_size: 0,
};
static void snd_rme32_reset_dac(rme32_t *rme32)
{
writel(rme32->wcreg | RME32_WCR_PD,
......@@ -359,15 +407,20 @@ static int snd_rme32_playback_getrate(rme32_t * rme32)
static int snd_rme32_capture_getrate(rme32_t * rme32, int *is_adat)
{
int n;
*is_adat = 0;
*is_adat = 0;
if (rme32->rcreg & RME32_RCR_LOCK) {
/* ADAT rate */
*is_adat = 1;
}
if (rme32->rcreg & RME32_RCR_ERF) {
return -1;
}
/* S/PDIF rate */
n = ((rme32->rcreg >> RME32_RCR_BITPOS_F0) & 1) +
(((rme32->rcreg >> RME32_RCR_BITPOS_F1) & 1) << 1) +
(((rme32->rcreg >> RME32_RCR_BITPOS_F2) & 1) << 2);
(((rme32->rcreg >> RME32_RCR_BITPOS_F1) & 1) << 1) +
(((rme32->rcreg >> RME32_RCR_BITPOS_F2) & 1) << 2);
if (RME32_PRO_WITH_8414(rme32))
switch (n) { /* supporting the CS8414 */
......@@ -388,7 +441,8 @@ static int snd_rme32_capture_getrate(rme32_t * rme32, int *is_adat)
default:
return -1;
break;
} else
}
else
switch (n) { /* supporting the CS8412 */
case 0:
return -1;
......@@ -816,6 +870,62 @@ static int snd_rme32_capture_spdif_open(snd_pcm_substream_t * substream)
return 0;
}
static int
snd_rme32_playback_adat_open(snd_pcm_substream_t *substream)
{
unsigned long flags;
rme32_t *rme32 = _snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_set_sync(substream);
spin_lock_irqsave(&rme32->lock, flags);
rme32->wcreg |= RME32_WCR_ADAT;
writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
rme32->playback_substream = substream;
rme32->playback_last_appl_ptr = 0;
rme32->playback_ptr = 0;
spin_unlock_irqrestore(&rme32->lock, flags);
runtime->hw = snd_rme32_playback_adat_info;
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
RME32_BUFFER_SIZE, RME32_BUFFER_SIZE);
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
&hw_constraints_period_bytes);
return 0;
}
static int
snd_rme32_capture_adat_open(snd_pcm_substream_t *substream)
{
unsigned long flags;
int isadat;
rme32_t *rme32 = _snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
rme32->rcreg = readl(rme32->iobase + RME32_IO_CONTROL_REGISTER);
if (snd_rme32_capture_getrate(rme32, &isadat) < 0) {
/* no input */
return -EIO;
}
if (!isadat) {
/* S/PDIF input */
return -EBUSY;
}
snd_pcm_set_sync(substream);
spin_lock_irqsave(&rme32->lock, flags);
rme32->capture_substream = substream;
rme32->capture_ptr = 0;
spin_unlock_irqrestore(&rme32->lock, flags);
runtime->hw = snd_rme32_capture_adat_info;
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
RME32_BUFFER_SIZE, RME32_BUFFER_SIZE);
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
&hw_constraints_period_bytes);
return 0;
}
static int snd_rme32_playback_close(snd_pcm_substream_t * substream)
{
......@@ -1004,7 +1114,31 @@ static snd_pcm_uframes_t
snd_rme32_capture_pointer(snd_pcm_substream_t * substream)
{
rme32_t *rme32 = _snd_pcm_substream_chip(substream);
return snd_rme32_capture_ptr(rme32);
snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_uframes_t frameptr;
size_t ptr;
frameptr = snd_rme32_capture_ptr(rme32);
if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
ptr = frameptr << rme32->capture_frlog;
if (ptr > rme32->capture_ptr) {
memcpy_fromio(runtime->dma_area + rme32->capture_ptr,
rme32->iobase + RME32_IO_DATA_BUFFER +
rme32->capture_ptr,
ptr - rme32->capture_ptr);
rme32->capture_ptr += ptr - rme32->capture_ptr;
} else if (ptr < rme32->capture_ptr) {
memcpy_fromio(runtime->dma_area + rme32->capture_ptr,
rme32->iobase + RME32_IO_DATA_BUFFER +
rme32->capture_ptr,
RME32_BUFFER_SIZE - rme32->capture_ptr);
memcpy_fromio(runtime->dma_area,
rme32->iobase + RME32_IO_DATA_BUFFER,
ptr);
rme32->capture_ptr = ptr;
}
}
return frameptr;
}
static snd_pcm_ops_t snd_rme32_playback_spdif_ops = {
......@@ -1032,6 +1166,31 @@ static snd_pcm_ops_t snd_rme32_capture_spdif_ops = {
copy: snd_rme32_capture_copy,
};
static snd_pcm_ops_t snd_rme32_playback_adat_ops = {
open: snd_rme32_playback_adat_open,
close: snd_rme32_playback_close,
ioctl: snd_pcm_lib_ioctl,
hw_params: snd_rme32_playback_hw_params,
hw_free: snd_rme32_playback_hw_free,
prepare: snd_rme32_playback_prepare,
trigger: snd_rme32_playback_trigger,
pointer: snd_rme32_playback_pointer,
copy: snd_rme32_playback_copy,
silence: snd_rme32_playback_silence,
};
static snd_pcm_ops_t snd_rme32_capture_adat_ops = {
open: snd_rme32_capture_adat_open,
close: snd_rme32_capture_close,
ioctl: snd_pcm_lib_ioctl,
hw_params: snd_rme32_capture_hw_params,
hw_free: snd_rme32_capture_hw_free,
prepare: snd_rme32_capture_prepare,
trigger: snd_rme32_capture_trigger,
pointer: snd_rme32_capture_pointer,
copy: snd_rme32_capture_copy,
};
static void snd_rme32_free(void *private_data)
{
rme32_t *rme32 = (rme32_t *) private_data;
......@@ -1063,6 +1222,14 @@ static void snd_rme32_free_spdif_pcm(snd_pcm_t * pcm)
snd_pcm_lib_preallocate_free_for_all(pcm);
}
static void
snd_rme32_free_adat_pcm(snd_pcm_t *pcm)
{
rme32_t *rme32 = (rme32_t *) pcm->private_data;
rme32->adat_pcm = NULL;
snd_pcm_lib_preallocate_free_for_all(pcm);
}
static int __devinit snd_rme32_create(rme32_t * rme32)
{
struct pci_dev *pci = rme32->pci;
......@@ -1117,10 +1284,33 @@ static int __devinit snd_rme32_create(rme32_t * rme32)
GFP_KERNEL);
/* set up ALSA pcm device for ADAT */
if (pci->device == PCI_DEVICE_ID_DIGI32) {
/* ADAT is not available on the base model */
if ((pci->device == PCI_DEVICE_ID_DIGI32) ||
(pci->device == PCI_DEVICE_ID_DIGI32_PRO)) {
/* ADAT is not available on DIGI32 and DIGI32 Pro */
rme32->adat_pcm = NULL;
}
else {
if ((err = snd_pcm_new(rme32->card, "Digi32 ADAT", 1,
1, 1, &rme32->adat_pcm)) < 0)
{
return err;
}
rme32->adat_pcm->private_data = rme32;
rme32->adat_pcm->private_free = snd_rme32_free_adat_pcm;
strcpy(rme32->adat_pcm->name, "Digi32 ADAT");
snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK,
&snd_rme32_playback_adat_ops);
snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE,
&snd_rme32_capture_adat_ops);
rme32->adat_pcm->info_flags = 0;
snd_pcm_lib_preallocate_pages_for_all(rme32->adat_pcm,
RME32_BUFFER_SIZE,
RME32_BUFFER_SIZE,
GFP_KERNEL);
}
rme32->playback_periodsize = 0;
rme32->capture_periodsize = 0;
......@@ -1137,8 +1327,8 @@ static int __devinit snd_rme32_create(rme32_t * rme32)
/* set default values in registers */
rme32->wcreg = RME32_WCR_SEL | /* normal playback */
RME32_WCR_INP_0 | /* input select */
RME32_WCR_MUTE; /* setting muting on */
RME32_WCR_INP_0 | /* input select */
RME32_WCR_MUTE; /* muting on */
writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
......
......@@ -33,6 +33,7 @@
#include <sound/info.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/asoundef.h>
#define SNDRV_GET_ID
#include <sound/initval.h>
......
......@@ -366,9 +366,9 @@ static void snd_via8233_setup_periods(via8233_t *chip, viadev_t *viadev,
switch (runtime->channels) {
case 1: slots = (1<<0); break;
case 2: slots = (1<<0) | (2<<4); break;
case 4: slots = (1<<0) | (2<<4) | (3<<8) | (4<<12);
case 4: slots = (1<<0) | (2<<4) | (3<<8) | (4<<12); break;
case 6: slots = (1<<0) | (2<<4) | (5<<8) | (6<<12) | (3<<16) | (4<<20); break;
default: slots = 0;
default: slots = 0; break;
}
/* STOP index is never reached */
outl(0xff000000 | slots, chip->port + VIA_REG_MULTPLAY_STOP_IDX);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment