2005-04-17 02:20:36 +04:00
# ifndef __SOUND_PCM_PARAMS_H
# define __SOUND_PCM_PARAMS_H
/*
* PCM params helpers
* Copyright ( c ) by Abramo Bagnara < abramo @ alsa - project . org >
*
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
2006-04-28 17:13:40 +04:00
int snd_pcm_hw_param_first ( struct snd_pcm_substream * pcm ,
struct snd_pcm_hw_params * params ,
snd_pcm_hw_param_t var , int * dir ) ;
int snd_pcm_hw_param_last ( struct snd_pcm_substream * pcm ,
struct snd_pcm_hw_params * params ,
snd_pcm_hw_param_t var , int * dir ) ;
int snd_pcm_hw_param_value ( const struct snd_pcm_hw_params * params ,
snd_pcm_hw_param_t var , int * dir ) ;
2005-04-17 02:20:36 +04:00
# 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))
2006-04-28 17:13:39 +04:00
static inline unsigned int ld2 ( u_int32_t v )
2005-04-17 02:20:36 +04:00
{
unsigned r = 0 ;
if ( v > = 0x10000 ) {
v > > = 16 ;
r + = 16 ;
}
if ( v > = 0x100 ) {
v > > = 8 ;
r + = 8 ;
}
if ( v > = 0x10 ) {
v > > = 4 ;
r + = 4 ;
}
if ( v > = 4 ) {
v > > = 2 ;
r + = 2 ;
}
if ( v > = 2 )
r + + ;
return r ;
}
2006-04-28 17:13:39 +04:00
static inline size_t snd_mask_sizeof ( void )
2005-04-17 02:20:36 +04:00
{
2005-11-17 15:59:38 +03:00
return sizeof ( struct snd_mask ) ;
2005-04-17 02:20:36 +04:00
}
2006-04-28 17:13:39 +04:00
static inline void snd_mask_none ( struct snd_mask * mask )
2005-04-17 02:20:36 +04:00
{
memset ( mask , 0 , sizeof ( * mask ) ) ;
}
2006-04-28 17:13:39 +04:00
static inline void snd_mask_any ( struct snd_mask * mask )
2005-04-17 02:20:36 +04:00
{
memset ( mask , 0xff , SNDRV_MASK_SIZE * sizeof ( u_int32_t ) ) ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_mask_empty ( const struct snd_mask * mask )
2005-04-17 02:20:36 +04:00
{
int i ;
for ( i = 0 ; i < SNDRV_MASK_SIZE ; i + + )
if ( mask - > bits [ i ] )
return 0 ;
return 1 ;
}
2006-04-28 17:13:39 +04:00
static inline unsigned int snd_mask_min ( const struct snd_mask * mask )
2005-04-17 02:20:36 +04:00
{
int i ;
for ( i = 0 ; i < SNDRV_MASK_SIZE ; i + + ) {
if ( mask - > bits [ i ] )
return ffs ( mask - > bits [ i ] ) - 1 + ( i < < 5 ) ;
}
return 0 ;
}
2006-04-28 17:13:39 +04:00
static inline unsigned int snd_mask_max ( const struct snd_mask * mask )
2005-04-17 02:20:36 +04:00
{
int i ;
for ( i = SNDRV_MASK_SIZE - 1 ; i > = 0 ; i - - ) {
if ( mask - > bits [ i ] )
return ld2 ( mask - > bits [ i ] ) + ( i < < 5 ) ;
}
return 0 ;
}
2006-04-28 17:13:39 +04:00
static inline void snd_mask_set ( struct snd_mask * mask , unsigned int val )
2005-04-17 02:20:36 +04:00
{
mask - > bits [ MASK_OFS ( val ) ] | = MASK_BIT ( val ) ;
}
2006-04-28 17:13:39 +04:00
static inline void snd_mask_reset ( struct snd_mask * mask , unsigned int val )
2005-04-17 02:20:36 +04:00
{
mask - > bits [ MASK_OFS ( val ) ] & = ~ MASK_BIT ( val ) ;
}
2006-04-28 17:13:39 +04:00
static inline void snd_mask_set_range ( struct snd_mask * mask ,
unsigned int from , unsigned int to )
2005-04-17 02:20:36 +04:00
{
unsigned int i ;
for ( i = from ; i < = to ; i + + )
mask - > bits [ MASK_OFS ( i ) ] | = MASK_BIT ( i ) ;
}
2006-04-28 17:13:39 +04:00
static inline void snd_mask_reset_range ( struct snd_mask * mask ,
unsigned int from , unsigned int to )
2005-04-17 02:20:36 +04:00
{
unsigned int i ;
for ( i = from ; i < = to ; i + + )
mask - > bits [ MASK_OFS ( i ) ] & = ~ MASK_BIT ( i ) ;
}
2006-04-28 17:13:39 +04:00
static inline void snd_mask_leave ( struct snd_mask * mask , unsigned int val )
2005-04-17 02:20:36 +04:00
{
unsigned int v ;
v = mask - > bits [ MASK_OFS ( val ) ] & MASK_BIT ( val ) ;
snd_mask_none ( mask ) ;
mask - > bits [ MASK_OFS ( val ) ] = v ;
}
2006-04-28 17:13:39 +04:00
static inline void snd_mask_intersect ( struct snd_mask * mask ,
const struct snd_mask * v )
2005-04-17 02:20:36 +04:00
{
int i ;
for ( i = 0 ; i < SNDRV_MASK_SIZE ; i + + )
mask - > bits [ i ] & = v - > bits [ i ] ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_mask_eq ( const struct snd_mask * mask ,
const struct snd_mask * v )
2005-04-17 02:20:36 +04:00
{
return ! memcmp ( mask , v , SNDRV_MASK_SIZE * sizeof ( u_int32_t ) ) ;
}
2006-04-28 17:13:39 +04:00
static inline void snd_mask_copy ( struct snd_mask * mask ,
const struct snd_mask * v )
2005-04-17 02:20:36 +04:00
{
* mask = * v ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_mask_test ( const struct snd_mask * mask , unsigned int val )
2005-04-17 02:20:36 +04:00
{
return mask - > bits [ MASK_OFS ( val ) ] & MASK_BIT ( val ) ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_mask_single ( const struct snd_mask * mask )
2005-04-17 02:20:36 +04:00
{
int i , c = 0 ;
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 ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_mask_refine ( struct snd_mask * mask ,
const struct snd_mask * v )
2005-04-17 02:20:36 +04:00
{
2005-11-17 15:59:38 +03:00
struct snd_mask old ;
2005-04-17 02:20:36 +04:00
snd_mask_copy ( & old , mask ) ;
snd_mask_intersect ( mask , v ) ;
if ( snd_mask_empty ( mask ) )
return - EINVAL ;
return ! snd_mask_eq ( mask , & old ) ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_mask_refine_first ( struct snd_mask * mask )
2005-04-17 02:20:36 +04:00
{
if ( snd_mask_single ( mask ) )
return 0 ;
snd_mask_leave ( mask , snd_mask_min ( mask ) ) ;
return 1 ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_mask_refine_last ( struct snd_mask * mask )
2005-04-17 02:20:36 +04:00
{
if ( snd_mask_single ( mask ) )
return 0 ;
snd_mask_leave ( mask , snd_mask_max ( mask ) ) ;
return 1 ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_mask_refine_min ( struct snd_mask * mask , unsigned int val )
2005-04-17 02:20:36 +04:00
{
if ( snd_mask_min ( mask ) > = val )
return 0 ;
snd_mask_reset_range ( mask , 0 , val - 1 ) ;
if ( snd_mask_empty ( mask ) )
return - EINVAL ;
return 1 ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_mask_refine_max ( struct snd_mask * mask , unsigned int val )
2005-04-17 02:20:36 +04:00
{
if ( snd_mask_max ( mask ) < = val )
return 0 ;
snd_mask_reset_range ( mask , val + 1 , SNDRV_MASK_BITS ) ;
if ( snd_mask_empty ( mask ) )
return - EINVAL ;
return 1 ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_mask_refine_set ( struct snd_mask * mask , unsigned int val )
2005-04-17 02:20:36 +04:00
{
int changed ;
changed = ! snd_mask_single ( mask ) ;
snd_mask_leave ( mask , val ) ;
if ( snd_mask_empty ( mask ) )
return - EINVAL ;
return changed ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_mask_value ( const struct snd_mask * mask )
2005-04-17 02:20:36 +04:00
{
return snd_mask_min ( mask ) ;
}
2006-04-28 17:13:39 +04:00
static inline void snd_interval_any ( struct snd_interval * i )
2005-04-17 02:20:36 +04:00
{
i - > min = 0 ;
i - > openmin = 0 ;
i - > max = UINT_MAX ;
i - > openmax = 0 ;
i - > integer = 0 ;
i - > empty = 0 ;
}
2006-04-28 17:13:39 +04:00
static inline void snd_interval_none ( struct snd_interval * i )
2005-04-17 02:20:36 +04:00
{
i - > empty = 1 ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_interval_checkempty ( const struct snd_interval * i )
2005-04-17 02:20:36 +04:00
{
return ( i - > min > i - > max | |
( i - > min = = i - > max & & ( i - > openmin | | i - > openmax ) ) ) ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_interval_empty ( const struct snd_interval * i )
2005-04-17 02:20:36 +04:00
{
return i - > empty ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_interval_single ( const struct snd_interval * i )
2005-04-17 02:20:36 +04:00
{
return ( i - > min = = i - > max | |
( i - > min + 1 = = i - > max & & i - > openmax ) ) ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_interval_value ( const struct snd_interval * i )
2005-04-17 02:20:36 +04:00
{
return i - > min ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_interval_min ( const struct snd_interval * i )
2005-04-17 02:20:36 +04:00
{
return i - > min ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_interval_max ( const struct snd_interval * i )
2005-04-17 02:20:36 +04:00
{
unsigned int v ;
v = i - > max ;
if ( i - > openmax )
v - - ;
return v ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_interval_test ( const struct snd_interval * i , unsigned int val )
2005-04-17 02:20:36 +04:00
{
return ! ( ( i - > min > val | | ( i - > min = = val & & i - > openmin ) | |
i - > max < val | | ( i - > max = = val & & i - > openmax ) ) ) ;
}
2006-04-28 17:13:39 +04:00
static inline void snd_interval_copy ( struct snd_interval * d , const struct snd_interval * s )
2005-04-17 02:20:36 +04:00
{
* d = * s ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_interval_setinteger ( struct snd_interval * i )
2005-04-17 02:20:36 +04:00
{
if ( i - > integer )
return 0 ;
if ( i - > openmin & & i - > openmax & & i - > min = = i - > max )
return - EINVAL ;
i - > integer = 1 ;
return 1 ;
}
2006-04-28 17:13:39 +04:00
static inline int snd_interval_eq ( const struct snd_interval * i1 , const struct snd_interval * i2 )
2005-04-17 02:20:36 +04:00
{
if ( i1 - > empty )
return i2 - > empty ;
if ( i2 - > empty )
return i1 - > empty ;
return i1 - > min = = i2 - > min & & i1 - > openmin = = i2 - > openmin & &
i1 - > max = = i2 - > max & & i1 - > openmax = = i2 - > openmax ;
}
static inline unsigned int add ( unsigned int a , unsigned int b )
{
if ( a > = UINT_MAX - b )
return UINT_MAX ;
return a + b ;
}
static inline unsigned int sub ( unsigned int a , unsigned int b )
{
if ( a > b )
return a - b ;
return 0 ;
}
2011-07-26 14:02:56 +04:00
# define params_access(p) ((__force snd_pcm_access_t)\
snd_mask_min ( hw_param_mask_c ( ( p ) , SNDRV_PCM_HW_PARAM_ACCESS ) ) )
# define params_format(p) ((__force snd_pcm_format_t)\
snd_mask_min ( hw_param_mask_c ( ( p ) , SNDRV_PCM_HW_PARAM_FORMAT ) ) )
# define params_subformat(p) \
snd_mask_min ( hw_param_mask_c ( ( p ) , SNDRV_PCM_HW_PARAM_SUBFORMAT ) )
2005-04-17 02:20:36 +04:00
2011-07-26 14:02:56 +04:00
static inline unsigned int
params_period_bytes ( const struct snd_pcm_hw_params * p )
{
return ( params_period_size ( p ) *
snd_pcm_format_physical_width ( params_format ( p ) ) *
params_channels ( p ) ) / 8 ;
}
# endif /* __SOUND_PCM_PARAMS_H */