Skip to content

Commit 19b89d1

Browse files
ossilatortiwai
authored andcommitted
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>
1 parent e73b597 commit 19b89d1

2 files changed

Lines changed: 56 additions & 57 deletions

File tree

include/sound/emu10k1.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1495,6 +1495,7 @@ struct snd_emu10k1_pcm {
14951495
unsigned short first_ptr;
14961496
snd_pcm_uframes_t resume_pos;
14971497
struct snd_util_memblk *memblk;
1498+
unsigned int pitch_target;
14981499
unsigned int start_addr;
14991500
unsigned int ccca_start_addr;
15001501
unsigned int capture_ipr; /* interrupt acknowledge mask */

sound/pci/emu10k1/emupcm.c

Lines changed: 55 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,33 @@ static unsigned int snd_emu10k1_audigy_capture_rate_reg(unsigned int rate)
195195
}
196196
}
197197

198+
static void snd_emu10k1_constrain_capture_rates(struct snd_emu10k1 *emu,
199+
struct snd_pcm_runtime *runtime)
200+
{
201+
if (emu->card_capabilities->emu_model &&
202+
emu->emu1010.word_clock == 44100) {
203+
// This also sets the rate constraint by deleting SNDRV_PCM_RATE_KNOT
204+
runtime->hw.rates = SNDRV_PCM_RATE_11025 | \
205+
SNDRV_PCM_RATE_22050 | \
206+
SNDRV_PCM_RATE_44100;
207+
runtime->hw.rate_min = 11025;
208+
runtime->hw.rate_max = 44100;
209+
return;
210+
}
211+
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
212+
&hw_constraints_capture_rates);
213+
}
214+
215+
static void snd_emu1010_constrain_efx_rate(struct snd_emu10k1 *emu,
216+
struct snd_pcm_runtime *runtime)
217+
{
218+
int rate;
219+
220+
rate = emu->emu1010.word_clock;
221+
runtime->hw.rate_min = runtime->hw.rate_max = rate;
222+
runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
223+
}
224+
198225
static unsigned int emu10k1_calc_pitch_target(unsigned int rate)
199226
{
200227
unsigned int pitch_target;
@@ -251,18 +278,11 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
251278
const unsigned char *send_routing,
252279
const unsigned char *send_amount)
253280
{
254-
struct snd_pcm_substream *substream = evoice->epcm->substream;
255-
struct snd_pcm_runtime *runtime = substream->runtime;
256281
unsigned int silent_page;
257282
int voice;
258-
unsigned int pitch_target;
259283

260284
voice = evoice->number;
261285

262-
if (emu->card_capabilities->emu_model)
263-
pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */
264-
else
265-
pitch_target = emu10k1_calc_pitch_target(runtime->rate);
266286
silent_page = ((unsigned int)emu->silent_page.addr << emu->address_mode) |
267287
(emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
268288
snd_emu10k1_ptr_write_multiple(emu, voice,
@@ -273,7 +293,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
273293
// Stereo slaves don't need to have the addresses set, but it doesn't hurt
274294
DSL, end_addr | (send_amount[3] << 24),
275295
PSST, start_addr | (send_amount[2] << 24),
276-
CCCA, emu10k1_select_interprom(pitch_target) |
296+
CCCA, emu10k1_select_interprom(evoice->epcm->pitch_target) |
277297
(w_16 ? 0 : CCCA_8BITSELECT),
278298
// Clear filter delay memory
279299
Z1, 0,
@@ -419,6 +439,13 @@ static int snd_emu10k1_playback_prepare(struct snd_pcm_substream *substream)
419439
bool w_16 = snd_pcm_format_width(runtime->format) == 16;
420440
bool stereo = runtime->channels == 2;
421441
unsigned int start_addr, end_addr;
442+
unsigned int rate;
443+
444+
rate = runtime->rate;
445+
if (emu->card_capabilities->emu_model &&
446+
emu->emu1010.word_clock == 44100)
447+
rate = rate * 480 / 441;
448+
epcm->pitch_target = emu10k1_calc_pitch_target(rate);
422449

423450
start_addr = epcm->start_addr >> w_16;
424451
end_addr = start_addr + runtime->period_size;
@@ -443,6 +470,8 @@ static int snd_emu10k1_efx_playback_prepare(struct snd_pcm_substream *substream)
443470
unsigned int extra_size, channel_size;
444471
unsigned int i;
445472

473+
epcm->pitch_target = PITCH_48000;
474+
446475
start_addr = epcm->start_addr >> 1; // 16-bit voices
447476

448477
extra_size = runtime->period_size;
@@ -526,12 +555,16 @@ static int snd_emu10k1_capture_prepare(struct snd_pcm_substream *substream)
526555
epcm->capture_bs_val++;
527556
}
528557
if (epcm->type == CAPTURE_AC97ADC) {
558+
unsigned rate = runtime->rate;
559+
if (!(runtime->hw.rates & SNDRV_PCM_RATE_48000))
560+
rate = rate * 480 / 441;
561+
529562
epcm->capture_cr_val = emu->audigy ? A_ADCCR_LCHANENABLE : ADCCR_LCHANENABLE;
530563
if (runtime->channels > 1)
531564
epcm->capture_cr_val |= emu->audigy ? A_ADCCR_RCHANENABLE : ADCCR_RCHANENABLE;
532565
epcm->capture_cr_val |= emu->audigy ?
533-
snd_emu10k1_audigy_capture_rate_reg(runtime->rate) :
534-
snd_emu10k1_capture_rate_reg(runtime->rate);
566+
snd_emu10k1_audigy_capture_rate_reg(rate) :
567+
snd_emu10k1_capture_rate_reg(rate);
535568
}
536569
return 0;
537570
}
@@ -670,19 +703,10 @@ static void snd_emu10k1_playback_commit_pitch(struct snd_emu10k1 *emu,
670703
static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu,
671704
struct snd_emu10k1_voice *evoice)
672705
{
673-
struct snd_pcm_substream *substream;
674-
struct snd_pcm_runtime *runtime;
675-
unsigned int voice, pitch_target;
706+
unsigned int voice;
676707

677-
substream = evoice->epcm->substream;
678-
runtime = substream->runtime;
679708
voice = evoice->number;
680-
681-
if (emu->card_capabilities->emu_model)
682-
pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */
683-
else
684-
pitch_target = emu10k1_calc_pitch_target(runtime->rate);
685-
snd_emu10k1_playback_commit_pitch(emu, voice, pitch_target << 16);
709+
snd_emu10k1_playback_commit_pitch(emu, voice, evoice->epcm->pitch_target << 16);
686710
}
687711

688712
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 =
10431067
SNDRV_PCM_INFO_RESUME |
10441068
SNDRV_PCM_INFO_MMAP_VALID),
10451069
.formats = SNDRV_PCM_FMTBIT_S16_LE,
1046-
.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
1047-
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
1048-
SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
1049-
.rate_min = 44100,
1050-
.rate_max = 192000,
1070+
.rates = SNDRV_PCM_RATE_48000,
1071+
.rate_min = 48000,
1072+
.rate_max = 48000,
10511073
.channels_min = 1,
10521074
.channels_max = 16,
10531075
.buffer_bytes_max = (64*1024),
@@ -1144,6 +1166,8 @@ static int snd_emu10k1_efx_playback_open(struct snd_pcm_substream *substream)
11441166
runtime->private_data = epcm;
11451167
runtime->private_free = snd_emu10k1_pcm_free_substream;
11461168
runtime->hw = snd_emu10k1_efx_playback;
1169+
if (emu->card_capabilities->emu_model)
1170+
snd_emu1010_constrain_efx_rate(emu, runtime);
11471171
err = snd_emu10k1_playback_set_constraints(runtime);
11481172
if (err < 0) {
11491173
kfree(epcm);
@@ -1185,8 +1209,8 @@ static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream)
11851209
kfree(epcm);
11861210
return err;
11871211
}
1188-
if (emu->card_capabilities->emu_model && emu->emu1010.clock_source == 0)
1189-
sample_rate = 44100;
1212+
if (emu->card_capabilities->emu_model)
1213+
sample_rate = emu->emu1010.word_clock;
11901214
else
11911215
sample_rate = 48000;
11921216
err = snd_pcm_hw_rule_noresample(runtime, sample_rate);
@@ -1236,11 +1260,11 @@ static int snd_emu10k1_capture_open(struct snd_pcm_substream *substream)
12361260
runtime->private_data = epcm;
12371261
runtime->private_free = snd_emu10k1_pcm_free_substream;
12381262
runtime->hw = snd_emu10k1_capture;
1263+
snd_emu10k1_constrain_capture_rates(emu, runtime);
12391264
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
12401265
&hw_constraints_capture_buffer_sizes);
12411266
emu->capture_interrupt = snd_emu10k1_pcm_ac97adc_interrupt;
12421267
emu->pcm_capture_substream = substream;
1243-
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_capture_rates);
12441268
return 0;
12451269
}
12461270

