Skip to content

Commit e73b597

Browse files
ossilatortiwai
authored andcommitted
ALSA: emu10k1: query rate of external clock sources on E-MU cards
The value isn't used yet; the subsequent commits will do that. This ignores the existence of rates above 48 kHz, which is fine, as the hardware will just switch to the fallback clock source when fed with a rate which is incompatible with the base clock multiplier, which currently is always x1. The sample rate display in /proc spdif-in is adjusted to reflect our understanding of the input rates. This is tested only with an 0404b card without sync card, so there is a lot of room for improvement. Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> Link: https://lore.kernel.org/r/20230612191325.1315854-4-oswald.buddenhagen@gmx.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent 6098524 commit e73b597

3 files changed

Lines changed: 78 additions & 21 deletions

File tree

include/sound/emu10k1.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,9 @@ SUB_REG_NC(A_EHC, A_I2S_CAPTURE_RATE, 0x00000e00) /* This sets the capture PCM
11101110
#define EMU_DOCK_BOARD_ID0 0x00 /* ID bit 0 */
11111111
#define EMU_DOCK_BOARD_ID1 0x03 /* ID bit 1 */
11121112

1113+
// The actual code disagrees about the bit width of the registers -
1114+
// the formula used is freq = 0x1770000 / (((X_HI << 5) | X_LO) + 1)
1115+
11131116
#define EMU_HANA_WC_SPDIF_HI 0x28 /* 0xxxxxx 6 bit SPDIF IN Word clock, upper 6 bits */
11141117
#define EMU_HANA_WC_SPDIF_LO 0x29 /* 0xxxxxx 6 bit SPDIF IN Word clock, lower 6 bits */
11151118

@@ -1669,6 +1672,7 @@ struct snd_emu1010 {
16691672
unsigned int adc_pads; /* bit mask */
16701673
unsigned int dac_pads; /* bit mask */
16711674
unsigned int wclock; /* Cached register value */
1675+
unsigned int word_clock; /* Cached effective value */
16721676
unsigned int clock_source;
16731677
unsigned int clock_fallback;
16741678
unsigned int optical_in; /* 0:SPDIF, 1:ADAT */
@@ -1825,6 +1829,7 @@ void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
18251829
void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value);
18261830
void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src);
18271831
u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst);
1832+
int snd_emu1010_get_raw_rate(struct snd_emu10k1 *emu, u8 src);
18281833
void snd_emu1010_update_clock(struct snd_emu10k1 *emu);
18291834
unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc);
18301835
void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb);

sound/pci/emu10k1/emuproc.c

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -168,29 +168,32 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
168168
struct snd_emu10k1 *emu = entry->private_data;
169169
u32 value;
170170
u32 value2;
171-
u32 rate;
172171

173172
if (emu->card_capabilities->emu_model) {
174-
if (!emu->card_capabilities->no_adat) {
175-
snd_emu1010_fpga_read(emu, 0x38, &value);
176-
if ((value & 0x1) == 0) {
177-
snd_emu1010_fpga_read(emu, 0x2a, &value);
178-
snd_emu1010_fpga_read(emu, 0x2b, &value2);
179-
rate = 0x1770000 / (((value << 5) | value2)+1);
180-
snd_iprintf(buffer, "ADAT Locked : %u\n", rate);
181-
} else {
182-
snd_iprintf(buffer, "ADAT Unlocked\n");
183-
}
184-
}
185-
snd_emu1010_fpga_read(emu, 0x20, &value);
186-
if ((value & 0x4) == 0) {
187-
snd_emu1010_fpga_read(emu, 0x28, &value);
188-
snd_emu1010_fpga_read(emu, 0x29, &value2);
189-
rate = 0x1770000 / (((value << 5) | value2)+1);
190-
snd_iprintf(buffer, "SPDIF Locked : %d\n", rate);
191-
} else {
192-
snd_iprintf(buffer, "SPDIF Unlocked\n");
173+
// This represents the S/PDIF lock status on 0404b, which is
174+
// kinda weird and unhelpful, because monitoring it via IRQ is
175+
// impractical (one gets an IRQ flood as long as it is desynced).
176+
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &value);
177+
snd_iprintf(buffer, "Lock status 1: %#x\n", value & 0x10);
178+
179+
// Bit 0x1 in LO being 0 is supposedly for ADAT lock.
180+
// The registers are always all zero on 0404b.
181+
snd_emu1010_fpga_read(emu, EMU_HANA_LOCK_STS_LO, &value);
182+
snd_emu1010_fpga_read(emu, EMU_HANA_LOCK_STS_HI, &value2);
183+
snd_iprintf(buffer, "Lock status 2: %#x %#x\n", value, value2);
184+
185+
snd_iprintf(buffer, "S/PDIF rate: %dHz\n",
186+
snd_emu1010_get_raw_rate(emu, EMU_HANA_WCLOCK_HANA_SPDIF_IN));
187+
if (emu->card_capabilities->emu_model != EMU_MODEL_EMU0404) {
188+
snd_iprintf(buffer, "ADAT rate: %dHz\n",
189+
snd_emu1010_get_raw_rate(emu, EMU_HANA_WCLOCK_HANA_ADAT_IN));
190+
snd_iprintf(buffer, "Dock rate: %dHz\n",
191+
snd_emu1010_get_raw_rate(emu, EMU_HANA_WCLOCK_2ND_HANA));
193192
}
193+
if (emu->card_capabilities->emu_model == EMU_MODEL_EMU0404 ||
194+
emu->card_capabilities->emu_model == EMU_MODEL_EMU1010)
195+
snd_iprintf(buffer, "BNC rate: %dHz\n",
196+
snd_emu1010_get_raw_rate(emu, EMU_HANA_WCLOCK_SYNC_BNC));
194197
} else {
195198
snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS);
196199
snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS);

