diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-11 15:58:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-11 15:58:37 -0400 |
commit | 0a3fd051c7036ef71b58863f8e5da7c3dabd9d3f (patch) | |
tree | 43388a81494ded94008afff66777f9f6e8cb5484 /sound/pci/rme9652/hdsp.c | |
parent | 57a44415beee38d1afcd8e1b5fad66f3414d2dac (diff) | |
parent | c911d1e16dfc1f0338bbc245ff724322c0113395 (diff) |
Merge branch 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa
* 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa: (122 commits)
[ALSA] version 1.0.14rc4
[ALSA] Add speaker pin sequencing to hda_codec.c:snd_hda_parse_pin_def_config()
[ALSA] hda-codec - Add ALC861VD Lenovo support
[ALSA] hda-codec - Fix connection list in generic parser
[ALSA] usb-audio: work around wrong wMaxPacketSize on ESI M4U
[ALSA] usb-audio: work around broken M-Audio MidiSport Uno firmware
[ALSA] usb-audio: explicitly match Logitech QuickCam
[ALSA] hda-codec - Fix a typo
[ALSA] hda-codec - Fix ALC880 uniwill auto-mutes
[ALSA] hda-codec - Fix AD1988 SPDIF playback route control
[ALSA] wm8750 typo fix
[ALSA] wavefront: only declare isapnp on CONFIG_PNP
[ALSA] hda-codec - bug fixes for stac92xx HDA codecs.
[ALSA] add MODULE_FIRMWARE entries
[ALSA] do not depend on FW_LOADER when internal firmware images are used
[ALSA] hda-codec - Fix resume of STAC92xx codecs
[ALSA] usbaudio - Revert the minimal period size fix patch
[ALSA] hda-codec - Add support for new HP DV series laptops
[ALSA] usb-audio - Fix the minimum period size per transfer mode
[ALSA] sound/pcmcia/vx/vxpocket.c: fix an if() condition
...
Diffstat (limited to 'sound/pci/rme9652/hdsp.c')
-rw-r--r-- | sound/pci/rme9652/hdsp.c | 99 |
1 files changed, 87 insertions, 12 deletions
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 89b3c7ff5037..3b3ef657f73e 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -60,6 +60,12 @@ MODULE_LICENSE("GPL"); | |||
60 | MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," | 60 | MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," |
61 | "{RME HDSP-9652}," | 61 | "{RME HDSP-9652}," |
62 | "{RME HDSP-9632}}"); | 62 | "{RME HDSP-9632}}"); |
63 | #ifdef HDSP_FW_LOADER | ||
64 | MODULE_FIRMWARE("multiface_firmware.bin"); | ||
65 | MODULE_FIRMWARE("multiface_firmware_rev11.bin"); | ||
66 | MODULE_FIRMWARE("digiface_firmware.bin"); | ||
67 | MODULE_FIRMWARE("digiface_firmware_rev11.bin"); | ||
68 | #endif | ||
63 | 69 | ||
64 | #define HDSP_MAX_CHANNELS 26 | 70 | #define HDSP_MAX_CHANNELS 26 |
65 | #define HDSP_MAX_DS_CHANNELS 14 | 71 | #define HDSP_MAX_DS_CHANNELS 14 |
@@ -275,6 +281,11 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," | |||
275 | #define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0) | 281 | #define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0) |
276 | #define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1) | 282 | #define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1) |
277 | #define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0) | 283 | #define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0) |
284 | /* RME says n = 104857600000000, but in the windows MADI driver, I see: | ||
285 | return 104857600000000 / rate; // 100 MHz | ||
286 | return 110100480000000 / rate; // 105 MHz | ||
287 | */ | ||
288 | #define DDS_NUMERATOR 104857600000000ULL; /* = 2^20 * 10^8 */ | ||
278 | 289 | ||
279 | #define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask) | 290 | #define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask) |
280 | #define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1) | 291 | #define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1) |
@@ -1001,11 +1012,7 @@ static void hdsp_set_dds_value(struct hdsp *hdsp, int rate) | |||
1001 | else if (rate >= 56000) | 1012 | else if (rate >= 56000) |
1002 | rate /= 2; | 1013 | rate /= 2; |
1003 | 1014 | ||
1004 | /* RME says n = 104857600000000, but in the windows MADI driver, I see: | 1015 | 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); | 1016 | div64_32(&n, rate, &r); |
1010 | /* n should be less than 2^32 for being written to FREQ register */ | 1017 | /* n should be less than 2^32 for being written to FREQ register */ |
1011 | snd_assert((n >> 32) == 0); | 1018 | snd_assert((n >> 32) == 0); |
@@ -3085,11 +3092,83 @@ static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct sn | |||
3085 | return 0; | 3092 | return 0; |
3086 | } | 3093 | } |
3087 | 3094 | ||
3095 | #define HDSP_DDS_OFFSET(xname, xindex) \ | ||
3096 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
3097 | .name = xname, \ | ||
3098 | .index = xindex, \ | ||
3099 | .info = snd_hdsp_info_dds_offset, \ | ||
3100 | .get = snd_hdsp_get_dds_offset, \ | ||
3101 | .put = snd_hdsp_put_dds_offset \ | ||
3102 | } | ||
3103 | |||
3104 | static int hdsp_dds_offset(struct hdsp *hdsp) | ||
3105 | { | ||
3106 | u64 n; | ||
3107 | u32 r; | ||
3108 | unsigned int dds_value = hdsp->dds_value; | ||
3109 | int system_sample_rate = hdsp->system_sample_rate; | ||
3110 | |||
3111 | n = DDS_NUMERATOR; | ||
3112 | /* | ||
3113 | * dds_value = n / rate | ||
3114 | * rate = n / dds_value | ||
3115 | */ | ||
3116 | div64_32(&n, dds_value, &r); | ||
3117 | if (system_sample_rate >= 112000) | ||
3118 | n *= 4; | ||
3119 | else if (system_sample_rate >= 56000) | ||
3120 | n *= 2; | ||
3121 | return ((int)n) - system_sample_rate; | ||
3122 | } | ||
3123 | |||
3124 | static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz) | ||
3125 | { | ||
3126 | int rate = hdsp->system_sample_rate + offset_hz; | ||
3127 | hdsp_set_dds_value(hdsp, rate); | ||
3128 | return 0; | ||
3129 | } | ||
3130 | |||
3131 | static int snd_hdsp_info_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
3132 | { | ||
3133 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
3134 | uinfo->count = 1; | ||
3135 | uinfo->value.integer.min = -5000; | ||
3136 | uinfo->value.integer.max = 5000; | ||
3137 | return 0; | ||
3138 | } | ||
3139 | |||
3140 | static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
3141 | { | ||
3142 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | ||
3143 | |||
3144 | ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp); | ||
3145 | return 0; | ||
3146 | } | ||
3147 | |||
3148 | static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
3149 | { | ||
3150 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | ||
3151 | int change; | ||
3152 | int val; | ||
3153 | |||
3154 | if (!snd_hdsp_use_is_exclusive(hdsp)) | ||
3155 | return -EBUSY; | ||
3156 | val = ucontrol->value.enumerated.item[0]; | ||
3157 | spin_lock_irq(&hdsp->lock); | ||
3158 | if (val != hdsp_dds_offset(hdsp)) | ||
3159 | change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0; | ||
3160 | else | ||
3161 | change = 0; | ||
3162 | spin_unlock_irq(&hdsp->lock); | ||
3163 | return change; | ||
3164 | } | ||
3165 | |||
3088 | static struct snd_kcontrol_new snd_hdsp_9632_controls[] = { | 3166 | static struct snd_kcontrol_new snd_hdsp_9632_controls[] = { |
3089 | HDSP_DA_GAIN("DA Gain", 0), | 3167 | HDSP_DA_GAIN("DA Gain", 0), |
3090 | HDSP_AD_GAIN("AD Gain", 0), | 3168 | HDSP_AD_GAIN("AD Gain", 0), |
3091 | HDSP_PHONE_GAIN("Phones Gain", 0), | 3169 | HDSP_PHONE_GAIN("Phones Gain", 0), |
3092 | HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0) | 3170 | HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0), |
3171 | HDSP_DDS_OFFSET("DDS Sample Rate Offset", 0) | ||
3093 | }; | 3172 | }; |
3094 | 3173 | ||
3095 | static struct snd_kcontrol_new snd_hdsp_controls[] = { | 3174 | static struct snd_kcontrol_new snd_hdsp_controls[] = { |
@@ -3780,11 +3859,9 @@ static int snd_hdsp_reset(struct snd_pcm_substream *substream) | |||
3780 | else | 3859 | else |
3781 | runtime->status->hw_ptr = 0; | 3860 | runtime->status->hw_ptr = 0; |
3782 | if (other) { | 3861 | if (other) { |
3783 | struct list_head *pos; | ||
3784 | struct snd_pcm_substream *s; | 3862 | struct snd_pcm_substream *s; |
3785 | struct snd_pcm_runtime *oruntime = other->runtime; | 3863 | struct snd_pcm_runtime *oruntime = other->runtime; |
3786 | snd_pcm_group_for_each(pos, substream) { | 3864 | snd_pcm_group_for_each_entry(s, substream) { |
3787 | s = snd_pcm_group_substream_entry(pos); | ||
3788 | if (s == other) { | 3865 | if (s == other) { |
3789 | oruntime->status->hw_ptr = runtime->status->hw_ptr; | 3866 | oruntime->status->hw_ptr = runtime->status->hw_ptr; |
3790 | break; | 3867 | break; |
@@ -3933,10 +4010,8 @@ static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd) | |||
3933 | other = hdsp->playback_substream; | 4010 | other = hdsp->playback_substream; |
3934 | 4011 | ||
3935 | if (other) { | 4012 | if (other) { |
3936 | struct list_head *pos; | ||
3937 | struct snd_pcm_substream *s; | 4013 | struct snd_pcm_substream *s; |
3938 | snd_pcm_group_for_each(pos, substream) { | 4014 | snd_pcm_group_for_each_entry(s, substream) { |
3939 | s = snd_pcm_group_substream_entry(pos); | ||
3940 | if (s == other) { | 4015 | if (s == other) { |
3941 | snd_pcm_trigger_done(s, substream); | 4016 | snd_pcm_trigger_done(s, substream); |
3942 | if (cmd == SNDRV_PCM_TRIGGER_START) | 4017 | if (cmd == SNDRV_PCM_TRIGGER_START) |