diff options
Diffstat (limited to 'sound/pci/rme9652')
-rw-r--r-- | sound/pci/rme9652/hdsp.c | 85 |
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 | |||
3098 | static 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 | |||
3118 | static 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 | |||
3125 | static 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 | |||
3134 | static 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 | |||
3142 | static 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 | |||
3088 | static struct snd_kcontrol_new snd_hdsp_9632_controls[] = { | 3160 | static struct snd_kcontrol_new snd_hdsp_9632_controls[] = { |
3089 | HDSP_DA_GAIN("DA Gain", 0), | 3161 | HDSP_DA_GAIN("DA Gain", 0), |
3090 | HDSP_AD_GAIN("AD Gain", 0), | 3162 | HDSP_AD_GAIN("AD Gain", 0), |
3091 | HDSP_PHONE_GAIN("Phones Gain", 0), | 3163 | HDSP_PHONE_GAIN("Phones Gain", 0), |
3092 | HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0) | 3164 | HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0), |
3165 | HDSP_DDS_OFFSET("DDS Sample Rate Offset", 0) | ||
3093 | }; | 3166 | }; |
3094 | 3167 | ||
3095 | static struct snd_kcontrol_new snd_hdsp_controls[] = { | 3168 | static struct snd_kcontrol_new snd_hdsp_controls[] = { |