summaryrefslogtreecommitdiff
path: root/sound/pci/emu10k1/io.c
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@gmx.de>2023-06-12 21:13:19 +0200
committerTakashi Iwai <tiwai@suse.de>2023-06-13 07:41:07 +0200
commite73b597e63ebad26d9dee5feb5d47251ed53b8a4 (patch)
tree2d966bcf9b1e5d2317dcb4396383fd7cc0ba62e5 /sound/pci/emu10k1/io.c
parent60985241bfc61c6d6d85a78e0f29c866c546c7f5 (diff)
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>
Diffstat (limited to 'sound/pci/emu10k1/io.c')
-rw-r--r--sound/pci/emu10k1/io.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index e7a44443023a..a0d66ce3ee83 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -357,21 +357,70 @@ u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst)
return (hi << 8) | lo;
}
+int snd_emu1010_get_raw_rate(struct snd_emu10k1 *emu, u8 src)
+{
+ u32 reg_lo, reg_hi, value, value2;
+
+ switch (src) {
+ case EMU_HANA_WCLOCK_HANA_SPDIF_IN:
+ snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &value);
+ if (value & EMU_HANA_SPDIF_MODE_RX_INVALID)
+ return 0;
+ reg_lo = EMU_HANA_WC_SPDIF_LO;
+ reg_hi = EMU_HANA_WC_SPDIF_HI;
+ break;
+ case EMU_HANA_WCLOCK_HANA_ADAT_IN:
+ reg_lo = EMU_HANA_WC_ADAT_LO;
+ reg_hi = EMU_HANA_WC_ADAT_HI;
+ break;
+ case EMU_HANA_WCLOCK_SYNC_BNC:
+ reg_lo = EMU_HANA_WC_BNC_LO;
+ reg_hi = EMU_HANA_WC_BNC_HI;
+ break;
+ case EMU_HANA_WCLOCK_2ND_HANA:
+ reg_lo = EMU_HANA2_WC_SPDIF_LO;
+ reg_hi = EMU_HANA2_WC_SPDIF_HI;
+ break;
+ default:
+ return 0;
+ }
+ snd_emu1010_fpga_read(emu, reg_hi, &value);
+ snd_emu1010_fpga_read(emu, reg_lo, &value2);
+ // FIXME: The /4 is valid for 0404b, but contradicts all other info.
+ return 0x1770000 / 4 / (((value << 5) | value2) + 1);
+}
+
void snd_emu1010_update_clock(struct snd_emu10k1 *emu)
{
+ int clock;
u32 leds;
switch (emu->emu1010.wclock) {
case EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X:
+ clock = 44100;
leds = EMU_HANA_DOCK_LEDS_2_44K;
break;
case EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X:
+ clock = 48000;
leds = EMU_HANA_DOCK_LEDS_2_48K;
break;
default:
- leds = EMU_HANA_DOCK_LEDS_2_EXT;
+ clock = snd_emu1010_get_raw_rate(
+ emu, emu->emu1010.wclock & EMU_HANA_WCLOCK_SRC_MASK);
+ // The raw rate reading is rather coarse (it cannot accurately
+ // represent 44.1 kHz) and fluctuates slightly. Luckily, the
+ // clock comes from digital inputs, which use standardized rates.
+ // So we round to the closest standard rate and ignore discrepancies.
+ if (clock < 46000) {
+ clock = 44100;
+ leds = EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_44K;
+ } else {
+ clock = 48000;
+ leds = EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_48K;
+ }
break;
}
+ emu->emu1010.word_clock = clock;
// FIXME: this should probably represent the AND of all currently
// used sources' lock status. But we don't know how to get that ...