mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
[ALSA] pcm: add snd_pcm_rate_to_rate_bit() helper
Add a snd_pcm_rate_to_rate_bit() function to factor out common code used by several drivers. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
This commit is contained in:
parent
7653d55760
commit
918f3a0e8c
@ -925,6 +925,7 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
|
||||
extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
|
||||
|
||||
int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime);
|
||||
unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate);
|
||||
|
||||
static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream,
|
||||
struct snd_dma_buffer *bufp)
|
||||
|
@ -450,3 +450,21 @@ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
|
||||
|
||||
/**
|
||||
* snd_pcm_rate_to_rate_bit - converts sample rate to SNDRV_PCM_RATE_xxx bit
|
||||
* @rate: the sample rate to convert
|
||||
*
|
||||
* Returns the SNDRV_PCM_RATE_xxx flag that corresponds to the given rate, or
|
||||
* SNDRV_PCM_RATE_KNOT for an unknown rate.
|
||||
*/
|
||||
unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < snd_pcm_known_rates.count; i++)
|
||||
if (snd_pcm_known_rates.list[i] == rate)
|
||||
return 1u << i;
|
||||
return SNDRV_PCM_RATE_KNOT;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_pcm_rate_to_rate_bit);
|
||||
|
@ -340,28 +340,9 @@ static struct snd_pcm_hardware snd_bt87x_analog_hw = {
|
||||
|
||||
static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime)
|
||||
{
|
||||
static struct {
|
||||
int rate;
|
||||
unsigned int bit;
|
||||
} ratebits[] = {
|
||||
{8000, SNDRV_PCM_RATE_8000},
|
||||
{11025, SNDRV_PCM_RATE_11025},
|
||||
{16000, SNDRV_PCM_RATE_16000},
|
||||
{22050, SNDRV_PCM_RATE_22050},
|
||||
{32000, SNDRV_PCM_RATE_32000},
|
||||
{44100, SNDRV_PCM_RATE_44100},
|
||||
{48000, SNDRV_PCM_RATE_48000}
|
||||
};
|
||||
int i;
|
||||
|
||||
chip->reg_control |= CTL_DA_IOM_DA;
|
||||
runtime->hw = snd_bt87x_digital_hw;
|
||||
runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
|
||||
for (i = 0; i < ARRAY_SIZE(ratebits); ++i)
|
||||
if (chip->dig_rate == ratebits[i].rate) {
|
||||
runtime->hw.rates = ratebits[i].bit;
|
||||
break;
|
||||
}
|
||||
runtime->hw.rates = snd_pcm_rate_to_rate_bit(chip->dig_rate);
|
||||
runtime->hw.rate_min = chip->dig_rate;
|
||||
runtime->hw.rate_max = chip->dig_rate;
|
||||
return 0;
|
||||
|
@ -258,19 +258,6 @@ static inline unsigned int snd_rme32_pcm_byteptr(struct rme32 * rme32)
|
||||
& RME32_RCR_AUDIO_ADDR_MASK);
|
||||
}
|
||||
|
||||
static int snd_rme32_ratecode(int rate)
|
||||
{
|
||||
switch (rate) {
|
||||
case 32000: return SNDRV_PCM_RATE_32000;
|
||||
case 44100: return SNDRV_PCM_RATE_44100;
|
||||
case 48000: return SNDRV_PCM_RATE_48000;
|
||||
case 64000: return SNDRV_PCM_RATE_64000;
|
||||
case 88200: return SNDRV_PCM_RATE_88200;
|
||||
case 96000: return SNDRV_PCM_RATE_96000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* silence callback for halfduplex mode */
|
||||
static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */
|
||||
snd_pcm_uframes_t pos,
|
||||
@ -887,7 +874,7 @@ static int snd_rme32_playback_spdif_open(struct snd_pcm_substream *substream)
|
||||
if ((rme32->rcreg & RME32_RCR_KMODE) &&
|
||||
(rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) {
|
||||
/* AutoSync */
|
||||
runtime->hw.rates = snd_rme32_ratecode(rate);
|
||||
runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
|
||||
runtime->hw.rate_min = rate;
|
||||
runtime->hw.rate_max = rate;
|
||||
}
|
||||
@ -929,7 +916,7 @@ static int snd_rme32_capture_spdif_open(struct snd_pcm_substream *substream)
|
||||
if (isadat) {
|
||||
return -EIO;
|
||||
}
|
||||
runtime->hw.rates = snd_rme32_ratecode(rate);
|
||||
runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
|
||||
runtime->hw.rate_min = rate;
|
||||
runtime->hw.rate_max = rate;
|
||||
}
|
||||
@ -965,7 +952,7 @@ snd_rme32_playback_adat_open(struct snd_pcm_substream *substream)
|
||||
if ((rme32->rcreg & RME32_RCR_KMODE) &&
|
||||
(rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) {
|
||||
/* AutoSync */
|
||||
runtime->hw.rates = snd_rme32_ratecode(rate);
|
||||
runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
|
||||
runtime->hw.rate_min = rate;
|
||||
runtime->hw.rate_max = rate;
|
||||
}
|
||||
@ -989,7 +976,7 @@ snd_rme32_capture_adat_open(struct snd_pcm_substream *substream)
|
||||
if (!isadat) {
|
||||
return -EIO;
|
||||
}
|
||||
runtime->hw.rates = snd_rme32_ratecode(rate);
|
||||
runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
|
||||
runtime->hw.rate_min = rate;
|
||||
runtime->hw.rate_max = rate;
|
||||
}
|
||||
|
@ -300,20 +300,6 @@ snd_rme96_capture_ptr(struct rme96 *rme96)
|
||||
& RME96_RCR_AUDIO_ADDR_MASK) >> rme96->capture_frlog;
|
||||
}
|
||||
|
||||
static int
|
||||
snd_rme96_ratecode(int rate)
|
||||
{
|
||||
switch (rate) {
|
||||
case 32000: return SNDRV_PCM_RATE_32000;
|
||||
case 44100: return SNDRV_PCM_RATE_44100;
|
||||
case 48000: return SNDRV_PCM_RATE_48000;
|
||||
case 64000: return SNDRV_PCM_RATE_64000;
|
||||
case 88200: return SNDRV_PCM_RATE_88200;
|
||||
case 96000: return SNDRV_PCM_RATE_96000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
snd_rme96_playback_silence(struct snd_pcm_substream *substream,
|
||||
int channel, /* not used (interleaved data) */
|
||||
@ -1192,7 +1178,7 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream)
|
||||
(rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0)
|
||||
{
|
||||
/* slave clock */
|
||||
runtime->hw.rates = snd_rme96_ratecode(rate);
|
||||
runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
|
||||
runtime->hw.rate_min = rate;
|
||||
runtime->hw.rate_max = rate;
|
||||
}
|
||||
@ -1219,7 +1205,7 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream)
|
||||
if (isadat) {
|
||||
return -EIO;
|
||||
}
|
||||
runtime->hw.rates = snd_rme96_ratecode(rate);
|
||||
runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
|
||||
runtime->hw.rate_min = rate;
|
||||
runtime->hw.rate_max = rate;
|
||||
}
|
||||
@ -1259,7 +1245,7 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream)
|
||||
(rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0)
|
||||
{
|
||||
/* slave clock */
|
||||
runtime->hw.rates = snd_rme96_ratecode(rate);
|
||||
runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
|
||||
runtime->hw.rate_min = rate;
|
||||
runtime->hw.rate_max = rate;
|
||||
}
|
||||
@ -1284,7 +1270,7 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream)
|
||||
if (!isadat) {
|
||||
return -EIO;
|
||||
}
|
||||
runtime->hw.rates = snd_rme96_ratecode(rate);
|
||||
runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
|
||||
runtime->hw.rate_min = rate;
|
||||
runtime->hw.rate_max = rate;
|
||||
}
|
||||
|
@ -490,35 +490,14 @@ static int snd_pmac_pcm_open(struct snd_pmac *chip, struct pmac_stream *rec,
|
||||
struct snd_pcm_substream *subs)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = subs->runtime;
|
||||
int i, j, fflags;
|
||||
static int typical_freqs[] = {
|
||||
44100,
|
||||
22050,
|
||||
11025,
|
||||
0,
|
||||
};
|
||||
static int typical_freq_flags[] = {
|
||||
SNDRV_PCM_RATE_44100,
|
||||
SNDRV_PCM_RATE_22050,
|
||||
SNDRV_PCM_RATE_11025,
|
||||
0,
|
||||
};
|
||||
int i;
|
||||
|
||||
/* look up frequency table and fill bit mask */
|
||||
runtime->hw.rates = 0;
|
||||
fflags = chip->freqs_ok;
|
||||
for (i = 0; typical_freqs[i]; i++) {
|
||||
for (j = 0; j < chip->num_freqs; j++) {
|
||||
if ((chip->freqs_ok & (1 << j)) &&
|
||||
chip->freq_table[j] == typical_freqs[i]) {
|
||||
runtime->hw.rates |= typical_freq_flags[i];
|
||||
fflags &= ~(1 << j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fflags) /* rest */
|
||||
runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
|
||||
for (i = 0; i < chip->num_freqs; i++)
|
||||
if (chip->freqs_ok & (1 << i))
|
||||
runtime->hw.rates |=
|
||||
snd_pcm_rate_to_rate_bit(chip->freq_table[i]);
|
||||
|
||||
/* check for minimum and maximum rates */
|
||||
for (i = 0; i < chip->num_freqs; i++) {
|
||||
|
@ -55,35 +55,6 @@ struct cs4270_private {
|
||||
static unsigned int mclk_ratios[NUM_MCLK_RATIOS] =
|
||||
{64, 96, 128, 192, 256, 384, 512, 768, 1024};
|
||||
|
||||
/*
|
||||
* Sampling rate <-> bit patter mapping
|
||||
*
|
||||
* This array maps sampling rates to their SNDRV_PCM_RATE_x equivalent.
|
||||
*
|
||||
* This is really something that ALSA should provide.
|
||||
*
|
||||
* This table is used by cs4270_set_dai_sysclk() to tell ALSA which sampling
|
||||
* rates the CS4270 currently supports.
|
||||
*/
|
||||
static struct {
|
||||
unsigned int rate;
|
||||
unsigned int bit;
|
||||
} rate_map[] = {
|
||||
{5512, SNDRV_PCM_RATE_5512},
|
||||
{8000, SNDRV_PCM_RATE_8000},
|
||||
{11025, SNDRV_PCM_RATE_11025},
|
||||
{16000, SNDRV_PCM_RATE_16000},
|
||||
{22050, SNDRV_PCM_RATE_22050},
|
||||
{32000, SNDRV_PCM_RATE_32000},
|
||||
{44100, SNDRV_PCM_RATE_44100},
|
||||
{48000, SNDRV_PCM_RATE_48000},
|
||||
{64000, SNDRV_PCM_RATE_64000},
|
||||
{88200, SNDRV_PCM_RATE_88200},
|
||||
{96000, SNDRV_PCM_RATE_96000},
|
||||
{176400, SNDRV_PCM_RATE_176400},
|
||||
{192000, SNDRV_PCM_RATE_192000}
|
||||
};
|
||||
|
||||
/*
|
||||
* Determine the CS4270 samples rates.
|
||||
*
|
||||
@ -126,19 +97,15 @@ static int cs4270_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
|
||||
cs4270->mclk = freq;
|
||||
|
||||
for (i = 0; i < NUM_MCLK_RATIOS; i++) {
|
||||
unsigned int rate;
|
||||
unsigned int j;
|
||||
rate = freq / mclk_ratios[i];
|
||||
for (j = 0; j < ARRAY_SIZE(rate_map); j++) {
|
||||
if (rate == rate_map[j].rate) {
|
||||
rates |= rate_map[j].bit;
|
||||
if (rate < rate_min)
|
||||
rate_min = rate;
|
||||
if (rate > rate_max)
|
||||
rate_max = rate;
|
||||
}
|
||||
}
|
||||
unsigned int rate = freq / mclk_ratios[i];
|
||||
rates |= snd_pcm_rate_to_rate_bit(rate);
|
||||
if (rate < rate_min)
|
||||
rate_min = rate;
|
||||
if (rate > rate_max)
|
||||
rate_max = rate;
|
||||
}
|
||||
/* FIXME: soc should support a rate list */
|
||||
rates &= ~SNDRV_PCM_RATE_KNOT;
|
||||
|
||||
if (!rates) {
|
||||
printk(KERN_ERR "cs4270: could not find a valid sample rate\n");
|
||||
|
@ -123,7 +123,6 @@ struct audioformat {
|
||||
unsigned int rate_min, rate_max; /* min/max rates */
|
||||
unsigned int nr_rates; /* number of rate table entries */
|
||||
unsigned int *rate_table; /* rate table */
|
||||
unsigned int needs_knot; /* any unusual rates? */
|
||||
};
|
||||
|
||||
struct snd_usb_substream;
|
||||
@ -1761,7 +1760,7 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
|
||||
channels[f->format] |= (1 << f->channels);
|
||||
rates[f->format] |= f->rates;
|
||||
/* needs knot? */
|
||||
if (f->needs_knot)
|
||||
if (f->rates & SNDRV_PCM_RATE_KNOT)
|
||||
goto __out;
|
||||
}
|
||||
/* check whether channels and rates match for all formats */
|
||||
@ -1817,7 +1816,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
|
||||
if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
|
||||
return 0;
|
||||
count += fp->nr_rates;
|
||||
if (fp->needs_knot)
|
||||
if (fp->rates & SNDRV_PCM_RATE_KNOT)
|
||||
needs_knot = 1;
|
||||
}
|
||||
if (!needs_knot)
|
||||
@ -2453,7 +2452,7 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
|
||||
unsigned char *fmt, int offset)
|
||||
{
|
||||
int nr_rates = fmt[offset];
|
||||
int found;
|
||||
|
||||
if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
|
||||
snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
|
||||
chip->dev->devnum, fp->iface, fp->altsetting);
|
||||
@ -2464,20 +2463,15 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
|
||||
/*
|
||||
* build the rate table and bitmap flags
|
||||
*/
|
||||
int r, idx, c;
|
||||
int r, idx;
|
||||
unsigned int nonzero_rates = 0;
|
||||
/* this table corresponds to the SNDRV_PCM_RATE_XXX bit */
|
||||
static unsigned int conv_rates[] = {
|
||||
5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000,
|
||||
64000, 88200, 96000, 176400, 192000
|
||||
};
|
||||
|
||||
fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
|
||||
if (fp->rate_table == NULL) {
|
||||
snd_printk(KERN_ERR "cannot malloc\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fp->needs_knot = 0;
|
||||
fp->nr_rates = nr_rates;
|
||||
fp->rate_min = fp->rate_max = combine_triple(&fmt[8]);
|
||||
for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) {
|
||||
@ -2493,23 +2487,12 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
|
||||
fp->rate_min = rate;
|
||||
else if (rate > fp->rate_max)
|
||||
fp->rate_max = rate;
|
||||
found = 0;
|
||||
for (c = 0; c < (int)ARRAY_SIZE(conv_rates); c++) {
|
||||
if (rate == conv_rates[c]) {
|
||||
found = 1;
|
||||
fp->rates |= (1 << c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
fp->needs_knot = 1;
|
||||
fp->rates |= snd_pcm_rate_to_rate_bit(rate);
|
||||
}
|
||||
if (!nonzero_rates) {
|
||||
hwc_debug("All rates were zero. Skipping format!\n");
|
||||
return -1;
|
||||
}
|
||||
if (fp->needs_knot)
|
||||
fp->rates |= SNDRV_PCM_RATE_KNOT;
|
||||
} else {
|
||||
/* continuous rates */
|
||||
fp->rates = SNDRV_PCM_RATE_CONTINUOUS;
|
||||
|
Loading…
Reference in New Issue
Block a user