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 { ...@@ -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 unsigned long sndrv_pcm_uframes_t;
typedef long sndrv_pcm_sframes_t; typedef long sndrv_pcm_sframes_t;
...@@ -191,7 +191,19 @@ enum sndrv_pcm_format { ...@@ -191,7 +191,19 @@ enum sndrv_pcm_format {
SNDRV_PCM_FORMAT_MPEG, SNDRV_PCM_FORMAT_MPEG,
SNDRV_PCM_FORMAT_GSM, SNDRV_PCM_FORMAT_GSM,
SNDRV_PCM_FORMAT_SPECIAL = 31, 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 #ifdef SNDRV_LITTLE_ENDIAN
SNDRV_PCM_FORMAT_S16 = SNDRV_PCM_FORMAT_S16_LE, SNDRV_PCM_FORMAT_S16 = SNDRV_PCM_FORMAT_S16_LE,
...@@ -284,7 +296,7 @@ enum sndrv_pcm_hw_param { ...@@ -284,7 +296,7 @@ enum sndrv_pcm_hw_param {
SNDRV_PCM_HW_PARAM_SUBFORMAT, /* Subformat */ SNDRV_PCM_HW_PARAM_SUBFORMAT, /* Subformat */
SNDRV_PCM_HW_PARAM_LAST_MASK = SNDRV_PCM_HW_PARAM_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_FIRST_INTERVAL = SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
SNDRV_PCM_HW_PARAM_FRAME_BITS, /* Bits per frame */ SNDRV_PCM_HW_PARAM_FRAME_BITS, /* Bits per frame */
SNDRV_PCM_HW_PARAM_CHANNELS, /* Channels */ SNDRV_PCM_HW_PARAM_CHANNELS, /* Channels */
...@@ -298,8 +310,7 @@ enum sndrv_pcm_hw_param { ...@@ -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_SIZE, /* Size of buffer in frames */
SNDRV_PCM_HW_PARAM_BUFFER_BYTES, /* Size of buffer in bytes */ 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_TICK_TIME, /* Approx tick duration in us */
SNDRV_PCM_HW_PARAM_LAST_INTERVAL = SNDRV_PCM_HW_PARAM_TICK_TIME, SNDRV_PCM_HW_PARAM_LAST_INTERVAL = SNDRV_PCM_HW_PARAM_TICK_TIME
SNDRV_PCM_HW_PARAM_LAST = SNDRV_PCM_HW_PARAM_LAST_INTERVAL,
}; };
#define SNDRV_PCM_HW_PARAMS_RUNTIME (1<<0) #define SNDRV_PCM_HW_PARAMS_RUNTIME (1<<0)
...@@ -312,20 +323,28 @@ struct sndrv_interval { ...@@ -312,20 +323,28 @@ struct sndrv_interval {
empty:1; empty:1;
}; };
#define SNDRV_MASK_MAX 256
struct sndrv_mask {
u_int32_t bits[(SNDRV_MASK_MAX+31)/32];
};
struct sndrv_pcm_hw_params { struct sndrv_pcm_hw_params {
unsigned int flags; unsigned int flags;
unsigned int masks[SNDRV_PCM_HW_PARAM_LAST_MASK - struct sndrv_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
struct sndrv_mask mres[5]; /* reserved masks */
struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
unsigned int rmask; struct sndrv_interval ires[9]; /* reserved intervals */
unsigned int cmask; unsigned int rmask; /* W: requested masks */
unsigned int cmask; /* R: changed masks */
unsigned int info; /* R: Info flags for returned setup */ unsigned int info; /* R: Info flags for returned setup */
unsigned int msbits; /* R: used most significant bits */ unsigned int msbits; /* R: used most significant bits */
unsigned int rate_num; /* R: rate numerator */ unsigned int rate_num; /* R: rate numerator */
unsigned int rate_den; /* R: rate denominator */ unsigned int rate_den; /* R: rate denominator */
sndrv_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */ 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 { enum sndrv_pcm_tstamp {
...@@ -345,7 +364,7 @@ struct sndrv_pcm_sw_params { ...@@ -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_threshold; /* min distance from noise for silence filling */
sndrv_pcm_uframes_t silence_size; /* silence block size */ sndrv_pcm_uframes_t silence_size; /* silence block size */
sndrv_pcm_uframes_t boundary; /* pointers wrap point */ sndrv_pcm_uframes_t boundary; /* pointers wrap point */
unsigned char reserved[64]; unsigned char reserved[64]; /* reserved for future */
}; };
struct sndrv_pcm_channel_info { struct sndrv_pcm_channel_info {
......
...@@ -48,6 +48,7 @@ typedef struct sndrv_pcm_channel_info snd_pcm_channel_info_t; ...@@ -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_status snd_pcm_status_t;
typedef struct sndrv_pcm_mmap_status snd_pcm_mmap_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_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) ((substream)->pcm->private_data)
#define snd_pcm_substream_chip(substream) snd_magic_cast1(chip_t, _snd_pcm_substream_chip(substream), return -ENXIO) #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; ...@@ -67,7 +68,7 @@ typedef struct _snd_pcm_runtime snd_pcm_runtime_t;
typedef struct _snd_pcm_hardware { typedef struct _snd_pcm_hardware {
unsigned int info; /* SNDRV_PCM_INFO_* */ 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 rates; /* SNDRV_PCM_RATE_* */
unsigned int rate_min; /* min rate */ unsigned int rate_min; /* min rate */
unsigned int rate_max; /* max rate */ unsigned int rate_max; /* max rate */
...@@ -148,32 +149,44 @@ typedef struct _snd_pcm_ops { ...@@ -148,32 +149,44 @@ typedef struct _snd_pcm_ops {
SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000)
#define SNDRV_PCM_RATE_8000_192000 (SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\ #define SNDRV_PCM_RATE_8000_192000 (SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\
SNDRV_PCM_RATE_192000) SNDRV_PCM_RATE_192000)
#define SNDRV_PCM_FMTBIT_S8 (1 << SNDRV_PCM_FORMAT_S8) #define SNDRV_PCM_FMTBIT_S8 (1ULL << SNDRV_PCM_FORMAT_S8)
#define SNDRV_PCM_FMTBIT_U8 (1 << SNDRV_PCM_FORMAT_U8) #define SNDRV_PCM_FMTBIT_U8 (1ULL << SNDRV_PCM_FORMAT_U8)
#define SNDRV_PCM_FMTBIT_S16_LE (1 << SNDRV_PCM_FORMAT_S16_LE) #define SNDRV_PCM_FMTBIT_S16_LE (1ULL << SNDRV_PCM_FORMAT_S16_LE)
#define SNDRV_PCM_FMTBIT_S16_BE (1 << SNDRV_PCM_FORMAT_S16_BE) #define SNDRV_PCM_FMTBIT_S16_BE (1ULL << SNDRV_PCM_FORMAT_S16_BE)
#define SNDRV_PCM_FMTBIT_U16_LE (1 << SNDRV_PCM_FORMAT_U16_LE) #define SNDRV_PCM_FMTBIT_U16_LE (1ULL << SNDRV_PCM_FORMAT_U16_LE)
#define SNDRV_PCM_FMTBIT_U16_BE (1 << SNDRV_PCM_FORMAT_U16_BE) #define SNDRV_PCM_FMTBIT_U16_BE (1ULL << SNDRV_PCM_FORMAT_U16_BE)
#define SNDRV_PCM_FMTBIT_S24_LE (1 << SNDRV_PCM_FORMAT_S24_LE) #define SNDRV_PCM_FMTBIT_S24_LE (1ULL << SNDRV_PCM_FORMAT_S24_LE)
#define SNDRV_PCM_FMTBIT_S24_BE (1 << SNDRV_PCM_FORMAT_S24_BE) #define SNDRV_PCM_FMTBIT_S24_BE (1ULL << SNDRV_PCM_FORMAT_S24_BE)
#define SNDRV_PCM_FMTBIT_U24_LE (1 << SNDRV_PCM_FORMAT_U24_LE) #define SNDRV_PCM_FMTBIT_U24_LE (1ULL << SNDRV_PCM_FORMAT_U24_LE)
#define SNDRV_PCM_FMTBIT_U24_BE (1 << SNDRV_PCM_FORMAT_U24_BE) #define SNDRV_PCM_FMTBIT_U24_BE (1ULL << SNDRV_PCM_FORMAT_U24_BE)
#define SNDRV_PCM_FMTBIT_S32_LE (1 << SNDRV_PCM_FORMAT_S32_LE) #define SNDRV_PCM_FMTBIT_S32_LE (1ULL << SNDRV_PCM_FORMAT_S32_LE)
#define SNDRV_PCM_FMTBIT_S32_BE (1 << SNDRV_PCM_FORMAT_S32_BE) #define SNDRV_PCM_FMTBIT_S32_BE (1ULL << SNDRV_PCM_FORMAT_S32_BE)
#define SNDRV_PCM_FMTBIT_U32_LE (1 << SNDRV_PCM_FORMAT_U32_LE) #define SNDRV_PCM_FMTBIT_U32_LE (1ULL << SNDRV_PCM_FORMAT_U32_LE)
#define SNDRV_PCM_FMTBIT_U32_BE (1 << SNDRV_PCM_FORMAT_U32_BE) #define SNDRV_PCM_FMTBIT_U32_BE (1ULL << SNDRV_PCM_FORMAT_U32_BE)
#define SNDRV_PCM_FMTBIT_FLOAT_LE (1 << SNDRV_PCM_FORMAT_FLOAT_LE) #define SNDRV_PCM_FMTBIT_FLOAT_LE (1ULL << SNDRV_PCM_FORMAT_FLOAT_LE)
#define SNDRV_PCM_FMTBIT_FLOAT_BE (1 << SNDRV_PCM_FORMAT_FLOAT_BE) #define SNDRV_PCM_FMTBIT_FLOAT_BE (1ULL << SNDRV_PCM_FORMAT_FLOAT_BE)
#define SNDRV_PCM_FMTBIT_FLOAT64_LE (1 << SNDRV_PCM_FORMAT_FLOAT64_LE) #define SNDRV_PCM_FMTBIT_FLOAT64_LE (1ULL << SNDRV_PCM_FORMAT_FLOAT64_LE)
#define SNDRV_PCM_FMTBIT_FLOAT64_BE (1 << SNDRV_PCM_FORMAT_FLOAT64_BE) #define SNDRV_PCM_FMTBIT_FLOAT64_BE (1ULL << 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_LE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE)
#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE (1 << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE) #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE)
#define SNDRV_PCM_FMTBIT_MU_LAW (1 << SNDRV_PCM_FORMAT_MU_LAW) #define SNDRV_PCM_FMTBIT_MU_LAW (1ULL << SNDRV_PCM_FORMAT_MU_LAW)
#define SNDRV_PCM_FMTBIT_A_LAW (1 << SNDRV_PCM_FORMAT_A_LAW) #define SNDRV_PCM_FMTBIT_A_LAW (1ULL << SNDRV_PCM_FORMAT_A_LAW)
#define SNDRV_PCM_FMTBIT_IMA_ADPCM (1 << SNDRV_PCM_FORMAT_IMA_ADPCM) #define SNDRV_PCM_FMTBIT_IMA_ADPCM (1ULL << SNDRV_PCM_FORMAT_IMA_ADPCM)
#define SNDRV_PCM_FMTBIT_MPEG (1 << SNDRV_PCM_FORMAT_MPEG) #define SNDRV_PCM_FMTBIT_MPEG (1ULL << SNDRV_PCM_FORMAT_MPEG)
#define SNDRV_PCM_FMTBIT_GSM (1 << SNDRV_PCM_FORMAT_GSM) #define SNDRV_PCM_FMTBIT_GSM (1ULL << SNDRV_PCM_FORMAT_GSM)
#define SNDRV_PCM_FMTBIT_SPECIAL (1 << SNDRV_PCM_FORMAT_SPECIAL) #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 #ifdef SNDRV_LITTLE_ENDIAN
#define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE #define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE
...@@ -217,8 +230,8 @@ struct _snd_pcm_hw_rule { ...@@ -217,8 +230,8 @@ struct _snd_pcm_hw_rule {
}; };
typedef struct _snd_pcm_hw_constraints { typedef struct _snd_pcm_hw_constraints {
unsigned int masks[SNDRV_PCM_HW_PARAM_LAST_MASK - snd_mask_t masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
snd_interval_t intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - snd_interval_t intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
unsigned int rules_num; unsigned int rules_num;
...@@ -226,8 +239,8 @@ typedef struct _snd_pcm_hw_constraints { ...@@ -226,8 +239,8 @@ typedef struct _snd_pcm_hw_constraints {
snd_pcm_hw_rule_t *rules; snd_pcm_hw_rule_t *rules;
} snd_pcm_hw_constraints_t; } snd_pcm_hw_constraints_t;
static inline unsigned int *constrs_mask(snd_pcm_hw_constraints_t *constrs, static inline snd_mask_t *constrs_mask(snd_pcm_hw_constraints_t *constrs,
snd_pcm_hw_param_t var) snd_pcm_hw_param_t var)
{ {
return &constrs->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK]; return &constrs->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK];
} }
...@@ -648,13 +661,10 @@ static inline int hw_is_interval(int var) ...@@ -648,13 +661,10 @@ static inline int hw_is_interval(int var)
var <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; 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, static inline snd_mask_t *hw_param_mask(snd_pcm_hw_params_t *params,
snd_pcm_hw_param_t var) 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, 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_ ...@@ -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); 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_access(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS))
#define params_format(p) (ffs(*hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT)) - 1) #define params_format(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT))
#define params_subformat(p) (ffs(*hw_param_mask((p), SNDRV_PCM_HW_PARAM_SUBFORMAT)) - 1) #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_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_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 #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); ...@@ -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_constraints_complete(snd_pcm_substream_t *substream);
int snd_pcm_hw_constraint_mask(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var, 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, int snd_pcm_hw_constraint_minmax(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
unsigned int min, unsigned int max); unsigned int min, unsigned int max);
int snd_pcm_hw_constraint_integer(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var); 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, ...@@ -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); snd_pcm_hw_param_t var, unsigned int val, int dir);
/* To share the same code we have alsa-lib */ /* To share the same code we have alsa-lib */
#define snd_mask_bits(mask) (*(mask))
#define INLINE static inline #define INLINE static inline
#define assert(a) (void)(a) #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) INLINE unsigned int ld2(u_int32_t v)
{ {
unsigned r = 0; unsigned r = 0;
...@@ -72,91 +76,119 @@ INLINE size_t snd_mask_sizeof(void) ...@@ -72,91 +76,119 @@ INLINE size_t snd_mask_sizeof(void)
INLINE void snd_mask_none(snd_mask_t *mask) 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) INLINE void snd_mask_any(snd_mask_t *mask)
{ {
snd_mask_bits(mask) = ~0U; memset(mask, 0xff, SNDRV_MASK_SIZE * sizeof(u_int32_t));
}
INLINE void snd_mask_load(snd_mask_t *mask, unsigned int msk)
{
snd_mask_bits(mask) = msk;
} }
INLINE int snd_mask_empty(const snd_mask_t *mask) 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) INLINE unsigned int snd_mask_min(const snd_mask_t *mask)
{ {
int i;
assert(!snd_mask_empty(mask)); 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) INLINE unsigned int snd_mask_max(const snd_mask_t *mask)
{ {
int i;
assert(!snd_mask_empty(mask)); 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) INLINE void snd_mask_set(snd_mask_t *mask, unsigned int val)
{ {
assert(val <= SND_MASK_MAX); assert(val <= SNDRV_MASK_BITS);
snd_mask_bits(mask) |= (1U << val); mask->bits[MASK_OFS(val)] |= MASK_BIT(val);
} }
INLINE void snd_mask_reset(snd_mask_t *mask, unsigned int val) INLINE void snd_mask_reset(snd_mask_t *mask, unsigned int val)
{ {
assert(val <= SND_MASK_MAX); assert(val <= SNDRV_MASK_BITS);
snd_mask_bits(mask) &= ~(1U << val); mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val);
} }
INLINE void snd_mask_set_range(snd_mask_t *mask, unsigned int from, unsigned int to) INLINE void snd_mask_set_range(snd_mask_t *mask, unsigned int from, unsigned int to)
{ {
assert(to <= SND_MASK_MAX && from <= to); int i;
snd_mask_bits(mask) |= ((1U << (from - to + 1)) - 1) << from; 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) INLINE void snd_mask_reset_range(snd_mask_t *mask, unsigned int from, unsigned int to)
{ {
assert(to <= SND_MASK_MAX && from <= to); int i;
snd_mask_bits(mask) &= ~(((1U << (from - to + 1)) - 1) << from); 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) INLINE void snd_mask_leave(snd_mask_t *mask, unsigned int val)
{ {
assert(val <= SND_MASK_MAX); unsigned int v;
snd_mask_bits(mask) &= 1U << val; 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) 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) 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) 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) INLINE int snd_mask_test(const snd_mask_t *mask, unsigned int val)
{ {
assert(val <= SND_MASK_MAX); assert(val <= SNDRV_MASK_BITS);
return snd_mask_bits(mask) & (1U << val); return mask->bits[MASK_OFS(val)] & MASK_BIT(val);
} }
INLINE int snd_mask_single(const snd_mask_t *mask) INLINE int snd_mask_single(const snd_mask_t *mask)
{ {
int i, c = 0;
assert(!snd_mask_empty(mask)); 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) 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) ...@@ -204,7 +236,7 @@ INLINE int snd_mask_refine_max(snd_mask_t *mask, unsigned int val)
assert(!snd_mask_empty(mask)); assert(!snd_mask_empty(mask));
if (snd_mask_max(mask) <= val) if (snd_mask_max(mask) <= val)
return 0; 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)) if (snd_mask_empty(mask))
return -EINVAL; return -EINVAL;
return 1; return 1;
......
/* include/version.h. Generated automatically by configure. */ /* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0rc2" #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 ...@@ -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_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_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_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_delay, pcm_sframes_str, SNDRV_PCM_IOCTL_DELAY);
DEFINE_ALSA_IOCTL_ENTRY(pcm_channel_info, pcm_channel_info, SNDRV_PCM_IOCTL_CHANNEL_INFO); DEFINE_ALSA_IOCTL_ENTRY(pcm_channel_info, pcm_channel_info, SNDRV_PCM_IOCTL_CHANNEL_INFO);
...@@ -335,6 +417,9 @@ enum { ...@@ -335,6 +417,9 @@ enum {
SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct sndrv_xferi32), 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_WRITEN_FRAMES32 = _IOW('A', 0x52, struct sndrv_xfern32),
SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, 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[] = { struct ioctl32_mapper pcm_mappers[] = {
...@@ -342,6 +427,8 @@ struct ioctl32_mapper pcm_mappers[] = { ...@@ -342,6 +427,8 @@ struct ioctl32_mapper pcm_mappers[] = {
{ SNDRV_PCM_IOCTL_INFO, NULL }, { SNDRV_PCM_IOCTL_INFO, NULL },
{ SNDRV_PCM_IOCTL_HW_REFINE32, AP(pcm_hw_refine) }, { SNDRV_PCM_IOCTL_HW_REFINE32, AP(pcm_hw_refine) },
{ SNDRV_PCM_IOCTL_HW_PARAMS32, AP(pcm_hw_params) }, { 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_HW_FREE, NULL },
{ SNDRV_PCM_IOCTL_SW_PARAMS32, AP(pcm_sw_params) }, { SNDRV_PCM_IOCTL_SW_PARAMS32, AP(pcm_sw_params) },
{ SNDRV_PCM_IOCTL_STATUS32, AP(pcm_status) }, { SNDRV_PCM_IOCTL_STATUS32, AP(pcm_status) },
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/time.h> #include <linux/time.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h>
#include "pcm_plugin.h" #include "pcm_plugin.h"
#define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1) #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) ...@@ -267,8 +267,8 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream)
int err; int err;
int direct; int direct;
int format, sformat, n; int format, sformat, n;
unsigned int sformat_mask; snd_mask_t sformat_mask;
unsigned int mask; snd_mask_t mask;
if (atomic_read(&runtime->mmap_count)) { if (atomic_read(&runtime->mmap_count)) {
direct = 1; direct = 1;
...@@ -280,12 +280,13 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) ...@@ -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_params_any(&sparams);
_snd_pcm_hw_param_setinteger(&sparams, SNDRV_PCM_HW_PARAM_PERIODS); _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_pcm_hw_param_min(&sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0);
snd_mask_none(&mask);
if (atomic_read(&runtime->mmap_count)) if (atomic_read(&runtime->mmap_count))
mask = 1 << SNDRV_PCM_ACCESS_MMAP_INTERLEAVED; snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
else { else {
mask = 1 << SNDRV_PCM_ACCESS_RW_INTERLEAVED; snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED);
if (!direct) 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); err = snd_pcm_hw_param_mask(substream, &sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask);
if (err < 0) { if (err < 0) {
...@@ -301,11 +302,11 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) ...@@ -301,11 +302,11 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream)
if (direct) if (direct)
sformat = format; sformat = format;
else 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++) { 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) snd_pcm_oss_format_to(sformat) >= 0)
break; break;
} }
...@@ -935,7 +936,7 @@ static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file) ...@@ -935,7 +936,7 @@ static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file)
int direct; int direct;
snd_pcm_hw_params_t params; snd_pcm_hw_params_t params;
unsigned int formats = 0; unsigned int formats = 0;
unsigned int format_mask; snd_mask_t format_mask;
int fmt; int fmt;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
return err; return err;
...@@ -955,7 +956,7 @@ static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file) ...@@ -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); snd_assert(err >= 0, return err);
format_mask = *hw_param_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT); format_mask = *hw_param_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT);
for (fmt = 0; fmt < 32; ++fmt) { 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); int f = snd_pcm_oss_format_to(fmt);
if (f >= 0) if (f >= 0)
formats |= f; formats |= f;
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h>
#include "pcm_plugin.h" #include "pcm_plugin.h"
#define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first) #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_ ...@@ -280,20 +281,23 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(snd_pcm_plug_t *plug, snd_pcm_uframes_
return frames; 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_LE | SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |
SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE |
SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |
SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE); 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) if (formats.bits[0] & (u32)linfmts)
formats |= linfmts; formats.bits[0] |= (u32)linfmts;
return formats; if (formats.bits[1] & (u32)(linfmts >> 32))
formats.bits[1] |= (u32)(linfmts >> 32);
return snd_mask_test(&formats, format);
} }
static int preferred_formats[] = { static int preferred_formats[] = {
...@@ -313,11 +317,11 @@ static int preferred_formats[] = { ...@@ -313,11 +317,11 @@ static int preferred_formats[] = {
SNDRV_PCM_FORMAT_U8 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; return format;
if ((snd_pcm_plug_formats(format_mask) & (1 << format)) == 0) if (! snd_pcm_plug_formats(format_mask, format))
return -EINVAL; return -EINVAL;
if (snd_pcm_format_linear(format)) { if (snd_pcm_format_linear(format)) {
int width = snd_pcm_format_width(format); int width = snd_pcm_format_width(format);
...@@ -333,7 +337,7 @@ int snd_pcm_plug_slave_format(int format, unsigned int format_mask) ...@@ -333,7 +337,7 @@ int snd_pcm_plug_slave_format(int format, unsigned int format_mask)
for (sgn = 0; sgn < 2; ++sgn) { for (sgn = 0; sgn < 2; ++sgn) {
format1 = snd_pcm_build_linear_format(width1, unsignd1, big1); format1 = snd_pcm_build_linear_format(width1, unsignd1, big1);
if (format1 >= 0 && if (format1 >= 0 &&
format_mask & (1 << format1)) snd_mask_test(format_mask, format1))
goto _found; goto _found;
unsignd1 = !unsignd1; unsignd1 = !unsignd1;
} }
...@@ -354,7 +358,7 @@ int snd_pcm_plug_slave_format(int format, unsigned int format_mask) ...@@ -354,7 +358,7 @@ int snd_pcm_plug_slave_format(int format, unsigned int format_mask)
case SNDRV_PCM_FORMAT_MU_LAW: case SNDRV_PCM_FORMAT_MU_LAW:
for (i = 0; i < sizeof(preferred_formats) / sizeof(preferred_formats[0]); ++i) { for (i = 0; i < sizeof(preferred_formats) / sizeof(preferred_formats[0]); ++i) {
int format1 = preferred_formats[i]; int format1 = preferred_formats[i];
if (format_mask & (1 << format1)) if (snd_mask_test(format_mask, format1))
return format1; return format1;
} }
default: default:
......
...@@ -197,13 +197,11 @@ int snd_pcm_plugin_build_copy(snd_pcm_plug_t *handle, ...@@ -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_format_t *dst_format,
snd_pcm_plugin_t **r_plugin); 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, int snd_pcm_plug_format_plugins(snd_pcm_plug_t *substream,
snd_pcm_hw_params_t *params, snd_pcm_hw_params_t *params,
snd_pcm_hw_params_t *slave_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); int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin);
......
...@@ -184,6 +184,18 @@ char *snd_pcm_format_names[] = { ...@@ -184,6 +184,18 @@ char *snd_pcm_format_names[] = {
FORMAT(MPEG), FORMAT(MPEG),
FORMAT(GSM), FORMAT(GSM),
FORMAT(SPECIAL), 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[] = { char *snd_pcm_subformat_names[] = {
......
...@@ -810,12 +810,26 @@ int snd_pcm_hw_rule_add(snd_pcm_runtime_t *runtime, unsigned int cond, ...@@ -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, 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; snd_pcm_hw_constraints_t *constrs = &runtime->hw_constraints;
unsigned int *maskp = constrs_mask(constrs, var); snd_mask_t *maskp = constrs_mask(constrs, var);
*maskp &= mask; *maskp->bits &= mask;
if (*maskp == 0) 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 -EINVAL;
return 0; return 0;
} }
...@@ -982,7 +996,9 @@ void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params) ...@@ -982,7 +996,9 @@ void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
{ {
unsigned int k; unsigned int k;
memset(params, 0, sizeof(*params)); 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); _snd_pcm_hw_param_any(params, k);
params->info = ~0U; params->info = ~0U;
} }
......
...@@ -41,6 +41,12 @@ int snd_pcm_format_signed(snd_pcm_format_t format) ...@@ -41,6 +41,12 @@ int snd_pcm_format_signed(snd_pcm_format_t format)
case SNDRV_PCM_FORMAT_S24_BE: case SNDRV_PCM_FORMAT_S24_BE:
case SNDRV_PCM_FORMAT_S32_LE: case SNDRV_PCM_FORMAT_S32_LE:
case SNDRV_PCM_FORMAT_S32_BE: 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; return 1;
case SNDRV_PCM_FORMAT_U8: case SNDRV_PCM_FORMAT_U8:
case SNDRV_PCM_FORMAT_U16_LE: case SNDRV_PCM_FORMAT_U16_LE:
...@@ -49,6 +55,12 @@ int snd_pcm_format_signed(snd_pcm_format_t format) ...@@ -49,6 +55,12 @@ int snd_pcm_format_signed(snd_pcm_format_t format)
case SNDRV_PCM_FORMAT_U24_BE: case SNDRV_PCM_FORMAT_U24_BE:
case SNDRV_PCM_FORMAT_U32_LE: case SNDRV_PCM_FORMAT_U32_LE:
case SNDRV_PCM_FORMAT_U32_BE: 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; return 0;
default: default:
return -EINVAL; return -EINVAL;
...@@ -82,6 +94,12 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format) ...@@ -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_FLOAT_LE:
case SNDRV_PCM_FORMAT_FLOAT64_LE: case SNDRV_PCM_FORMAT_FLOAT64_LE:
case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_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; return 1;
case SNDRV_PCM_FORMAT_S16_BE: case SNDRV_PCM_FORMAT_S16_BE:
case SNDRV_PCM_FORMAT_U16_BE: case SNDRV_PCM_FORMAT_U16_BE:
...@@ -92,6 +110,12 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format) ...@@ -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_FLOAT_BE:
case SNDRV_PCM_FORMAT_FLOAT64_BE: case SNDRV_PCM_FORMAT_FLOAT64_BE:
case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_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; return 0;
default: default:
return -EINVAL; return -EINVAL;
...@@ -128,10 +152,24 @@ int snd_pcm_format_width(snd_pcm_format_t format) ...@@ -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_LE:
case SNDRV_PCM_FORMAT_U16_BE: case SNDRV_PCM_FORMAT_U16_BE:
return 16; 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_LE:
case SNDRV_PCM_FORMAT_S24_BE: case SNDRV_PCM_FORMAT_S24_BE:
case SNDRV_PCM_FORMAT_U24_LE: case SNDRV_PCM_FORMAT_U24_LE:
case SNDRV_PCM_FORMAT_U24_BE: 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; return 24;
case SNDRV_PCM_FORMAT_S32_LE: case SNDRV_PCM_FORMAT_S32_LE:
case SNDRV_PCM_FORMAT_S32_BE: case SNDRV_PCM_FORMAT_S32_BE:
...@@ -167,6 +205,19 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format) ...@@ -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_LE:
case SNDRV_PCM_FORMAT_U16_BE: case SNDRV_PCM_FORMAT_U16_BE:
return 16; 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_LE:
case SNDRV_PCM_FORMAT_S24_BE: case SNDRV_PCM_FORMAT_S24_BE:
case SNDRV_PCM_FORMAT_U24_LE: case SNDRV_PCM_FORMAT_U24_LE:
...@@ -204,6 +255,19 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples) ...@@ -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_LE:
case SNDRV_PCM_FORMAT_U16_BE: case SNDRV_PCM_FORMAT_U16_BE:
return samples * 2; 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_LE:
case SNDRV_PCM_FORMAT_S24_BE: case SNDRV_PCM_FORMAT_S24_BE:
case SNDRV_PCM_FORMAT_U24_LE: case SNDRV_PCM_FORMAT_U24_LE:
...@@ -243,6 +307,12 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format) ...@@ -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_S24_BE:
case SNDRV_PCM_FORMAT_S32_LE: case SNDRV_PCM_FORMAT_S32_LE:
case SNDRV_PCM_FORMAT_S32_BE: 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; return 0;
case SNDRV_PCM_FORMAT_U8: case SNDRV_PCM_FORMAT_U8:
return 0x8080808080808080ULL; return 0x8080808080808080ULL;
...@@ -273,6 +343,15 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format) ...@@ -273,6 +343,15 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format)
case SNDRV_PCM_FORMAT_U32_BE: case SNDRV_PCM_FORMAT_U32_BE:
return 0x8000000080000000ULL; return 0x8000000080000000ULL;
#endif #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: case SNDRV_PCM_FORMAT_FLOAT_LE:
{ {
union { union {
...@@ -379,20 +458,45 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int ...@@ -379,20 +458,45 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
} }
case 16: { case 16: {
u_int16_t silence = snd_pcm_format_silence_64(format); u_int16_t silence = snd_pcm_format_silence_64(format);
while (samples-- > 0) if (! silence)
*((u_int16_t *)data)++ = silence; memset(data, 0, samples * 2);
else {
while (samples-- > 0)
*((u_int16_t *)data)++ = silence;
}
break; 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: { case 32: {
u_int32_t silence = snd_pcm_format_silence_64(format); u_int32_t silence = snd_pcm_format_silence_64(format);
while (samples-- > 0) if (! silence)
*((u_int32_t *)data)++ = silence; memset(data, 0, samples * 4);
else {
while (samples-- > 0)
*((u_int32_t *)data)++ = silence;
}
break; break;
} }
case 64: { case 64: {
u_int64_t silence = snd_pcm_format_silence_64(format); u_int64_t silence = snd_pcm_format_silence_64(format);
while (samples-- > 0) if (! silence)
*((u_int64_t *)data)++ = silence; memset(data, 0, samples * 8);
else {
while (samples-- > 0)
*((u_int64_t *)data)++ = silence;
}
break; break;
} }
default: default:
......
...@@ -32,6 +32,36 @@ ...@@ -32,6 +32,36 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/minors.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 rwlock_t pcm_link_lock = RW_LOCK_UNLOCKED;
static inline mm_segment_t snd_enter_user(void) static inline mm_segment_t snd_enter_user(void)
...@@ -52,6 +82,8 @@ static inline void dec_mod_count(struct module *module) ...@@ -52,6 +82,8 @@ static inline void dec_mod_count(struct module *module)
__MOD_DEC_USE_COUNT(module); __MOD_DEC_USE_COUNT(module);
} }
int snd_pcm_info(snd_pcm_substream_t * substream, snd_pcm_info_t *info) int snd_pcm_info(snd_pcm_substream_t * substream, snd_pcm_info_t *info)
{ {
snd_pcm_runtime_t * runtime; snd_pcm_runtime_t * runtime;
...@@ -121,7 +153,7 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream, ...@@ -121,7 +153,7 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream,
snd_mask_t *m = NULL; snd_mask_t *m = NULL;
snd_pcm_hw_constraints_t *constrs = &substream->runtime->hw_constraints; snd_pcm_hw_constraints_t *constrs = &substream->runtime->hw_constraints;
unsigned int rstamps[constrs->rules_num]; 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; unsigned int stamp = 2;
int changed, again; int changed, again;
...@@ -187,7 +219,7 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream, ...@@ -187,7 +219,7 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream,
for (k = 0; k < constrs->rules_num; k++) for (k = 0; k < constrs->rules_num; k++)
rstamps[k] = 0; 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; vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
do { do {
again = 0; again = 0;
...@@ -211,7 +243,7 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream, ...@@ -211,7 +243,7 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream,
printk("%s = ", snd_pcm_hw_param_names[r->var]); printk("%s = ", snd_pcm_hw_param_names[r->var]);
if (hw_is_mask(r->var)) { if (hw_is_mask(r->var)) {
m = hw_param_mask(params, r->var); m = hw_param_mask(params, r->var);
printk("%x", *m); printk("%x", *m->bits);
} else { } else {
i = hw_param_interval(params, r->var); i = hw_param_interval(params, r->var);
if (i->empty) if (i->empty)
...@@ -228,7 +260,7 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream, ...@@ -228,7 +260,7 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream,
if (r->var >= 0) { if (r->var >= 0) {
printk(" -> "); printk(" -> ");
if (hw_is_mask(r->var)) if (hw_is_mask(r->var))
printk("%x", *m); printk("%x", *m->bits);
else { else {
if (i->empty) if (i->empty)
printk("empty"); printk("empty");
...@@ -1369,16 +1401,17 @@ static int snd_pcm_hw_rule_format(snd_pcm_hw_params_t *params, ...@@ -1369,16 +1401,17 @@ static int snd_pcm_hw_rule_format(snd_pcm_hw_params_t *params,
{ {
unsigned int k; unsigned int k;
snd_interval_t *i = hw_param_interval(params, rule->deps[0]); snd_interval_t *i = hw_param_interval(params, rule->deps[0]);
unsigned int m = ~0U; snd_mask_t m;
unsigned int *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 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) { for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
int bits; int bits;
if (!(*mask & (1U << k))) if (! snd_mask_test(mask, k))
continue; continue;
bits = snd_pcm_format_physical_width(k); bits = snd_pcm_format_physical_width(k);
snd_assert(bits > 0, continue); snd_assert(bits > 0, continue);
if ((unsigned)bits < i->min || (unsigned)bits > i->max) if ((unsigned)bits < i->min || (unsigned)bits > i->max)
m &= ~(1U << k); snd_mask_reset(&m, k);
} }
return snd_mask_refine(mask, &m); return snd_mask_refine(mask, &m);
} }
...@@ -1394,7 +1427,7 @@ static int snd_pcm_hw_rule_sample_bits(snd_pcm_hw_params_t *params, ...@@ -1394,7 +1427,7 @@ static int snd_pcm_hw_rule_sample_bits(snd_pcm_hw_params_t *params,
t.openmax = 0; t.openmax = 0;
for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) { for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
int bits; 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; continue;
bits = snd_pcm_format_physical_width(k); bits = snd_pcm_format_physical_width(k);
snd_assert(bits > 0, continue); snd_assert(bits > 0, continue);
...@@ -1582,7 +1615,8 @@ int snd_pcm_hw_constraints_complete(snd_pcm_substream_t *substream) ...@@ -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); err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_ACCESS, mask);
snd_assert(err >= 0, return -EINVAL); 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); snd_assert(err >= 0, return -EINVAL);
err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD); 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) ...@@ -1808,12 +1842,7 @@ int snd_pcm_release(struct inode *inode, struct file *file)
snd_assert(substream != NULL, return -ENXIO); snd_assert(substream != NULL, return -ENXIO);
snd_assert(!atomic_read(&substream->runtime->mmap_count), ); snd_assert(!atomic_read(&substream->runtime->mmap_count), );
pcm = substream->pcm; pcm = substream->pcm;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { snd_pcm_capture_drop(substream);
if ((substream->ffile->f_flags & O_NONBLOCK) ||
snd_pcm_playback_drain(substream) == -ERESTARTSYS)
snd_pcm_playback_drop(substream);
} else
snd_pcm_capture_drop(substream);
fasync_helper(-1, file, 0, &substream->runtime->fasync); fasync_helper(-1, file, 0, &substream->runtime->fasync);
down(&pcm->open_mutex); down(&pcm->open_mutex);
snd_pcm_release_file(pcm_file); snd_pcm_release_file(pcm_file);
...@@ -2053,6 +2082,10 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream, ...@@ -2053,6 +2082,10 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_resume(substream); return snd_pcm_resume(substream);
case SNDRV_PCM_IOCTL_XRUN: case SNDRV_PCM_IOCTL_XRUN:
return snd_pcm_xrun(substream); 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); snd_printd("unknown ioctl = 0x%x\n", cmd);
return -ENOTTY; return -ENOTTY;
...@@ -2725,6 +2758,79 @@ static int snd_pcm_fasync(int fd, struct file * file, int on) ...@@ -2725,6 +2758,79 @@ static int snd_pcm_fasync(int fd, struct file * file, int on)
return 0; 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 * 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 \ ...@@ -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_event.o seq_oss_rw.o seq_oss_synth.o \
seq_oss_midi.o seq_oss_readq.o seq_oss_writeq.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) ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
include $(TOPDIR)/Rules.make obj-$(CONFIG_SND_SEQUENCER) += snd-seq-oss.o
endif endif
include $(TOPDIR)/Rules.make
...@@ -3,8 +3,6 @@ ...@@ -3,8 +3,6 @@
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> # 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-als100-objs := als100.o
snd-azt2320-objs := azt2320.o snd-azt2320-objs := azt2320.o
snd-cmi8330-objs := cmi8330.o snd-cmi8330-objs := cmi8330.o
......
...@@ -24,11 +24,13 @@ ...@@ -24,11 +24,13 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/init.h> #include <linux/init.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/ad1848.h> #include <sound/ad1848.h>
#include <sound/pcm_params.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248"); MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248");
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/cs4231.h> #include <sound/cs4231.h>
#include <sound/pcm_params.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips"); MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips");
......
...@@ -78,6 +78,7 @@ ...@@ -78,6 +78,7 @@
#include <sound/core.h> #include <sound/core.h>
#include <sound/control.h> #include <sound/control.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/mpu401.h> #include <sound/mpu401.h>
#include <sound/opl3.h> #include <sound/opl3.h>
#define SNDRV_LEGACY_AUTO_PROBE #define SNDRV_LEGACY_AUTO_PROBE
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <sound/core.h> #include <sound/core.h>
#include <sound/control.h> #include <sound/control.h>
#include <sound/gus.h> #include <sound/gus.h>
#include <sound/pcm_params.h>
#include "gus_tables.h" #include "gus_tables.h"
#define chip_t snd_gus_card_t #define chip_t snd_gus_card_t
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <sound/info.h> #include <sound/info.h>
#include <sound/control.h> #include <sound/control.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h>
#define SNDRV_GET_ID #define SNDRV_GET_ID
#include <sound/initval.h> #include <sound/initval.h>
......
...@@ -23,8 +23,7 @@ ...@@ -23,8 +23,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* *
* ToDo: - ADAT (32/8) * ToDo: full duplex (32, 32/8, 32Pro)
* - full duplex (32, 32/8, 32Pro)
*/ */
#include <sound/driver.h> #include <sound/driver.h>
...@@ -37,6 +36,7 @@ ...@@ -37,6 +36,7 @@
#include <sound/info.h> #include <sound/info.h>
#include <sound/control.h> #include <sound/control.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/asoundef.h> #include <sound/asoundef.h>
#define SNDRV_GET_ID #define SNDRV_GET_ID
#include <sound/initval.h> #include <sound/initval.h>
...@@ -327,6 +327,54 @@ static snd_pcm_hardware_t snd_rme32_capture_spdif_info = { ...@@ -327,6 +327,54 @@ static snd_pcm_hardware_t snd_rme32_capture_spdif_info = {
fifo_size: 0, 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) static void snd_rme32_reset_dac(rme32_t *rme32)
{ {
writel(rme32->wcreg | RME32_WCR_PD, writel(rme32->wcreg | RME32_WCR_PD,
...@@ -359,15 +407,20 @@ static int snd_rme32_playback_getrate(rme32_t * rme32) ...@@ -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) static int snd_rme32_capture_getrate(rme32_t * rme32, int *is_adat)
{ {
int n; 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) { if (rme32->rcreg & RME32_RCR_ERF) {
return -1; return -1;
} }
/* S/PDIF rate */
n = ((rme32->rcreg >> RME32_RCR_BITPOS_F0) & 1) + n = ((rme32->rcreg >> RME32_RCR_BITPOS_F0) & 1) +
(((rme32->rcreg >> RME32_RCR_BITPOS_F1) & 1) << 1) + (((rme32->rcreg >> RME32_RCR_BITPOS_F1) & 1) << 1) +
(((rme32->rcreg >> RME32_RCR_BITPOS_F2) & 1) << 2); (((rme32->rcreg >> RME32_RCR_BITPOS_F2) & 1) << 2);
if (RME32_PRO_WITH_8414(rme32)) if (RME32_PRO_WITH_8414(rme32))
switch (n) { /* supporting the CS8414 */ switch (n) { /* supporting the CS8414 */
...@@ -388,7 +441,8 @@ static int snd_rme32_capture_getrate(rme32_t * rme32, int *is_adat) ...@@ -388,7 +441,8 @@ static int snd_rme32_capture_getrate(rme32_t * rme32, int *is_adat)
default: default:
return -1; return -1;
break; break;
} else }
else
switch (n) { /* supporting the CS8412 */ switch (n) { /* supporting the CS8412 */
case 0: case 0:
return -1; return -1;
...@@ -816,6 +870,62 @@ static int snd_rme32_capture_spdif_open(snd_pcm_substream_t * substream) ...@@ -816,6 +870,62 @@ static int snd_rme32_capture_spdif_open(snd_pcm_substream_t * substream)
return 0; 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) static int snd_rme32_playback_close(snd_pcm_substream_t * substream)
{ {
...@@ -1004,7 +1114,31 @@ static snd_pcm_uframes_t ...@@ -1004,7 +1114,31 @@ static snd_pcm_uframes_t
snd_rme32_capture_pointer(snd_pcm_substream_t * substream) snd_rme32_capture_pointer(snd_pcm_substream_t * substream)
{ {
rme32_t *rme32 = _snd_pcm_substream_chip(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 = { static snd_pcm_ops_t snd_rme32_playback_spdif_ops = {
...@@ -1032,6 +1166,31 @@ static snd_pcm_ops_t snd_rme32_capture_spdif_ops = { ...@@ -1032,6 +1166,31 @@ static snd_pcm_ops_t snd_rme32_capture_spdif_ops = {
copy: snd_rme32_capture_copy, 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) static void snd_rme32_free(void *private_data)
{ {
rme32_t *rme32 = (rme32_t *) private_data; rme32_t *rme32 = (rme32_t *) private_data;
...@@ -1063,6 +1222,14 @@ static void snd_rme32_free_spdif_pcm(snd_pcm_t * pcm) ...@@ -1063,6 +1222,14 @@ static void snd_rme32_free_spdif_pcm(snd_pcm_t * pcm)
snd_pcm_lib_preallocate_free_for_all(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) static int __devinit snd_rme32_create(rme32_t * rme32)
{ {
struct pci_dev *pci = rme32->pci; struct pci_dev *pci = rme32->pci;
...@@ -1117,10 +1284,33 @@ static int __devinit snd_rme32_create(rme32_t * rme32) ...@@ -1117,10 +1284,33 @@ static int __devinit snd_rme32_create(rme32_t * rme32)
GFP_KERNEL); GFP_KERNEL);
/* set up ALSA pcm device for ADAT */ /* set up ALSA pcm device for ADAT */
if (pci->device == PCI_DEVICE_ID_DIGI32) { if ((pci->device == PCI_DEVICE_ID_DIGI32) ||
/* ADAT is not available on the base model */ (pci->device == PCI_DEVICE_ID_DIGI32_PRO)) {
/* ADAT is not available on DIGI32 and DIGI32 Pro */
rme32->adat_pcm = NULL; 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->playback_periodsize = 0;
rme32->capture_periodsize = 0; rme32->capture_periodsize = 0;
...@@ -1137,8 +1327,8 @@ static int __devinit snd_rme32_create(rme32_t * rme32) ...@@ -1137,8 +1327,8 @@ static int __devinit snd_rme32_create(rme32_t * rme32)
/* set default values in registers */ /* set default values in registers */
rme32->wcreg = RME32_WCR_SEL | /* normal playback */ rme32->wcreg = RME32_WCR_SEL | /* normal playback */
RME32_WCR_INP_0 | /* input select */ RME32_WCR_INP_0 | /* input select */
RME32_WCR_MUTE; /* setting muting on */ RME32_WCR_MUTE; /* muting on */
writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <sound/info.h> #include <sound/info.h>
#include <sound/control.h> #include <sound/control.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/asoundef.h> #include <sound/asoundef.h>
#define SNDRV_GET_ID #define SNDRV_GET_ID
#include <sound/initval.h> #include <sound/initval.h>
......
...@@ -366,9 +366,9 @@ static void snd_via8233_setup_periods(via8233_t *chip, viadev_t *viadev, ...@@ -366,9 +366,9 @@ static void snd_via8233_setup_periods(via8233_t *chip, viadev_t *viadev,
switch (runtime->channels) { switch (runtime->channels) {
case 1: slots = (1<<0); break; case 1: slots = (1<<0); break;
case 2: slots = (1<<0) | (2<<4); 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; 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 */ /* STOP index is never reached */
outl(0xff000000 | slots, chip->port + VIA_REG_MULTPLAY_STOP_IDX); 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