aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/rme9652
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/rme9652')
-rw-r--r--sound/pci/rme9652/hdsp.c85
1 files changed, 79 insertions, 6 deletions
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 6540037a11e4..4b20f848dba2 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -275,6 +275,11 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
275#define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0) 275#define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0)
276#define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1) 276#define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1)
277#define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0) 277#define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
278/* RME says n = 104857600000000, but in the windows MADI driver, I see:
279 return 104857600000000 / rate; // 100 MHz
280 return 110100480000000 / rate; // 105 MHz
281*/
282#define DDS_NUMERATOR 104857600000000ULL; /* = 2^20 * 10^8 */
278 283
279#define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask) 284#define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask)
280#define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1) 285#define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1)
@@ -1001,11 +1006,7 @@ static void hdsp_set_dds_value(struct hdsp *hdsp, int rate)
1001 else if (rate >= 56000) 1006 else if (rate >= 56000)
1002 rate /= 2; 1007 rate /= 2;
1003 1008
1004 /* RME says n = 104857600000000, but in the windows MADI driver, I see: 1009 n = DDS_NUMERATOR;
1005// return 104857600000000 / rate; // 100 MHz
1006 return 110100480000000 / rate; // 105 MHz
1007 */
1008 n = 104857600000000ULL; /* = 2^20 * 10^8 */
1009 div64_32(&n, rate, &r); 1010 div64_32(&n, rate, &r);
1010 /* n should be less than 2^32 for being written to FREQ register */ 1011 /* n should be less than 2^32 for being written to FREQ register */
1011 snd_assert((n >> 32) == 0); 1012 snd_assert((n >> 32) == 0);
@@ -3085,11 +3086,83 @@ static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct sn
3085 return 0; 3086 return 0;
3086} 3087}
3087 3088
3089#define HDSP_DDS_OFFSET(xname, xindex) \
3090{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3091 .name = xname, \
3092 .index = xindex, \
3093 .info = snd_hdsp_info_dds_offset, \
3094 .get = snd_hdsp_get_dds_offset, \
3095 .put = snd_hdsp_put_dds_offset \
3096}
3097
3098static int hdsp_dds_offset(struct hdsp *hdsp)
3099{
3100 u64 n;
3101 u32 r;
3102 unsigned int dds_value = hdsp->dds_value;
3103 int system_sample_rate = hdsp->system_sample_rate;
3104
3105 n = DDS_NUMERATOR;
3106 /*
3107 * dds_value = n / rate
3108 * rate = n / dds_value
3109 */
3110 div64_32(&n, dds_value, &r);
3111 if (system_sample_rate >= 112000)
3112 n *= 4;
3113 else if (system_sample_rate >= 56000)
3114 n *= 2;
3115 return ((int)n) - system_sample_rate;
3116}
3117
3118static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz)
3119{
3120 int rate = hdsp->system_sample_rate + offset_hz;
3121 hdsp_set_dds_value(hdsp, rate);
3122 return 0;
3123}
3124
3125static int snd_hdsp_info_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3126{
3127 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3128 uinfo->count = 1;
3129 uinfo->value.integer.min = -5000;
3130 uinfo->value.integer.max = 5000;
3131 return 0;
3132}
3133
3134static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3135{
3136 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3137
3138 ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp);
3139 return 0;
3140}
3141
3142static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3143{
3144 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3145 int change;
3146 int val;
3147
3148 if (!snd_hdsp_use_is_exclusive(hdsp))
3149 return -EBUSY;
3150 val = ucontrol->value.enumerated.item[0];
3151 spin_lock_irq(&hdsp->lock);
3152 if (val != hdsp_dds_offset(hdsp))
3153 change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0;
3154 else
3155 change = 0;
3156 spin_unlock_irq(&hdsp->lock);
3157 return change;
3158}
3159
3088static struct snd_kcontrol_new snd_hdsp_9632_controls[] = { 3160static struct snd_kcontrol_new snd_hdsp_9632_controls[] = {
3089HDSP_DA_GAIN("DA Gain", 0), 3161HDSP_DA_GAIN("DA Gain", 0),
3090HDSP_AD_GAIN("AD Gain", 0), 3162HDSP_AD_GAIN("AD Gain", 0),
3091HDSP_PHONE_GAIN("Phones Gain", 0), 3163HDSP_PHONE_GAIN("Phones Gain", 0),
3092HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0) 3164HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0),
3165HDSP_DDS_OFFSET("DDS Sample Rate Offset", 0)
3093}; 3166};
3094 3167
3095static struct snd_kcontrol_new snd_hdsp_controls[] = { 3168static struct snd_kcontrol_new snd_hdsp_controls[] = {