@@ -1313,17 +1337,9 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream)
13131337
substream->runtime->private_data = epcm;
13141338
substream->runtime->private_free = snd_emu10k1_pcm_free_substream;
13151339
runtime->hw = snd_emu10k1_capture_efx;
1316-
runtime->hw.rates = SNDRV_PCM_RATE_48000;
1317-
runtime->hw.rate_min = runtime->hw.rate_max = 48000;
13181340
if (emu->card_capabilities->emu_model) {
1319-
/* TODO
1320-
* SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
1321-
* SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
1322-
* SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000
1323-
* rate_min = 44100,
1324-
* rate_max = 192000,
1325-
* Need to add mixer control to fix sample rate
1326-
*
1341+
snd_emu1010_constrain_efx_rate(emu, runtime);
1342+
/*
13271343
* There are 32 mono channels of 16bits each.
13281344
* 24bit Audio uses 2x channels over 16bit,
13291345
* 96kHz uses 2x channels over 48kHz,
@@ -1334,30 +1350,12 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream)
13341350
* 1010rev2 and 1616(m) cards have double that,
13351351
* but we don't exceed 16 channels anyway.
13361352
*/
1337-
#if 1
1338-
switch (emu->emu1010.clock_source) {
1339-
case 0:
1340-
/* For 44.1kHz */
1341-
runtime->hw.rates = SNDRV_PCM_RATE_44100;
1342-
runtime->hw.rate_min = runtime->hw.rate_max = 44100;
1343-
break;
1344-
case 1:
1345-
/* For 48kHz */
1346-
runtime->hw.rates = SNDRV_PCM_RATE_48000;
1347-
runtime->hw.rate_min = runtime->hw.rate_max = 48000;
1348-
break;
1349-
}
1350-
#endif
13511353
#if 0
13521354
/* For 96kHz */
1353-
runtime->hw.rates = SNDRV_PCM_RATE_96000;
1354-
runtime->hw.rate_min = runtime->hw.rate_max = 96000;
13551355
runtime->hw.channels_min = runtime->hw.channels_max = 4;
13561356
#endif
13571357
#if 0
13581358
/* For 192kHz */
1359-
runtime->hw.rates = SNDRV_PCM_RATE_192000;
1360-
runtime->hw.rate_min = runtime->hw.rate_max = 192000;
13611359
runtime->hw.channels_min = runtime->hw.channels_max = 2;
13621360
#endif
13631361
runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;

0 commit comments

Comments
 (0)