sound/pci/emu10k1/io.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,21 +357,70 @@ u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst)
357357
return (hi << 8) | lo;
358358
}
359359

360+
int snd_emu1010_get_raw_rate(struct snd_emu10k1 *emu, u8 src)
361+
{
362+
u32 reg_lo, reg_hi, value, value2;
363+
364+
switch (src) {
365+
case EMU_HANA_WCLOCK_HANA_SPDIF_IN:
366+
snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &value);
367+
if (value & EMU_HANA_SPDIF_MODE_RX_INVALID)
368+
return 0;
369+
reg_lo = EMU_HANA_WC_SPDIF_LO;
370+
reg_hi = EMU_HANA_WC_SPDIF_HI;
371+
break;
372+
case EMU_HANA_WCLOCK_HANA_ADAT_IN:
373+
reg_lo = EMU_HANA_WC_ADAT_LO;
374+
reg_hi = EMU_HANA_WC_ADAT_HI;
375+
break;
376+
case EMU_HANA_WCLOCK_SYNC_BNC:
377+
reg_lo = EMU_HANA_WC_BNC_LO;
378+
reg_hi = EMU_HANA_WC_BNC_HI;
379+
break;
380+
case EMU_HANA_WCLOCK_2ND_HANA:
381+
reg_lo = EMU_HANA2_WC_SPDIF_LO;
382+
reg_hi = EMU_HANA2_WC_SPDIF_HI;
383+
break;
384+
default:
385+
return 0;
386+
}
387+
snd_emu1010_fpga_read(emu, reg_hi, &value);
388+
snd_emu1010_fpga_read(emu, reg_lo, &value2);
389+
// FIXME: The /4 is valid for 0404b, but contradicts all other info.
390+
return 0x1770000 / 4 / (((value << 5) | value2) + 1);
391+
}
392+
360393
void snd_emu1010_update_clock(struct snd_emu10k1 *emu)
361394
{
395+
int clock;
362396
u32 leds;
363397

364398
switch (emu->emu1010.wclock) {
365399
case EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X:
400+
clock = 44100;
366401
leds = EMU_HANA_DOCK_LEDS_2_44K;
367402
break;
368403
case EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X:
404+
clock = 48000;
369405
leds = EMU_HANA_DOCK_LEDS_2_48K;
370406
break;
371407
default:
372-
leds = EMU_HANA_DOCK_LEDS_2_EXT;
408+
clock = snd_emu1010_get_raw_rate(
409+
emu, emu->emu1010.wclock & EMU_HANA_WCLOCK_SRC_MASK);
410+
// The raw rate reading is rather coarse (it cannot accurately
411+
// represent 44.1 kHz) and fluctuates slightly. Luckily, the
412+
// clock comes from digital inputs, which use standardized rates.
413+
// So we round to the closest standard rate and ignore discrepancies.
414+
if (clock < 46000) {
415+
clock = 44100;
416+
leds = EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_44K;
417+
} else {
418+
clock = 48000;
419+
leds = EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_48K;
420+
}
373421
break;
374422
}
423+
emu->emu1010.word_clock = clock;
375424

376425
// FIXME: this should probably represent the AND of all currently
377426
// used sources' lock status. But we don't know how to get that ...

0 commit comments

Comments
 (0)