2019-05-27 09:55:05 +03:00
/* SPDX-License-Identifier: GPL-2.0-or-later */
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 >
*/
2012-06-19 22:31:48 +04:00
# include <sound/pcm.h>
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 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 ] )
2014-12-29 21:41:44 +03:00
return __ffs ( mask - > bits [ i ] ) + ( i < < 5 ) ;
2005-04-17 02:20:36 +04:00
}
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 ] )
2014-12-29 21:41:46 +03:00
return __fls ( mask - > bits [ i ] ) + ( i < < 5 ) ;
2005-04-17 02:20:36 +04:00
}
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 ) ;
}
2018-07-26 00:17:17 +03:00
/* Most of drivers need only this one */
static inline void snd_mask_set_format ( struct snd_mask * mask ,
snd_pcm_format_t format )
{
snd_mask_set ( mask , ( __force unsigned int ) format ) ;
}
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 ) ;
}
2020-02-06 19:39:39 +03:00
/* Most of drivers need only this one */
static inline int snd_mask_test_format ( const struct snd_mask * mask ,
snd_pcm_format_t format )
{
return snd_mask_test ( mask , ( __force unsigned int ) format ) ;
}
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 | |
2018-11-29 14:05:19 +03:00
( i - > min + 1 = = i - > max & & ( i - > openmin | | i - > openmax ) ) ) ;
2005-04-17 02:20:36 +04:00
}
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
{
2018-11-29 14:05:19 +03:00
if ( i - > openmin & & ! i - > openmax )
return i - > max ;
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 ;
}
2014-12-29 21:41:42 +03:00
/**
* params_access - get the access type from the hw params
* @ p : hw params
*/
2014-12-29 21:41:41 +03:00
static inline snd_pcm_access_t params_access ( const struct snd_pcm_hw_params * p )
{
return ( __force snd_pcm_access_t ) snd_mask_min ( hw_param_mask_c ( p ,
SNDRV_PCM_HW_PARAM_ACCESS ) ) ;
}
2014-12-29 21:41:42 +03:00
/**
* params_format - get the sample format from the hw params
* @ p : hw params
*/
2014-12-29 21:41:41 +03:00
static inline snd_pcm_format_t params_format ( const struct snd_pcm_hw_params * p )
{
return ( __force snd_pcm_format_t ) snd_mask_min ( hw_param_mask_c ( p ,
SNDRV_PCM_HW_PARAM_FORMAT ) ) ;
}
2014-12-29 21:41:42 +03:00
/**
* params_subformat - get the sample subformat from the hw params
* @ p : hw params
*/
2014-12-29 21:41:41 +03:00
static inline snd_pcm_subformat_t
params_subformat ( const struct snd_pcm_hw_params * p )
{
return ( __force snd_pcm_subformat_t ) snd_mask_min ( hw_param_mask_c ( p ,
SNDRV_PCM_HW_PARAM_SUBFORMAT ) ) ;
}
2005-04-17 02:20:36 +04:00
2014-12-29 21:41:42 +03:00
/**
* params_period_bytes - get the period size ( in bytes ) from the hw params
* @ p : hw params
*/
2011-07-26 14:02:56 +04:00
static inline unsigned int
params_period_bytes ( const struct snd_pcm_hw_params * p )
{
2014-12-29 21:41:43 +03:00
return hw_param_interval_c ( p , SNDRV_PCM_HW_PARAM_PERIOD_BYTES ) - > min ;
2011-07-26 14:02:56 +04:00
}
2014-12-29 21:41:42 +03:00
/**
* params_width - get the number of bits of the sample format from the hw params
* @ p : hw params
*
* This function returns the number of bits per sample that the selected sample
* format of the hw params has .
*/
static inline int params_width ( const struct snd_pcm_hw_params * p )
2013-12-24 16:24:28 +04:00
{
return snd_pcm_format_width ( params_format ( p ) ) ;
}
2014-12-29 21:41:42 +03:00
/*
* params_physical_width - get the storage size of the sample format from the hw params
* @ p : hw params
*
* This functions returns the number of bits per sample that the selected sample
* format of the hw params takes up in memory . This will be equal or larger than
* params_width ( ) .
*/
static inline int params_physical_width ( const struct snd_pcm_hw_params * p )
2013-12-24 16:24:28 +04:00
{
return snd_pcm_format_physical_width ( params_format ( p ) ) ;
}
2023-11-17 15:05:58 +03:00
int snd_pcm_hw_params_bits ( const struct snd_pcm_hw_params * p ) ;
2015-02-09 11:18:11 +03:00
static inline void
params_set_format ( struct snd_pcm_hw_params * p , snd_pcm_format_t fmt )
{
2018-07-26 00:17:17 +03:00
snd_mask_set_format ( hw_param_mask ( p , SNDRV_PCM_HW_PARAM_FORMAT ) , fmt ) ;
2015-02-09 11:18:11 +03:00
}
2011-07-26 14:02:56 +04:00
# endif /* __SOUND_PCM_PARAMS_H */