mirror of
https://github.com/torvalds/linux.git
synced 2024-11-17 09:31:50 +00:00
[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:
parent
02a5039fc7
commit
e4b6088c8c
@ -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[] = {
|
||||
|
Loading…
Reference in New Issue
Block a user