[ALSA] hdsp - Add support for fine tuning of sample rate support to HDSP 9632

Add 'DDS Sample Rate Offset' control. Allows values in Hz from -5000 to +5000.
The value is added to the nominal sample rate and written to the DDS register.

Signed-off-by: Julian Cable <julian_cable@yahoo.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
This commit is contained in:
Julian Cable 2007-03-19 11:44:40 +01:00 committed by Jaroslav Kysela
parent 02a5039fc7
commit e4b6088c8c
1 changed files with 79 additions and 6 deletions

View File

@ -275,6 +275,11 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
#define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0)
#define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1)
#define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
/* RME says n = 104857600000000, but in the windows MADI driver, I see:
return 104857600000000 / rate; // 100 MHz
return 110100480000000 / rate; // 105 MHz
*/
#define DDS_NUMERATOR 104857600000000ULL; /* = 2^20 * 10^8 */
#define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask)
#define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1)
@ -1001,11 +1006,7 @@ static void hdsp_set_dds_value(struct hdsp *hdsp, int rate)
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 */
n = DDS_NUMERATOR;
div64_32(&n, rate, &r);
/* n should be less than 2^32 for being written to FREQ register */
snd_assert((n >> 32) == 0);
@ -3085,11 +3086,83 @@ static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct sn
return 0;
}
#define HDSP_DDS_OFFSET(xname, xindex) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = xindex, \
.info = snd_hdsp_info_dds_offset, \
.get = snd_hdsp_get_dds_offset, \
.put = snd_hdsp_put_dds_offset \
}
static int hdsp_dds_offset(struct hdsp *hdsp)
{
u64 n;
u32 r;
unsigned int dds_value = hdsp->dds_value;
int system_sample_rate = hdsp->system_sample_rate;
n = DDS_NUMERATOR;
/*
* dds_value = n / rate
* rate = n / dds_value
*/
div64_32(&n, dds_value, &r);
if (system_sample_rate >= 112000)
n *= 4;
else if (system_sample_rate >= 56000)
n *= 2;
return ((int)n) - system_sample_rate;
}
static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz)
{
int rate = hdsp->system_sample_rate + offset_hz;
hdsp_set_dds_value(hdsp, rate);
return 0;
}
static int snd_hdsp_info_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
uinfo->value.integer.min = -5000;
uinfo->value.integer.max = 5000;
return 0;
}
static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp);
return 0;
}
static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int val;
if (!snd_hdsp_use_is_exclusive(hdsp))
return -EBUSY;
val = ucontrol->value.enumerated.item[0];
spin_lock_irq(&hdsp->lock);
if (val != hdsp_dds_offset(hdsp))
change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0;
else
change = 0;
spin_unlock_irq(&hdsp->lock);
return change;
}
static struct snd_kcontrol_new snd_hdsp_9632_controls[] = {
HDSP_DA_GAIN("DA Gain", 0),
HDSP_AD_GAIN("AD Gain", 0),
HDSP_PHONE_GAIN("Phones Gain", 0),
HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0)
HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0),
HDSP_DDS_OFFSET("DDS Sample Rate Offset", 0)
};
static struct snd_kcontrol_new snd_hdsp_controls[] = {