Commit e88e8ae6 authored by Takashi Iwai's avatar Takashi Iwai Committed by Jaroslav Kysela
Browse files

[ALSA] Move OSS-specific hw_params helper to snd-pcm-oss module



Move EXPORT_SYMBOL()s to places adjacent to functions/variables.
Also move OSS-specific hw_params helper functions to pcm_oss.c.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent e5e8a1d4
......@@ -825,14 +825,6 @@ int snd_interval_ratnum(struct snd_interval *i,
void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params);
void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var);
int snd_pcm_hw_param_near(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var,
unsigned int val, int *dir);
int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm,
struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var,
unsigned int val, int dir);
int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params);
int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params);
......
......@@ -22,18 +22,14 @@
*
*/
extern int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, const struct snd_mask *val);
extern unsigned int snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, int *dir);
extern unsigned int snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, int *dir);
extern int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val, int dir);
extern int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var);
extern int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val, int dir);
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);
#define SNDRV_MASK_BITS 64 /* we use so far 64bits only */
#define SNDRV_MASK_SIZE (SNDRV_MASK_BITS / 32)
......
......@@ -78,6 +78,487 @@ static inline void snd_leave_user(mm_segment_t fs)
set_fs(fs);
}
/*
* helper functions to process hw_params
*/
static int snd_interval_refine_min(struct snd_interval *i, unsigned int min, int openmin)
{
int changed = 0;
if (i->min < min) {
i->min = min;
i->openmin = openmin;
changed = 1;
} else if (i->min == min && !i->openmin && openmin) {
i->openmin = 1;
changed = 1;
}
if (i->integer) {
if (i->openmin) {
i->min++;
i->openmin = 0;
}
}
if (snd_interval_checkempty(i)) {
snd_interval_none(i);
return -EINVAL;
}
return changed;
}
static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int openmax)
{
int changed = 0;
if (i->max > max) {
i->max = max;
i->openmax = openmax;
changed = 1;
} else if (i->max == max && !i->openmax && openmax) {
i->openmax = 1;
changed = 1;
}
if (i->integer) {
if (i->openmax) {
i->max--;
i->openmax = 0;
}
}
if (snd_interval_checkempty(i)) {
snd_interval_none(i);
return -EINVAL;
}
return changed;
}
static int snd_interval_refine_set(struct snd_interval *i, unsigned int val)
{
struct snd_interval t;
t.empty = 0;
t.min = t.max = val;
t.openmin = t.openmax = 0;
t.integer = 1;
return snd_interval_refine(i, &t);
}
/**
* snd_pcm_hw_param_value_min
* @params: the hw_params instance
* @var: parameter to retrieve
* @dir: pointer to the direction (-1,0,1) or NULL
*
* Return the minimum value for field PAR.
*/
static unsigned int
snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, int *dir)
{
if (hw_is_mask(var)) {
if (dir)
*dir = 0;
return snd_mask_min(hw_param_mask_c(params, var));
}
if (hw_is_interval(var)) {
const struct snd_interval *i = hw_param_interval_c(params, var);
if (dir)
*dir = i->openmin;
return snd_interval_min(i);
}
return -EINVAL;
}
/**
* snd_pcm_hw_param_value_max
* @params: the hw_params instance
* @var: parameter to retrieve
* @dir: pointer to the direction (-1,0,1) or NULL
*
* Return the maximum value for field PAR.
*/
static unsigned int
snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, int *dir)
{
if (hw_is_mask(var)) {
if (dir)
*dir = 0;
return snd_mask_max(hw_param_mask_c(params, var));
}
if (hw_is_interval(var)) {
const struct snd_interval *i = hw_param_interval_c(params, var);
if (dir)
*dir = - (int) i->openmax;
return snd_interval_max(i);
}
return -EINVAL;
}
static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var,
const struct snd_mask *val)
{
int changed;
changed = snd_mask_refine(hw_param_mask(params, var), val);
if (changed) {
params->cmask |= 1 << var;
params->rmask |= 1 << var;
}
return changed;
}
static int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm,
struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var,
const struct snd_mask *val)
{
int changed = _snd_pcm_hw_param_mask(params, var, val);
if (changed < 0)
return changed;
if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
if (err < 0)
return err;
}
return 0;
}
static int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val,
int dir)
{
int changed;
int open = 0;
if (dir) {
if (dir > 0) {
open = 1;
} else if (dir < 0) {
if (val > 0) {
open = 1;
val--;
}
}
}
if (hw_is_mask(var))
changed = snd_mask_refine_min(hw_param_mask(params, var),
val + !!open);
else if (hw_is_interval(var))
changed = snd_interval_refine_min(hw_param_interval(params, var),
val, open);
else
return -EINVAL;
if (changed) {
params->cmask |= 1 << var;
params->rmask |= 1 << var;
}
return changed;
}
/**
* snd_pcm_hw_param_min
* @pcm: PCM instance
* @params: the hw_params instance
* @var: parameter to retrieve
* @val: minimal value
* @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS remove from PAR all
* values < VAL. Reduce configuration space accordingly.
* Return new minimum or -EINVAL if the configuration space is empty
*/
static int snd_pcm_hw_param_min(struct snd_pcm_substream *pcm,
struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val,
int *dir)
{
int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
if (changed < 0)
return changed;
if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
if (err < 0)
return err;
}
return snd_pcm_hw_param_value_min(params, var, dir);
}
static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val,
int dir)
{
int changed;
int open = 0;
if (dir) {
if (dir < 0) {
open = 1;
} else if (dir > 0) {
open = 1;
val++;
}
}
if (hw_is_mask(var)) {
if (val == 0 && open) {
snd_mask_none(hw_param_mask(params, var));
changed = -EINVAL;
} else
changed = snd_mask_refine_max(hw_param_mask(params, var),
val - !!open);
} else if (hw_is_interval(var))
changed = snd_interval_refine_max(hw_param_interval(params, var),
val, open);
else
return -EINVAL;
if (changed) {
params->cmask |= 1 << var;
params->rmask |= 1 << var;
}
return changed;
}
/**
* snd_pcm_hw_param_max
* @pcm: PCM instance
* @params: the hw_params instance
* @var: parameter to retrieve
* @val: maximal value
* @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS remove from PAR all
* values >= VAL + 1. Reduce configuration space accordingly.
* Return new maximum or -EINVAL if the configuration space is empty
*/
static int snd_pcm_hw_param_max(struct snd_pcm_substream *pcm,
struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val,
int *dir)
{
int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
if (changed < 0)
return changed;
if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
if (err < 0)
return err;
}
return snd_pcm_hw_param_value_max(params, var, dir);
}
static int boundary_sub(int a, int adir,
int b, int bdir,
int *c, int *cdir)
{
adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0);
bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0);
*c = a - b;
*cdir = adir - bdir;
if (*cdir == -2) {
(*c)--;
} else if (*cdir == 2) {
(*c)++;
}
return 0;
}
static int boundary_lt(unsigned int a, int adir,
unsigned int b, int bdir)
{
if (adir < 0) {
a--;
adir = 1;
} else if (adir > 0)
adir = 1;
if (bdir < 0) {
b--;
bdir = 1;
} else if (bdir > 0)
bdir = 1;
return a < b || (a == b && adir < bdir);
}
/* Return 1 if min is nearer to best than max */
static int boundary_nearer(int min, int mindir,
int best, int bestdir,
int max, int maxdir)
{
int dmin, dmindir;
int dmax, dmaxdir;
boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir);
boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir);
return boundary_lt(dmin, dmindir, dmax, dmaxdir);
}
/**
* snd_pcm_hw_param_near
* @pcm: PCM instance
* @params: the hw_params instance
* @var: parameter to retrieve
* @best: value to set
* @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS set PAR to the available value
* nearest to VAL. Reduce configuration space accordingly.
* This function cannot be called for SNDRV_PCM_HW_PARAM_ACCESS,
* SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT.
* Return the value found.
*/
static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm,
struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int best,
int *dir)
{
struct snd_pcm_hw_params *save = NULL;
int v;
unsigned int saved_min;
int last = 0;
int min, max;
int mindir, maxdir;
int valdir = dir ? *dir : 0;
/* FIXME */
if (best > INT_MAX)
best = INT_MAX;
min = max = best;
mindir = maxdir = valdir;
if (maxdir > 0)
maxdir = 0;
else if (maxdir == 0)
maxdir = -1;
else {
maxdir = 1;
max--;
}
save = kmalloc(sizeof(*save), GFP_KERNEL);
if (save == NULL)
return -ENOMEM;
*save = *params;
saved_min = min;
min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
if (min >= 0) {
struct snd_pcm_hw_params *params1;
if (max < 0)
goto _end;
if ((unsigned int)min == saved_min && mindir == valdir)
goto _end;
params1 = kmalloc(sizeof(*params1), GFP_KERNEL);
if (params1 == NULL) {
kfree(save);
return -ENOMEM;
}
*params1 = *save;
max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir);
if (max < 0) {
kfree(params1);
goto _end;
}
if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
*params = *params1;
last = 1;
}
kfree(params1);
} else {
*params = *save;
max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);
snd_assert(max >= 0, return -EINVAL);
last = 1;
}
_end:
kfree(save);
if (last)
v = snd_pcm_hw_param_last(pcm, params, var, dir);
else
v = snd_pcm_hw_param_first(pcm, params, var, dir);
snd_assert(v >= 0, return -EINVAL);
return v;
}
static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val,
int dir)
{
int changed;
if (hw_is_mask(var)) {
struct snd_mask *m = hw_param_mask(params, var);
if (val == 0 && dir < 0) {
changed = -EINVAL;
snd_mask_none(m);
} else {
if (dir > 0)
val++;
else if (dir < 0)
val--;
changed = snd_mask_refine_set(hw_param_mask(params, var), val);
}
} else if (hw_is_interval(var)) {
struct snd_interval *i = hw_param_interval(params, var);
if (val == 0 && dir < 0) {
changed = -EINVAL;
snd_interval_none(i);
} else if (dir == 0)
changed = snd_interval_refine_set(i, val);
else {
struct snd_interval t;
t.openmin = 1;
t.openmax = 1;
t.empty = 0;
t.integer = 0;
if (dir < 0) {
t.min = val - 1;
t.max = val;
} else {
t.min = val;
t.max = val+1;
}
changed = snd_interval_refine(i, &t);
}
} else
return -EINVAL;
if (changed) {
params->cmask |= 1 << var;
params->rmask |= 1 << var;
}
return changed;
}
/**
* snd_pcm_hw_param_set
* @pcm: PCM instance
* @params: the hw_params instance
* @var: parameter to retrieve
* @val: value to set
* @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS remove from PAR all
* values != VAL. Reduce configuration space accordingly.
* Return VAL or -EINVAL if the configuration space is empty
*/
static int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm,
struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val,
int dir)
{
int changed = _snd_pcm_hw_param_set(params, var, val, dir);
if (changed < 0)
return changed;
if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
if (err < 0)
return err;
}
return snd_pcm_hw_param_value(params, var, NULL);
}
static int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
int changed;
changed = snd_interval_setinteger(hw_param_interval(params, var));
if (changed) {
params->cmask |= 1 << var;
params->rmask |= 1 << var;
}
return changed;
}
/*
* plugin
*/
#ifdef CONFIG_SND_PCM_OSS_PLUGINS
static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream)
{
......
......@@ -671,6 +671,8 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
return 0;
}
EXPORT_SYMBOL(snd_pcm_new_stream);
/**
* snd_pcm_new - create a new PCM instance
* @card: the card instance
......@@ -730,6 +732,8 @@ int snd_pcm_new(struct snd_card *card, char *id, int device,
return 0;
}
EXPORT_SYMBOL(snd_pcm_new);
static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
{
struct snd_pcm_substream *substream, *substream_next;
......@@ -1022,6 +1026,8 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
return 0;
}
EXPORT_SYMBOL(snd_pcm_notify);
#ifdef CONFIG_PROC_FS
/*
* Info interface
......@@ -1099,33 +1105,3 @@ static void __exit alsa_pcm_exit(void)
module_init(alsa_pcm_init)
module_exit(alsa_pcm_exit)
EXPORT_SYMBOL(snd_pcm_new);
EXPORT_SYMBOL(snd_pcm_new_stream);
EXPORT_SYMBOL(snd_pcm_notify);
EXPORT_SYMBOL(snd_pcm_open_substream);
EXPORT_SYMBOL(snd_pcm_release_substream);
/* pcm_native.c */
EXPORT_SYMBOL(snd_pcm_link_rwlock);
#ifdef CONFIG_PM
EXPORT_SYMBOL(snd_pcm_suspend);
EXPORT_SYMBOL(snd_pcm_suspend_all);
#endif
EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
EXPORT_SYMBOL(snd_pcm_mmap_data);
#if SNDRV_PCM_INFO_MMAP_IOMEM
EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
#endif
/* pcm_misc.c */
EXPORT_SYMBOL(snd_pcm_format_signed);
EXPORT_SYMBOL(snd_pcm_format_unsigned);
EXPORT_SYMBOL(snd_pcm_format_linear);
EXPORT_SYMBOL(snd_pcm_format_little_endian);
EXPORT_SYMBOL(snd_pcm_format_big_endian);
EXPORT_SYMBOL(snd_pcm_format_width);
EXPORT_SYMBOL(snd_pcm_format_physical_width);
EXPORT_SYMBOL(snd_pcm_format_size);
EXPORT_SYMBOL(snd_pcm_format_silence_64);
EXPORT_SYMBOL(snd_pcm_format_set_silence);
EXPORT_SYMBOL(snd_pcm_build_linear_format);
EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
This diff is collapsed.
......@@ -126,6 +126,8 @@ int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
return 0;
}
EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
#ifdef CONFIG_SND_VERBOSE_PROCFS
/*
* read callback for prealloc proc file
......@@ -253,6 +255,8 @@ int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
return snd_pcm_lib_preallocate_pages1(substream, size, max);
}
EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
/**
* snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continous memory type (all substreams)
* @pcm: the pcm instance
......@@ -280,6 +284,8 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
return 0;
}
EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);