Skip to content

Commit

Permalink
[ALSA] hdsp - Add support for fine tuning of sample rate support to H…
Browse files Browse the repository at this point in the history
…DSP 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>
  • Loading branch information
Julian Cable authored and Jaroslav Kysela committed May 11, 2007
1 parent 02a5039 commit e4b6088
Showing 1 changed file with 79 additions and 6 deletions.
85 changes: 79 additions & 6 deletions sound/pci/rme9652/hdsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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[] = {
Expand Down

0 comments on commit e4b6088

Please sign in to comment.