ALSA: emu10k1: fix sample rates for E-MU cards at 44.1 kHz word clock
Now that we know the actual word clock, we can: - Put the resulting rate into the hardware info - At 44.1 kHz word clock shift the rate for the pitch calculations, which presume a 48 kHz word clock Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> Link: https://lore.kernel.org/r/20230612191325.1315854-5-oswald.buddenhagen@gmx.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
e73b597e63
commit
19b89d15fa
@ -1495,6 +1495,7 @@ struct snd_emu10k1_pcm {
|
|||||||
unsigned short first_ptr;
|
unsigned short first_ptr;
|
||||||
snd_pcm_uframes_t resume_pos;
|
snd_pcm_uframes_t resume_pos;
|
||||||
struct snd_util_memblk *memblk;
|
struct snd_util_memblk *memblk;
|
||||||
|
unsigned int pitch_target;
|
||||||
unsigned int start_addr;
|
unsigned int start_addr;
|
||||||
unsigned int ccca_start_addr;
|
unsigned int ccca_start_addr;
|
||||||
unsigned int capture_ipr; /* interrupt acknowledge mask */
|
unsigned int capture_ipr; /* interrupt acknowledge mask */
|
||||||
|
@ -195,6 +195,33 @@ static unsigned int snd_emu10k1_audigy_capture_rate_reg(unsigned int rate)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void snd_emu10k1_constrain_capture_rates(struct snd_emu10k1 *emu,
|
||||||
|
struct snd_pcm_runtime *runtime)
|
||||||
|
{
|
||||||
|
if (emu->card_capabilities->emu_model &&
|
||||||
|
emu->emu1010.word_clock == 44100) {
|
||||||
|
// This also sets the rate constraint by deleting SNDRV_PCM_RATE_KNOT
|
||||||
|
runtime->hw.rates = SNDRV_PCM_RATE_11025 | \
|
||||||
|
SNDRV_PCM_RATE_22050 | \
|
||||||
|
SNDRV_PCM_RATE_44100;
|
||||||
|
runtime->hw.rate_min = 11025;
|
||||||
|
runtime->hw.rate_max = 44100;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
|
||||||
|
&hw_constraints_capture_rates);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void snd_emu1010_constrain_efx_rate(struct snd_emu10k1 *emu,
|
||||||
|
struct snd_pcm_runtime *runtime)
|
||||||
|
{
|
||||||
|
int rate;
|
||||||
|
|
||||||
|
rate = emu->emu1010.word_clock;
|
||||||
|
runtime->hw.rate_min = runtime->hw.rate_max = rate;
|
||||||
|
runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned int emu10k1_calc_pitch_target(unsigned int rate)
|
static unsigned int emu10k1_calc_pitch_target(unsigned int rate)
|
||||||
{
|
{
|
||||||
unsigned int pitch_target;
|
unsigned int pitch_target;
|
||||||
@ -251,18 +278,11 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
|
|||||||
const unsigned char *send_routing,
|
const unsigned char *send_routing,
|
||||||
const unsigned char *send_amount)
|
const unsigned char *send_amount)
|
||||||
{
|
{
|
||||||
struct snd_pcm_substream *substream = evoice->epcm->substream;
|
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
|
||||||
unsigned int silent_page;
|
unsigned int silent_page;
|
||||||
int voice;
|
int voice;
|
||||||
unsigned int pitch_target;
|
|
||||||
|
|
||||||
voice = evoice->number;
|
voice = evoice->number;
|
||||||
|
|
||||||
if (emu->card_capabilities->emu_model)
|
|
||||||
pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */
|
|
||||||
else
|
|
||||||
pitch_target = emu10k1_calc_pitch_target(runtime->rate);
|
|
||||||
silent_page = ((unsigned int)emu->silent_page.addr << emu->address_mode) |
|
silent_page = ((unsigned int)emu->silent_page.addr << emu->address_mode) |
|
||||||
(emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
|
(emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
|
||||||
snd_emu10k1_ptr_write_multiple(emu, voice,
|
snd_emu10k1_ptr_write_multiple(emu, voice,
|
||||||
@ -273,7 +293,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
|
|||||||
// Stereo slaves don't need to have the addresses set, but it doesn't hurt
|
// Stereo slaves don't need to have the addresses set, but it doesn't hurt
|
||||||
DSL, end_addr | (send_amount[3] << 24),
|
DSL, end_addr | (send_amount[3] << 24),
|
||||||
PSST, start_addr | (send_amount[2] << 24),
|
PSST, start_addr | (send_amount[2] << 24),
|
||||||
CCCA, emu10k1_select_interprom(pitch_target) |
|
CCCA, emu10k1_select_interprom(evoice->epcm->pitch_target) |
|
||||||
(w_16 ? 0 : CCCA_8BITSELECT),
|
(w_16 ? 0 : CCCA_8BITSELECT),
|
||||||
// Clear filter delay memory
|
// Clear filter delay memory
|
||||||
Z1, 0,
|
Z1, 0,
|
||||||
@ -419,6 +439,13 @@ static int snd_emu10k1_playback_prepare(struct snd_pcm_substream *substream)
|
|||||||
bool w_16 = snd_pcm_format_width(runtime->format) == 16;
|
bool w_16 = snd_pcm_format_width(runtime->format) == 16;
|
||||||
bool stereo = runtime->channels == 2;
|
bool stereo = runtime->channels == 2;
|
||||||
unsigned int start_addr, end_addr;
|
unsigned int start_addr, end_addr;
|
||||||
|
unsigned int rate;
|
||||||
|
|
||||||
|
rate = runtime->rate;
|
||||||
|
if (emu->card_capabilities->emu_model &&
|
||||||
|
emu->emu1010.word_clock == 44100)
|
||||||
|
rate = rate * 480 / 441;
|
||||||
|
epcm->pitch_target = emu10k1_calc_pitch_target(rate);
|
||||||
|
|
||||||
start_addr = epcm->start_addr >> w_16;
|
start_addr = epcm->start_addr >> w_16;
|
||||||
end_addr = start_addr + runtime->period_size;
|
end_addr = start_addr + runtime->period_size;
|
||||||
@ -443,6 +470,8 @@ static int snd_emu10k1_efx_playback_prepare(struct snd_pcm_substream *substream)
|
|||||||
unsigned int extra_size, channel_size;
|
unsigned int extra_size, channel_size;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
epcm->pitch_target = PITCH_48000;
|
||||||
|
|
||||||
start_addr = epcm->start_addr >> 1; // 16-bit voices
|
start_addr = epcm->start_addr >> 1; // 16-bit voices
|
||||||
|
|
||||||
extra_size = runtime->period_size;
|
extra_size = runtime->period_size;
|
||||||
@ -526,12 +555,16 @@ static int snd_emu10k1_capture_prepare(struct snd_pcm_substream *substream)
|
|||||||
epcm->capture_bs_val++;
|
epcm->capture_bs_val++;
|
||||||
}
|
}
|
||||||
if (epcm->type == CAPTURE_AC97ADC) {
|
if (epcm->type == CAPTURE_AC97ADC) {
|
||||||
|
unsigned rate = runtime->rate;
|
||||||
|
if (!(runtime->hw.rates & SNDRV_PCM_RATE_48000))
|
||||||
|
rate = rate * 480 / 441;
|
||||||
|
|
||||||
epcm->capture_cr_val = emu->audigy ? A_ADCCR_LCHANENABLE : ADCCR_LCHANENABLE;
|
epcm->capture_cr_val = emu->audigy ? A_ADCCR_LCHANENABLE : ADCCR_LCHANENABLE;
|
||||||
if (runtime->channels > 1)
|
if (runtime->channels > 1)
|
||||||
epcm->capture_cr_val |= emu->audigy ? A_ADCCR_RCHANENABLE : ADCCR_RCHANENABLE;
|
epcm->capture_cr_val |= emu->audigy ? A_ADCCR_RCHANENABLE : ADCCR_RCHANENABLE;
|
||||||
epcm->capture_cr_val |= emu->audigy ?
|
epcm->capture_cr_val |= emu->audigy ?
|
||||||
snd_emu10k1_audigy_capture_rate_reg(runtime->rate) :
|
snd_emu10k1_audigy_capture_rate_reg(rate) :
|
||||||
snd_emu10k1_capture_rate_reg(runtime->rate);
|
snd_emu10k1_capture_rate_reg(rate);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -670,19 +703,10 @@ static void snd_emu10k1_playback_commit_pitch(struct snd_emu10k1 *emu,
|
|||||||
static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu,
|
static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu,
|
||||||
struct snd_emu10k1_voice *evoice)
|
struct snd_emu10k1_voice *evoice)
|
||||||
{
|
{
|
||||||
struct snd_pcm_substream *substream;
|
unsigned int voice;
|
||||||
struct snd_pcm_runtime *runtime;
|
|
||||||
unsigned int voice, pitch_target;
|
|
||||||
|
|
||||||
substream = evoice->epcm->substream;
|
|
||||||
runtime = substream->runtime;
|
|
||||||
voice = evoice->number;
|
voice = evoice->number;
|
||||||
|
snd_emu10k1_playback_commit_pitch(emu, voice, evoice->epcm->pitch_target << 16);
|
||||||
if (emu->card_capabilities->emu_model)
|
|
||||||
pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */
|
|
||||||
else
|
|
||||||
pitch_target = emu10k1_calc_pitch_target(runtime->rate);
|
|
||||||
snd_emu10k1_playback_commit_pitch(emu, voice, pitch_target << 16);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu,
|
static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu,
|
||||||
@ -1043,11 +1067,9 @@ static const struct snd_pcm_hardware snd_emu10k1_capture_efx =
|
|||||||
SNDRV_PCM_INFO_RESUME |
|
SNDRV_PCM_INFO_RESUME |
|
||||||
SNDRV_PCM_INFO_MMAP_VALID),
|
SNDRV_PCM_INFO_MMAP_VALID),
|
||||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||||
.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
|
.rates = SNDRV_PCM_RATE_48000,
|
||||||
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
|
.rate_min = 48000,
|
||||||
SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
|
.rate_max = 48000,
|
||||||
.rate_min = 44100,
|
|
||||||
.rate_max = 192000,
|
|
||||||
.channels_min = 1,
|
.channels_min = 1,
|
||||||
.channels_max = 16,
|
.channels_max = 16,
|
||||||
.buffer_bytes_max = (64*1024),
|
.buffer_bytes_max = (64*1024),
|
||||||
@ -1144,6 +1166,8 @@ static int snd_emu10k1_efx_playback_open(struct snd_pcm_substream *substream)
|
|||||||
runtime->private_data = epcm;
|
runtime->private_data = epcm;
|
||||||
runtime->private_free = snd_emu10k1_pcm_free_substream;
|
runtime->private_free = snd_emu10k1_pcm_free_substream;
|
||||||
runtime->hw = snd_emu10k1_efx_playback;
|
runtime->hw = snd_emu10k1_efx_playback;
|
||||||
|
if (emu->card_capabilities->emu_model)
|
||||||
|
snd_emu1010_constrain_efx_rate(emu, runtime);
|
||||||
err = snd_emu10k1_playback_set_constraints(runtime);
|
err = snd_emu10k1_playback_set_constraints(runtime);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
kfree(epcm);
|
kfree(epcm);
|
||||||
@ -1185,8 +1209,8 @@ static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream)
|
|||||||
kfree(epcm);
|
kfree(epcm);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (emu->card_capabilities->emu_model && emu->emu1010.clock_source == 0)
|
if (emu->card_capabilities->emu_model)
|
||||||
sample_rate = 44100;
|
sample_rate = emu->emu1010.word_clock;
|
||||||
else
|
else
|
||||||
sample_rate = 48000;
|
sample_rate = 48000;
|
||||||
err = snd_pcm_hw_rule_noresample(runtime, sample_rate);
|
err = snd_pcm_hw_rule_noresample(runtime, sample_rate);
|
||||||
@ -1236,11 +1260,11 @@ static int snd_emu10k1_capture_open(struct snd_pcm_substream *substream)
|
|||||||
runtime->private_data = epcm;
|
runtime->private_data = epcm;
|
||||||
runtime->private_free = snd_emu10k1_pcm_free_substream;
|
runtime->private_free = snd_emu10k1_pcm_free_substream;
|
||||||
runtime->hw = snd_emu10k1_capture;
|
runtime->hw = snd_emu10k1_capture;
|
||||||
|
snd_emu10k1_constrain_capture_rates(emu, runtime);
|
||||||
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
|
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
|
||||||
&hw_constraints_capture_buffer_sizes);
|
&hw_constraints_capture_buffer_sizes);
|
||||||
emu->capture_interrupt = snd_emu10k1_pcm_ac97adc_interrupt;
|
emu->capture_interrupt = snd_emu10k1_pcm_ac97adc_interrupt;
|
||||||
emu->pcm_capture_substream = substream;
|
emu->pcm_capture_substream = substream;
|
||||||
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_capture_rates);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1313,17 +1337,9 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream)
|
|||||||
substream->runtime->private_data = epcm;
|
substream->runtime->private_data = epcm;
|
||||||
substream->runtime->private_free = snd_emu10k1_pcm_free_substream;
|
substream->runtime->private_free = snd_emu10k1_pcm_free_substream;
|
||||||
runtime->hw = snd_emu10k1_capture_efx;
|
runtime->hw = snd_emu10k1_capture_efx;
|
||||||
runtime->hw.rates = SNDRV_PCM_RATE_48000;
|
|
||||||
runtime->hw.rate_min = runtime->hw.rate_max = 48000;
|
|
||||||
if (emu->card_capabilities->emu_model) {
|
if (emu->card_capabilities->emu_model) {
|
||||||
/* TODO
|
snd_emu1010_constrain_efx_rate(emu, runtime);
|
||||||
* SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
|
/*
|
||||||
* SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
|
|
||||||
* SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000
|
|
||||||
* rate_min = 44100,
|
|
||||||
* rate_max = 192000,
|
|
||||||
* Need to add mixer control to fix sample rate
|
|
||||||
*
|
|
||||||
* There are 32 mono channels of 16bits each.
|
* There are 32 mono channels of 16bits each.
|
||||||
* 24bit Audio uses 2x channels over 16bit,
|
* 24bit Audio uses 2x channels over 16bit,
|
||||||
* 96kHz uses 2x channels over 48kHz,
|
* 96kHz uses 2x channels over 48kHz,
|
||||||
@ -1334,30 +1350,12 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream)
|
|||||||
* 1010rev2 and 1616(m) cards have double that,
|
* 1010rev2 and 1616(m) cards have double that,
|
||||||
* but we don't exceed 16 channels anyway.
|
* but we don't exceed 16 channels anyway.
|
||||||
*/
|
*/
|
||||||
#if 1
|
|
||||||
switch (emu->emu1010.clock_source) {
|
|
||||||
case 0:
|
|
||||||
/* For 44.1kHz */
|
|
||||||
runtime->hw.rates = SNDRV_PCM_RATE_44100;
|
|
||||||
runtime->hw.rate_min = runtime->hw.rate_max = 44100;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
/* For 48kHz */
|
|
||||||
runtime->hw.rates = SNDRV_PCM_RATE_48000;
|
|
||||||
runtime->hw.rate_min = runtime->hw.rate_max = 48000;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if 0
|
#if 0
|
||||||
/* For 96kHz */
|
/* For 96kHz */
|
||||||
runtime->hw.rates = SNDRV_PCM_RATE_96000;
|
|
||||||
runtime->hw.rate_min = runtime->hw.rate_max = 96000;
|
|
||||||
runtime->hw.channels_min = runtime->hw.channels_max = 4;
|
runtime->hw.channels_min = runtime->hw.channels_max = 4;
|
||||||
#endif
|
#endif
|
||||||
#if 0
|
#if 0
|
||||||
/* For 192kHz */
|
/* For 192kHz */
|
||||||
runtime->hw.rates = SNDRV_PCM_RATE_192000;
|
|
||||||
runtime->hw.rate_min = runtime->hw.rate_max = 192000;
|
|
||||||
runtime->hw.channels_min = runtime->hw.channels_max = 2;
|
runtime->hw.channels_min = runtime->hw.channels_max = 2;
|
||||||
#endif
|
#endif
|
||||||
runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
|
runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user