diff options
author | Remy Bruno <remy.bruno@trinnov.com> | 2006-10-17 10:41:56 (GMT) |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2007-02-09 08:01:04 (GMT) |
commit | d7923b2a816625dc4208d89471da6bdcab188cdb (patch) | |
tree | c7d9732deb8280d479c850ecce440be8e9dbabd2 /sound/pci | |
parent | ccc656ce5f6627032bd44e660071bb71e65a231a (diff) | |
download | linux-fsl-qoriq-d7923b2a816625dc4208d89471da6bdcab188cdb.tar.xz |
[ALSA] hdsp - Add DDS register support for RME9632 rev >= 152
Add DDS register support for RME9632 rev >= 152.
This register sets the sample rate for these cards and is required
in addition to the standard control register. It corresponds to a
quartz divisor.
Signed-off-by: Remy Bruno <remy.bruno@trinnov.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/rme9652/hdsp.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 849ffe4..89b3c7f 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -80,6 +80,7 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," /* Write registers. These are defined as byte-offsets from the iobase value. */ #define HDSP_resetPointer 0 +#define HDSP_freqReg 0 #define HDSP_outputBufferAddress 32 #define HDSP_inputBufferAddress 36 #define HDSP_controlRegister 64 @@ -469,6 +470,7 @@ struct hdsp { struct pci_dev *pci; struct snd_kcontrol *spdif_ctl; unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE]; + unsigned int dds_value; /* last value written to freq register */ }; /* These tables map the ALSA channels 1..N to the channels that we @@ -940,6 +942,11 @@ static snd_pcm_uframes_t hdsp_hw_pointer(struct hdsp *hdsp) static void hdsp_reset_hw_pointer(struct hdsp *hdsp) { hdsp_write (hdsp, HDSP_resetPointer, 0); + if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152) + /* HDSP_resetPointer = HDSP_freqReg, which is strange and + * requires (?) to write again DDS value after a reset pointer + * (at least, it works like this) */ + hdsp_write (hdsp, HDSP_freqReg, hdsp->dds_value); } static void hdsp_start_audio(struct hdsp *s) @@ -984,6 +991,30 @@ static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames) return 0; } +static void hdsp_set_dds_value(struct hdsp *hdsp, int rate) +{ + u64 n; + u32 r; + + if (rate >= 112000) + rate /= 4; + else if (rate >= 56000) + rate /= 2; + + /* RME says n = 104857600000000, but in the windows MADI driver, I see: +// return 104857600000000 / rate; // 100 MHz + return 110100480000000 / rate; // 105 MHz + */ + n = 104857600000000ULL; /* = 2^20 * 10^8 */ + div64_32(&n, rate, &r); + /* n should be less than 2^32 for being written to FREQ register */ + snd_assert((n >> 32) == 0); + /* HDSP_freqReg and HDSP_resetPointer are the same, so keep the DDS + value to write it after a reset */ + hdsp->dds_value = n; + hdsp_write(hdsp, HDSP_freqReg, hdsp->dds_value); +} + static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) { int reject_if_open = 0; @@ -1092,6 +1123,10 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) hdsp->control_register |= rate_bits; hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); + /* For HDSP9632 rev 152, need to set DDS value in FREQ register */ + if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152) + hdsp_set_dds_value(hdsp, rate); + if (rate >= 128000) { hdsp->channel_map = channel_map_H9632_qs; } else if (rate > 48000) { @@ -4945,6 +4980,7 @@ static int __devinit snd_hdsp_create(struct snd_card *card, hdsp->irq = pci->irq; hdsp->precise_ptr = 0; hdsp->use_midi_tasklet = 1; + hdsp->dds_value = 0; if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) return err; |