diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/rme9652/hdspm.c | 1242 |
1 files changed, 1059 insertions, 183 deletions
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 0547f6f04bdc..3d3a4ce3a35e 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -6,6 +6,8 @@ | |||
6 | * code based on hdsp.c Paul Davis | 6 | * code based on hdsp.c Paul Davis |
7 | * Marcus Andersson | 7 | * Marcus Andersson |
8 | * Thomas Charbonnel | 8 | * Thomas Charbonnel |
9 | * Modified 2006-06-01 for AES32 support by Remy Bruno | ||
10 | * <remy.bruno@trinnov.com> | ||
9 | * | 11 | * |
10 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 13 | * it under the terms of the GNU General Public License as published by |
@@ -77,7 +79,8 @@ MODULE_PARM_DESC(enable_monitor, | |||
77 | 79 | ||
78 | MODULE_AUTHOR | 80 | MODULE_AUTHOR |
79 | ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, " | 81 | ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, " |
80 | "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>"); | 82 | "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, " |
83 | "Remy Bruno <remy.bruno@trinnov.com>"); | ||
81 | MODULE_DESCRIPTION("RME HDSPM"); | 84 | MODULE_DESCRIPTION("RME HDSPM"); |
82 | MODULE_LICENSE("GPL"); | 85 | MODULE_LICENSE("GPL"); |
83 | MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | 86 | MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); |
@@ -107,7 +110,12 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
107 | /* --- Read registers. --- | 110 | /* --- Read registers. --- |
108 | These are defined as byte-offsets from the iobase value */ | 111 | These are defined as byte-offsets from the iobase value */ |
109 | #define HDSPM_statusRegister 0 | 112 | #define HDSPM_statusRegister 0 |
110 | #define HDSPM_statusRegister2 96 | 113 | /*#define HDSPM_statusRegister2 96 */ |
114 | /* after RME Windows driver sources, status2 is 4-byte word # 48 = word at | ||
115 | * offset 192, for AES32 *and* MADI | ||
116 | * => need to check that offset 192 is working on MADI */ | ||
117 | #define HDSPM_statusRegister2 192 | ||
118 | #define HDSPM_timecodeRegister 128 | ||
111 | 119 | ||
112 | #define HDSPM_midiDataIn0 360 | 120 | #define HDSPM_midiDataIn0 360 |
113 | #define HDSPM_midiDataIn1 364 | 121 | #define HDSPM_midiDataIn1 364 |
@@ -140,37 +148,50 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
140 | #define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */ | 148 | #define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */ |
141 | #define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */ | 149 | #define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */ |
142 | #define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */ | 150 | #define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */ |
143 | #define HDSPM_QuadSpeed (1<<31) /* quad speed bit, not implemented now */ | 151 | #define HDSPM_QuadSpeed (1<<31) /* quad speed bit */ |
144 | 152 | ||
153 | #define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */ | ||
145 | #define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1, | 154 | #define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1, |
146 | 56channelMODE=0 */ | 155 | 56channelMODE=0 */ /* MADI ONLY*/ |
156 | #define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */ | ||
147 | 157 | ||
148 | #define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode, | 158 | #define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode, |
149 | 0=off, 1=on */ | 159 | 0=off, 1=on */ /* MADI ONLY */ |
160 | #define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */ | ||
150 | 161 | ||
151 | #define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */ | 162 | #define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */ /* MADI ONLY*/ |
152 | #define HDSPM_InputSelect1 (1<<15) /* should be 0 */ | 163 | #define HDSPM_InputSelect1 (1<<15) /* should be 0 */ |
153 | 164 | ||
154 | #define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */ | 165 | #define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */ |
155 | #define HDSPM_SyncRef1 (1<<17) /* should be 0 */ | 166 | #define HDSPM_SyncRef1 (1<<17) /* for AES32: SyncRefN codes the AES # */ |
167 | #define HDSPM_SyncRef2 (1<<13) | ||
168 | #define HDSPM_SyncRef3 (1<<25) | ||
156 | 169 | ||
170 | #define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */ | ||
157 | #define HDSPM_clr_tms (1<<19) /* clear track marker, do not use | 171 | #define HDSPM_clr_tms (1<<19) /* clear track marker, do not use |
158 | AES additional bits in | 172 | AES additional bits in |
159 | lower 5 Audiodatabits ??? */ | 173 | lower 5 Audiodatabits ??? */ |
174 | #define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */ | ||
175 | #define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */ | ||
160 | 176 | ||
161 | #define HDSPM_Midi0InterruptEnable (1<<22) | 177 | #define HDSPM_Midi0InterruptEnable (1<<22) |
162 | #define HDSPM_Midi1InterruptEnable (1<<23) | 178 | #define HDSPM_Midi1InterruptEnable (1<<23) |
163 | 179 | ||
164 | #define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */ | 180 | #define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */ |
165 | 181 | ||
182 | #define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */ | ||
183 | #define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */ | ||
184 | #define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */ | ||
185 | |||
186 | #define HDSPM_wclk_sel (1<<30) | ||
166 | 187 | ||
167 | /* --- bit helper defines */ | 188 | /* --- bit helper defines */ |
168 | #define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2) | 189 | #define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2) |
169 | #define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1) | 190 | #define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|HDSPM_DoubleSpeed|HDSPM_QuadSpeed) |
170 | #define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1) | 191 | #define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1) |
171 | #define HDSPM_InputOptical 0 | 192 | #define HDSPM_InputOptical 0 |
172 | #define HDSPM_InputCoaxial (HDSPM_InputSelect0) | 193 | #define HDSPM_InputCoaxial (HDSPM_InputSelect0) |
173 | #define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1) | 194 | #define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|HDSPM_SyncRef2|HDSPM_SyncRef3) |
174 | #define HDSPM_SyncRef_Word 0 | 195 | #define HDSPM_SyncRef_Word 0 |
175 | #define HDSPM_SyncRef_MADI (HDSPM_SyncRef0) | 196 | #define HDSPM_SyncRef_MADI (HDSPM_SyncRef0) |
176 | 197 | ||
@@ -183,6 +204,9 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
183 | #define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0) | 204 | #define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0) |
184 | #define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1) | 205 | #define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1) |
185 | #define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0) | 206 | #define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0) |
207 | #define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0) | ||
208 | #define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1) | ||
209 | #define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|HDSPM_Frequency0) | ||
186 | 210 | ||
187 | /* --- for internal discrimination */ | 211 | /* --- for internal discrimination */ |
188 | #define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */ | 212 | #define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */ |
@@ -229,7 +253,8 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
229 | #define HDSPM_BIGENDIAN_MODE (1<<9) | 253 | #define HDSPM_BIGENDIAN_MODE (1<<9) |
230 | #define HDSPM_RD_MULTIPLE (1<<10) | 254 | #define HDSPM_RD_MULTIPLE (1<<10) |
231 | 255 | ||
232 | /* --- Status Register bits --- */ | 256 | /* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and |
257 | that do not conflict with specific bits for AES32 seem to be valid also for the AES32 */ | ||
233 | #define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */ | 258 | #define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */ |
234 | #define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn. MODE=0 */ | 259 | #define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn. MODE=0 */ |
235 | #define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 (like inp0) */ | 260 | #define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 (like inp0) */ |
@@ -263,7 +288,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
263 | #define HDSPM_madiFreq176_4 (HDSPM_madiFreq3) | 288 | #define HDSPM_madiFreq176_4 (HDSPM_madiFreq3) |
264 | #define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0) | 289 | #define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0) |
265 | 290 | ||
266 | /* Status2 Register bits */ | 291 | /* Status2 Register bits */ /* MADI ONLY */ |
267 | 292 | ||
268 | #define HDSPM_version0 (1<<0) /* not realy defined but I guess */ | 293 | #define HDSPM_version0 (1<<0) /* not realy defined but I guess */ |
269 | #define HDSPM_version1 (1<<1) /* in former cards it was ??? */ | 294 | #define HDSPM_version1 (1<<1) /* in former cards it was ??? */ |
@@ -297,6 +322,56 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
297 | #define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0) | 322 | #define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0) |
298 | #define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2) | 323 | #define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2) |
299 | 324 | ||
325 | /* | ||
326 | For AES32, bits for status, status2 and timecode are different | ||
327 | */ | ||
328 | /* status */ | ||
329 | #define HDSPM_AES32_wcLock 0x0200000 | ||
330 | #define HDSPM_AES32_wcFreq_bit 22 | ||
331 | /* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function | ||
332 | HDSPM_bit2freq */ | ||
333 | #define HDSPM_AES32_syncref_bit 16 | ||
334 | /* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */ | ||
335 | |||
336 | #define HDSPM_AES32_AUTOSYNC_FROM_WORD 0 | ||
337 | #define HDSPM_AES32_AUTOSYNC_FROM_AES1 1 | ||
338 | #define HDSPM_AES32_AUTOSYNC_FROM_AES2 2 | ||
339 | #define HDSPM_AES32_AUTOSYNC_FROM_AES3 3 | ||
340 | #define HDSPM_AES32_AUTOSYNC_FROM_AES4 4 | ||
341 | #define HDSPM_AES32_AUTOSYNC_FROM_AES5 5 | ||
342 | #define HDSPM_AES32_AUTOSYNC_FROM_AES6 6 | ||
343 | #define HDSPM_AES32_AUTOSYNC_FROM_AES7 7 | ||
344 | #define HDSPM_AES32_AUTOSYNC_FROM_AES8 8 | ||
345 | #define HDSPM_AES32_AUTOSYNC_FROM_NONE -1 | ||
346 | |||
347 | /* status2 */ | ||
348 | /* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */ | ||
349 | #define HDSPM_LockAES 0x80 | ||
350 | #define HDSPM_LockAES1 0x80 | ||
351 | #define HDSPM_LockAES2 0x40 | ||
352 | #define HDSPM_LockAES3 0x20 | ||
353 | #define HDSPM_LockAES4 0x10 | ||
354 | #define HDSPM_LockAES5 0x8 | ||
355 | #define HDSPM_LockAES6 0x4 | ||
356 | #define HDSPM_LockAES7 0x2 | ||
357 | #define HDSPM_LockAES8 0x1 | ||
358 | /* | ||
359 | Timecode | ||
360 | After windows driver sources, bits 4*i to 4*i+3 give the input frequency on | ||
361 | AES i+1 | ||
362 | bits 3210 | ||
363 | 0001 32kHz | ||
364 | 0010 44.1kHz | ||
365 | 0011 48kHz | ||
366 | 0100 64kHz | ||
367 | 0101 88.2kHz | ||
368 | 0110 96kHz | ||
369 | 0111 128kHz | ||
370 | 1000 176.4kHz | ||
371 | 1001 192kHz | ||
372 | NB: Timecode register doesn't seem to work on AES32 card revision 230 | ||
373 | */ | ||
374 | |||
300 | /* Mixer Values */ | 375 | /* Mixer Values */ |
301 | #define UNITY_GAIN 32768 /* = 65536/2 */ | 376 | #define UNITY_GAIN 32768 /* = 65536/2 */ |
302 | #define MINUS_INFINITY_GAIN 0 | 377 | #define MINUS_INFINITY_GAIN 0 |
@@ -314,10 +389,14 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
314 | size is the same regardless of the number of channels, and | 389 | size is the same regardless of the number of channels, and |
315 | also the latency to use. | 390 | also the latency to use. |
316 | for one direction !!! | 391 | for one direction !!! |
392 | => need to mupltiply by 2!! | ||
317 | */ | 393 | */ |
318 | #define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES) | 394 | #define HDSPM_DMA_AREA_BYTES (2 * HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES) |
319 | #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) | 395 | #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) |
320 | 396 | ||
397 | /* revisions >= 230 indicate AES32 card */ | ||
398 | #define HDSPM_AESREVISION 230 | ||
399 | |||
321 | struct hdspm_midi { | 400 | struct hdspm_midi { |
322 | struct hdspm *hdspm; | 401 | struct hdspm *hdspm; |
323 | int id; | 402 | int id; |
@@ -336,7 +415,9 @@ struct hdspm { | |||
336 | struct snd_pcm_substream *playback_substream; /* and/or capture stream */ | 415 | struct snd_pcm_substream *playback_substream; /* and/or capture stream */ |
337 | 416 | ||
338 | char *card_name; /* for procinfo */ | 417 | char *card_name; /* for procinfo */ |
339 | unsigned short firmware_rev; /* dont know if relevant */ | 418 | unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/ |
419 | |||
420 | unsigned char is_aes32; /* indicates if card is AES32 */ | ||
340 | 421 | ||
341 | int precise_ptr; /* use precise pointers, to be tested */ | 422 | int precise_ptr; /* use precise pointers, to be tested */ |
342 | int monitor_outs; /* set up monitoring outs init flag */ | 423 | int monitor_outs; /* set up monitoring outs init flag */ |
@@ -453,6 +534,15 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm); | |||
453 | static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf, | 534 | static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf, |
454 | unsigned int reg, int channels); | 535 | unsigned int reg, int channels); |
455 | 536 | ||
537 | static inline int HDSPM_bit2freq(int n) | ||
538 | { | ||
539 | static int bit2freq_tab[] = { 0, 32000, 44100, 48000, 64000, 88200, | ||
540 | 96000, 128000, 176400, 192000 }; | ||
541 | if (n < 1 || n > 9) | ||
542 | return 0; | ||
543 | return bit2freq_tab[n]; | ||
544 | } | ||
545 | |||
456 | /* Write/read to/from HDSPM with Adresses in Bytes | 546 | /* Write/read to/from HDSPM with Adresses in Bytes |
457 | not words but only 32Bit writes are allowed */ | 547 | not words but only 32Bit writes are allowed */ |
458 | 548 | ||
@@ -544,86 +634,105 @@ static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm) | |||
544 | /* check for external sample rate */ | 634 | /* check for external sample rate */ |
545 | static inline int hdspm_external_sample_rate(struct hdspm * hdspm) | 635 | static inline int hdspm_external_sample_rate(struct hdspm * hdspm) |
546 | { | 636 | { |
547 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 637 | if (hdspm->is_aes32) { |
548 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); | 638 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); |
549 | unsigned int rate_bits; | 639 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); |
550 | int rate = 0; | 640 | unsigned int timecode = hdspm_read(hdspm, HDSPM_timecodeRegister); |
641 | |||
642 | int syncref = hdspm_autosync_ref(hdspm); | ||
643 | |||
644 | if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD && | ||
645 | status & HDSPM_AES32_wcLock) | ||
646 | return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF); | ||
647 | if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 && | ||
648 | syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 && | ||
649 | status2 & (HDSPM_LockAES >> | ||
650 | (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1))) | ||
651 | return HDSPM_bit2freq((timecode >> | ||
652 | (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF); | ||
653 | return 0; | ||
654 | } else { | ||
655 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
656 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); | ||
657 | unsigned int rate_bits; | ||
658 | int rate = 0; | ||
551 | 659 | ||
552 | /* if wordclock has synced freq and wordclock is valid */ | 660 | /* if wordclock has synced freq and wordclock is valid */ |
553 | if ((status2 & HDSPM_wcLock) != 0 && | 661 | if ((status2 & HDSPM_wcLock) != 0 && |
554 | (status & HDSPM_SelSyncRef0) == 0) { | 662 | (status & HDSPM_SelSyncRef0) == 0) { |
555 | 663 | ||
556 | rate_bits = status2 & HDSPM_wcFreqMask; | 664 | rate_bits = status2 & HDSPM_wcFreqMask; |
557 | 665 | ||
558 | switch (rate_bits) { | 666 | switch (rate_bits) { |
559 | case HDSPM_wcFreq32: | 667 | case HDSPM_wcFreq32: |
560 | rate = 32000; | 668 | rate = 32000; |
561 | break; | 669 | break; |
562 | case HDSPM_wcFreq44_1: | 670 | case HDSPM_wcFreq44_1: |
563 | rate = 44100; | 671 | rate = 44100; |
564 | break; | 672 | break; |
565 | case HDSPM_wcFreq48: | 673 | case HDSPM_wcFreq48: |
566 | rate = 48000; | 674 | rate = 48000; |
567 | break; | 675 | break; |
568 | case HDSPM_wcFreq64: | 676 | case HDSPM_wcFreq64: |
569 | rate = 64000; | 677 | rate = 64000; |
570 | break; | 678 | break; |
571 | case HDSPM_wcFreq88_2: | 679 | case HDSPM_wcFreq88_2: |
572 | rate = 88200; | 680 | rate = 88200; |
573 | break; | 681 | break; |
574 | case HDSPM_wcFreq96: | 682 | case HDSPM_wcFreq96: |
575 | rate = 96000; | 683 | rate = 96000; |
576 | break; | 684 | break; |
577 | /* Quadspeed Bit missing ???? */ | 685 | /* Quadspeed Bit missing ???? */ |
578 | default: | 686 | default: |
579 | rate = 0; | 687 | rate = 0; |
580 | break; | 688 | break; |
689 | } | ||
581 | } | 690 | } |
582 | } | ||
583 | 691 | ||
584 | /* if rate detected and Syncref is Word than have it, word has priority to MADI */ | 692 | /* if rate detected and Syncref is Word than have it, word has priority to MADI */ |
585 | if (rate != 0 | 693 | if (rate != 0 && |
586 | && (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) | 694 | (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) |
587 | return rate; | 695 | return rate; |
588 | 696 | ||
589 | /* maby a madi input (which is taken if sel sync is madi) */ | 697 | /* maby a madi input (which is taken if sel sync is madi) */ |
590 | if (status & HDSPM_madiLock) { | 698 | if (status & HDSPM_madiLock) { |
591 | rate_bits = status & HDSPM_madiFreqMask; | 699 | rate_bits = status & HDSPM_madiFreqMask; |
592 | 700 | ||
593 | switch (rate_bits) { | 701 | switch (rate_bits) { |
594 | case HDSPM_madiFreq32: | 702 | case HDSPM_madiFreq32: |
595 | rate = 32000; | 703 | rate = 32000; |
596 | break; | 704 | break; |
597 | case HDSPM_madiFreq44_1: | 705 | case HDSPM_madiFreq44_1: |
598 | rate = 44100; | 706 | rate = 44100; |
599 | break; | 707 | break; |
600 | case HDSPM_madiFreq48: | 708 | case HDSPM_madiFreq48: |
601 | rate = 48000; | 709 | rate = 48000; |
602 | break; | 710 | break; |
603 | case HDSPM_madiFreq64: | 711 | case HDSPM_madiFreq64: |
604 | rate = 64000; | 712 | rate = 64000; |
605 | break; | 713 | break; |
606 | case HDSPM_madiFreq88_2: | 714 | case HDSPM_madiFreq88_2: |
607 | rate = 88200; | 715 | rate = 88200; |
608 | break; | 716 | break; |
609 | case HDSPM_madiFreq96: | 717 | case HDSPM_madiFreq96: |
610 | rate = 96000; | 718 | rate = 96000; |
611 | break; | 719 | break; |
612 | case HDSPM_madiFreq128: | 720 | case HDSPM_madiFreq128: |
613 | rate = 128000; | 721 | rate = 128000; |
614 | break; | 722 | break; |
615 | case HDSPM_madiFreq176_4: | 723 | case HDSPM_madiFreq176_4: |
616 | rate = 176400; | 724 | rate = 176400; |
617 | break; | 725 | break; |
618 | case HDSPM_madiFreq192: | 726 | case HDSPM_madiFreq192: |
619 | rate = 192000; | 727 | rate = 192000; |
620 | break; | 728 | break; |
621 | default: | 729 | default: |
622 | rate = 0; | 730 | rate = 0; |
623 | break; | 731 | break; |
732 | } | ||
624 | } | 733 | } |
734 | return rate; | ||
625 | } | 735 | } |
626 | return rate; | ||
627 | } | 736 | } |
628 | 737 | ||
629 | /* Latency function */ | 738 | /* Latency function */ |
@@ -676,7 +785,8 @@ static inline void hdspm_silence_playback(struct hdspm * hdspm) | |||
676 | int n = hdspm->period_bytes; | 785 | int n = hdspm->period_bytes; |
677 | void *buf = hdspm->playback_buffer; | 786 | void *buf = hdspm->playback_buffer; |
678 | 787 | ||
679 | snd_assert(buf != NULL, return); | 788 | if (buf == NULL) |
789 | return; | ||
680 | 790 | ||
681 | for (i = 0; i < HDSPM_MAX_CHANNELS; i++) { | 791 | for (i = 0; i < HDSPM_MAX_CHANNELS; i++) { |
682 | memset(buf, 0, n); | 792 | memset(buf, 0, n); |
@@ -716,6 +826,7 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
716 | int current_rate; | 826 | int current_rate; |
717 | int rate_bits; | 827 | int rate_bits; |
718 | int not_set = 0; | 828 | int not_set = 0; |
829 | int is_single, is_double, is_quad; | ||
719 | 830 | ||
720 | /* ASSUMPTION: hdspm->lock is either set, or there is no need for | 831 | /* ASSUMPTION: hdspm->lock is either set, or there is no need for |
721 | it (e.g. during module initialization). | 832 | it (e.g. during module initialization). |
@@ -766,43 +877,56 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
766 | changes in the read/write routines. | 877 | changes in the read/write routines. |
767 | */ | 878 | */ |
768 | 879 | ||
880 | is_single = (current_rate <= 48000); | ||
881 | is_double = (current_rate > 48000 && current_rate <= 96000); | ||
882 | is_quad = (current_rate > 96000); | ||
883 | |||
769 | switch (rate) { | 884 | switch (rate) { |
770 | case 32000: | 885 | case 32000: |
771 | if (current_rate > 48000) { | 886 | if (!is_single) |
772 | reject_if_open = 1; | 887 | reject_if_open = 1; |
773 | } | ||
774 | rate_bits = HDSPM_Frequency32KHz; | 888 | rate_bits = HDSPM_Frequency32KHz; |
775 | break; | 889 | break; |
776 | case 44100: | 890 | case 44100: |
777 | if (current_rate > 48000) { | 891 | if (!is_single) |
778 | reject_if_open = 1; | 892 | reject_if_open = 1; |
779 | } | ||
780 | rate_bits = HDSPM_Frequency44_1KHz; | 893 | rate_bits = HDSPM_Frequency44_1KHz; |
781 | break; | 894 | break; |
782 | case 48000: | 895 | case 48000: |
783 | if (current_rate > 48000) { | 896 | if (!is_single) |
784 | reject_if_open = 1; | 897 | reject_if_open = 1; |
785 | } | ||
786 | rate_bits = HDSPM_Frequency48KHz; | 898 | rate_bits = HDSPM_Frequency48KHz; |
787 | break; | 899 | break; |
788 | case 64000: | 900 | case 64000: |
789 | if (current_rate <= 48000) { | 901 | if (!is_double) |
790 | reject_if_open = 1; | 902 | reject_if_open = 1; |
791 | } | ||
792 | rate_bits = HDSPM_Frequency64KHz; | 903 | rate_bits = HDSPM_Frequency64KHz; |
793 | break; | 904 | break; |
794 | case 88200: | 905 | case 88200: |
795 | if (current_rate <= 48000) { | 906 | if (!is_double) |
796 | reject_if_open = 1; | 907 | reject_if_open = 1; |
797 | } | ||
798 | rate_bits = HDSPM_Frequency88_2KHz; | 908 | rate_bits = HDSPM_Frequency88_2KHz; |
799 | break; | 909 | break; |
800 | case 96000: | 910 | case 96000: |
801 | if (current_rate <= 48000) { | 911 | if (!is_double) |
802 | reject_if_open = 1; | 912 | reject_if_open = 1; |
803 | } | ||
804 | rate_bits = HDSPM_Frequency96KHz; | 913 | rate_bits = HDSPM_Frequency96KHz; |
805 | break; | 914 | break; |
915 | case 128000: | ||
916 | if (!is_quad) | ||
917 | reject_if_open = 1; | ||
918 | rate_bits = HDSPM_Frequency128KHz; | ||
919 | break; | ||
920 | case 176400: | ||
921 | if (!is_quad) | ||
922 | reject_if_open = 1; | ||
923 | rate_bits = HDSPM_Frequency176_4KHz; | ||
924 | break; | ||
925 | case 192000: | ||
926 | if (!is_quad) | ||
927 | reject_if_open = 1; | ||
928 | rate_bits = HDSPM_Frequency192KHz; | ||
929 | break; | ||
806 | default: | 930 | default: |
807 | return -EINVAL; | 931 | return -EINVAL; |
808 | } | 932 | } |
@@ -819,7 +943,7 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
819 | hdspm->control_register |= rate_bits; | 943 | hdspm->control_register |= rate_bits; |
820 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | 944 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); |
821 | 945 | ||
822 | if (rate > 64000) | 946 | if (rate > 96000 /* 64000*/) |
823 | hdspm->channel_map = channel_map_madi_qs; | 947 | hdspm->channel_map = channel_map_madi_qs; |
824 | else if (rate > 48000) | 948 | else if (rate > 48000) |
825 | hdspm->channel_map = channel_map_madi_ds; | 949 | hdspm->channel_map = channel_map_madi_ds; |
@@ -1455,11 +1579,27 @@ static int hdspm_pref_sync_ref(struct hdspm * hdspm) | |||
1455 | /* Notice that this looks at the requested sync source, | 1579 | /* Notice that this looks at the requested sync source, |
1456 | not the one actually in use. | 1580 | not the one actually in use. |
1457 | */ | 1581 | */ |
1458 | switch (hdspm->control_register & HDSPM_SyncRefMask) { | 1582 | if (hdspm->is_aes32) { |
1459 | case HDSPM_SyncRef_Word: | 1583 | switch (hdspm->control_register & HDSPM_SyncRefMask) { |
1460 | return HDSPM_SYNC_FROM_WORD; | 1584 | /* number gives AES index, except for 0 which |
1461 | case HDSPM_SyncRef_MADI: | 1585 | corresponds to WordClock */ |
1462 | return HDSPM_SYNC_FROM_MADI; | 1586 | case 0: return 0; |
1587 | case HDSPM_SyncRef0: return 1; | ||
1588 | case HDSPM_SyncRef1: return 2; | ||
1589 | case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; | ||
1590 | case HDSPM_SyncRef2: return 4; | ||
1591 | case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; | ||
1592 | case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; | ||
1593 | case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0: return 7; | ||
1594 | case HDSPM_SyncRef3: return 8; | ||
1595 | } | ||
1596 | } else { | ||
1597 | switch (hdspm->control_register & HDSPM_SyncRefMask) { | ||
1598 | case HDSPM_SyncRef_Word: | ||
1599 | return HDSPM_SYNC_FROM_WORD; | ||
1600 | case HDSPM_SyncRef_MADI: | ||
1601 | return HDSPM_SYNC_FROM_MADI; | ||
1602 | } | ||
1463 | } | 1603 | } |
1464 | 1604 | ||
1465 | return HDSPM_SYNC_FROM_WORD; | 1605 | return HDSPM_SYNC_FROM_WORD; |
@@ -1469,15 +1609,49 @@ static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref) | |||
1469 | { | 1609 | { |
1470 | hdspm->control_register &= ~HDSPM_SyncRefMask; | 1610 | hdspm->control_register &= ~HDSPM_SyncRefMask; |
1471 | 1611 | ||
1472 | switch (pref) { | 1612 | if (hdspm->is_aes32) { |
1473 | case HDSPM_SYNC_FROM_MADI: | 1613 | switch (pref) { |
1474 | hdspm->control_register |= HDSPM_SyncRef_MADI; | 1614 | case 0: |
1475 | break; | 1615 | hdspm->control_register |= 0; |
1476 | case HDSPM_SYNC_FROM_WORD: | 1616 | break; |
1477 | hdspm->control_register |= HDSPM_SyncRef_Word; | 1617 | case 1: |
1478 | break; | 1618 | hdspm->control_register |= HDSPM_SyncRef0; |
1479 | default: | 1619 | break; |
1480 | return -1; | 1620 | case 2: |
1621 | hdspm->control_register |= HDSPM_SyncRef1; | ||
1622 | break; | ||
1623 | case 3: | ||
1624 | hdspm->control_register |= HDSPM_SyncRef1+HDSPM_SyncRef0; | ||
1625 | break; | ||
1626 | case 4: | ||
1627 | hdspm->control_register |= HDSPM_SyncRef2; | ||
1628 | break; | ||
1629 | case 5: | ||
1630 | hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef0; | ||
1631 | break; | ||
1632 | case 6: | ||
1633 | hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1; | ||
1634 | break; | ||
1635 | case 7: | ||
1636 | hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0; | ||
1637 | break; | ||
1638 | case 8: | ||
1639 | hdspm->control_register |= HDSPM_SyncRef3; | ||
1640 | break; | ||
1641 | default: | ||
1642 | return -1; | ||
1643 | } | ||
1644 | } else { | ||
1645 | switch (pref) { | ||
1646 | case HDSPM_SYNC_FROM_MADI: | ||
1647 | hdspm->control_register |= HDSPM_SyncRef_MADI; | ||
1648 | break; | ||
1649 | case HDSPM_SYNC_FROM_WORD: | ||
1650 | hdspm->control_register |= HDSPM_SyncRef_Word; | ||
1651 | break; | ||
1652 | default: | ||
1653 | return -1; | ||
1654 | } | ||
1481 | } | 1655 | } |
1482 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | 1656 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); |
1483 | return 0; | 1657 | return 0; |
@@ -1486,18 +1660,36 @@ static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref) | |||
1486 | static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol, | 1660 | static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol, |
1487 | struct snd_ctl_elem_info *uinfo) | 1661 | struct snd_ctl_elem_info *uinfo) |
1488 | { | 1662 | { |
1489 | static char *texts[] = { "Word", "MADI" }; | 1663 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1490 | 1664 | ||
1491 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1665 | if (hdspm->is_aes32) { |
1492 | uinfo->count = 1; | 1666 | static char *texts[] = { "Word", "AES1", "AES2", "AES3", |
1667 | "AES4", "AES5", "AES6", "AES7", "AES8" }; | ||
1493 | 1668 | ||
1494 | uinfo->value.enumerated.items = 2; | 1669 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1670 | uinfo->count = 1; | ||
1495 | 1671 | ||
1496 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1672 | uinfo->value.enumerated.items = 9; |
1497 | uinfo->value.enumerated.item = | 1673 | |
1498 | uinfo->value.enumerated.items - 1; | 1674 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
1499 | strcpy(uinfo->value.enumerated.name, | 1675 | uinfo->value.enumerated.item = |
1500 | texts[uinfo->value.enumerated.item]); | 1676 | uinfo->value.enumerated.items - 1; |
1677 | strcpy(uinfo->value.enumerated.name, | ||
1678 | texts[uinfo->value.enumerated.item]); | ||
1679 | } else { | ||
1680 | static char *texts[] = { "Word", "MADI" }; | ||
1681 | |||
1682 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1683 | uinfo->count = 1; | ||
1684 | |||
1685 | uinfo->value.enumerated.items = 2; | ||
1686 | |||
1687 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
1688 | uinfo->value.enumerated.item = | ||
1689 | uinfo->value.enumerated.items - 1; | ||
1690 | strcpy(uinfo->value.enumerated.name, | ||
1691 | texts[uinfo->value.enumerated.item]); | ||
1692 | } | ||
1501 | return 0; | 1693 | return 0; |
1502 | } | 1694 | } |
1503 | 1695 | ||
@@ -1517,7 +1709,7 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol, | |||
1517 | int change, max; | 1709 | int change, max; |
1518 | unsigned int val; | 1710 | unsigned int val; |
1519 | 1711 | ||
1520 | max = 2; | 1712 | max = hdspm->is_aes32 ? 9 : 2; |
1521 | 1713 | ||
1522 | if (!snd_hdspm_use_is_exclusive(hdspm)) | 1714 | if (!snd_hdspm_use_is_exclusive(hdspm)) |
1523 | return -EBUSY; | 1715 | return -EBUSY; |
@@ -1542,40 +1734,64 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol, | |||
1542 | 1734 | ||
1543 | static int hdspm_autosync_ref(struct hdspm * hdspm) | 1735 | static int hdspm_autosync_ref(struct hdspm * hdspm) |
1544 | { | 1736 | { |
1545 | /* This looks at the autosync selected sync reference */ | 1737 | if (hdspm->is_aes32) { |
1546 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 1738 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); |
1547 | 1739 | unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF; | |
1548 | switch (status2 & HDSPM_SelSyncRefMask) { | 1740 | if (syncref == 0) |
1549 | 1741 | return HDSPM_AES32_AUTOSYNC_FROM_WORD; | |
1550 | case HDSPM_SelSyncRef_WORD: | 1742 | if (syncref <= 8) |
1551 | return HDSPM_AUTOSYNC_FROM_WORD; | 1743 | return syncref; |
1552 | 1744 | return HDSPM_AES32_AUTOSYNC_FROM_NONE; | |
1553 | case HDSPM_SelSyncRef_MADI: | 1745 | } else { |
1554 | return HDSPM_AUTOSYNC_FROM_MADI; | 1746 | /* This looks at the autosync selected sync reference */ |
1555 | 1747 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | |
1556 | case HDSPM_SelSyncRef_NVALID: | 1748 | |
1557 | return HDSPM_AUTOSYNC_FROM_NONE; | 1749 | switch (status2 & HDSPM_SelSyncRefMask) { |
1750 | case HDSPM_SelSyncRef_WORD: | ||
1751 | return HDSPM_AUTOSYNC_FROM_WORD; | ||
1752 | case HDSPM_SelSyncRef_MADI: | ||
1753 | return HDSPM_AUTOSYNC_FROM_MADI; | ||
1754 | case HDSPM_SelSyncRef_NVALID: | ||
1755 | return HDSPM_AUTOSYNC_FROM_NONE; | ||
1756 | default: | ||
1757 | return 0; | ||
1758 | } | ||
1558 | 1759 | ||
1559 | default: | ||
1560 | return 0; | 1760 | return 0; |
1561 | } | 1761 | } |
1562 | |||
1563 | return 0; | ||
1564 | } | 1762 | } |
1565 | 1763 | ||
1566 | static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol, | 1764 | static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol, |
1567 | struct snd_ctl_elem_info *uinfo) | 1765 | struct snd_ctl_elem_info *uinfo) |
1568 | { | 1766 | { |
1569 | static char *texts[] = { "WordClock", "MADI", "None" }; | 1767 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1570 | 1768 | ||
1571 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1769 | if (hdspm->is_aes32) { |
1572 | uinfo->count = 1; | 1770 | static char *texts[] = { "WordClock", "AES1", "AES2", "AES3", |
1573 | uinfo->value.enumerated.items = 3; | 1771 | "AES4", "AES5", "AES6", "AES7", "AES8", "None"}; |
1574 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1772 | |
1575 | uinfo->value.enumerated.item = | 1773 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1576 | uinfo->value.enumerated.items - 1; | 1774 | uinfo->count = 1; |
1577 | strcpy(uinfo->value.enumerated.name, | 1775 | uinfo->value.enumerated.items = 10; |
1578 | texts[uinfo->value.enumerated.item]); | 1776 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
1777 | uinfo->value.enumerated.item = | ||
1778 | uinfo->value.enumerated.items - 1; | ||
1779 | strcpy(uinfo->value.enumerated.name, | ||
1780 | texts[uinfo->value.enumerated.item]); | ||
1781 | } | ||
1782 | else | ||
1783 | { | ||
1784 | static char *texts[] = { "WordClock", "MADI", "None" }; | ||
1785 | |||
1786 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1787 | uinfo->count = 1; | ||
1788 | uinfo->value.enumerated.items = 3; | ||
1789 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
1790 | uinfo->value.enumerated.item = | ||
1791 | uinfo->value.enumerated.items - 1; | ||
1792 | strcpy(uinfo->value.enumerated.name, | ||
1793 | texts[uinfo->value.enumerated.item]); | ||
1794 | } | ||
1579 | return 0; | 1795 | return 0; |
1580 | } | 1796 | } |
1581 | 1797 | ||
@@ -1841,6 +2057,195 @@ static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol, | |||
1841 | return change; | 2057 | return change; |
1842 | } | 2058 | } |
1843 | 2059 | ||
2060 | #define HDSPM_EMPHASIS(xname, xindex) \ | ||
2061 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2062 | .name = xname, \ | ||
2063 | .index = xindex, \ | ||
2064 | .info = snd_hdspm_info_emphasis, \ | ||
2065 | .get = snd_hdspm_get_emphasis, \ | ||
2066 | .put = snd_hdspm_put_emphasis \ | ||
2067 | } | ||
2068 | |||
2069 | static int hdspm_emphasis(struct hdspm * hdspm) | ||
2070 | { | ||
2071 | return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0; | ||
2072 | } | ||
2073 | |||
2074 | static int hdspm_set_emphasis(struct hdspm * hdspm, int emp) | ||
2075 | { | ||
2076 | if (emp) | ||
2077 | hdspm->control_register |= HDSPM_Emphasis; | ||
2078 | else | ||
2079 | hdspm->control_register &= ~HDSPM_Emphasis; | ||
2080 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
2081 | |||
2082 | return 0; | ||
2083 | } | ||
2084 | |||
2085 | static int snd_hdspm_info_emphasis(struct snd_kcontrol *kcontrol, | ||
2086 | struct snd_ctl_elem_info *uinfo) | ||
2087 | { | ||
2088 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2089 | uinfo->count = 1; | ||
2090 | uinfo->value.integer.min = 0; | ||
2091 | uinfo->value.integer.max = 1; | ||
2092 | return 0; | ||
2093 | } | ||
2094 | |||
2095 | static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol, | ||
2096 | struct snd_ctl_elem_value *ucontrol) | ||
2097 | { | ||
2098 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2099 | |||
2100 | spin_lock_irq(&hdspm->lock); | ||
2101 | ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm); | ||
2102 | spin_unlock_irq(&hdspm->lock); | ||
2103 | return 0; | ||
2104 | } | ||
2105 | |||
2106 | static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol, | ||
2107 | struct snd_ctl_elem_value *ucontrol) | ||
2108 | { | ||
2109 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2110 | int change; | ||
2111 | unsigned int val; | ||
2112 | |||
2113 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
2114 | return -EBUSY; | ||
2115 | val = ucontrol->value.integer.value[0] & 1; | ||
2116 | spin_lock_irq(&hdspm->lock); | ||
2117 | change = (int) val != hdspm_emphasis(hdspm); | ||
2118 | hdspm_set_emphasis(hdspm, val); | ||
2119 | spin_unlock_irq(&hdspm->lock); | ||
2120 | return change; | ||
2121 | } | ||
2122 | |||
2123 | #define HDSPM_DOLBY(xname, xindex) \ | ||
2124 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2125 | .name = xname, \ | ||
2126 | .index = xindex, \ | ||
2127 | .info = snd_hdspm_info_dolby, \ | ||
2128 | .get = snd_hdspm_get_dolby, \ | ||
2129 | .put = snd_hdspm_put_dolby \ | ||
2130 | } | ||
2131 | |||
2132 | static int hdspm_dolby(struct hdspm * hdspm) | ||
2133 | { | ||
2134 | return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0; | ||
2135 | } | ||
2136 | |||
2137 | static int hdspm_set_dolby(struct hdspm * hdspm, int dol) | ||
2138 | { | ||
2139 | if (dol) | ||
2140 | hdspm->control_register |= HDSPM_Dolby; | ||
2141 | else | ||
2142 | hdspm->control_register &= ~HDSPM_Dolby; | ||
2143 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
2144 | |||
2145 | return 0; | ||
2146 | } | ||
2147 | |||
2148 | static int snd_hdspm_info_dolby(struct snd_kcontrol *kcontrol, | ||
2149 | struct snd_ctl_elem_info *uinfo) | ||
2150 | { | ||
2151 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2152 | uinfo->count = 1; | ||
2153 | uinfo->value.integer.min = 0; | ||
2154 | uinfo->value.integer.max = 1; | ||
2155 | return 0; | ||
2156 | } | ||
2157 | |||
2158 | static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol, | ||
2159 | struct snd_ctl_elem_value *ucontrol) | ||
2160 | { | ||
2161 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2162 | |||
2163 | spin_lock_irq(&hdspm->lock); | ||
2164 | ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm); | ||
2165 | spin_unlock_irq(&hdspm->lock); | ||
2166 | return 0; | ||
2167 | } | ||
2168 | |||
2169 | static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol, | ||
2170 | struct snd_ctl_elem_value *ucontrol) | ||
2171 | { | ||
2172 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2173 | int change; | ||
2174 | unsigned int val; | ||
2175 | |||
2176 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
2177 | return -EBUSY; | ||
2178 | val = ucontrol->value.integer.value[0] & 1; | ||
2179 | spin_lock_irq(&hdspm->lock); | ||
2180 | change = (int) val != hdspm_dolby(hdspm); | ||
2181 | hdspm_set_dolby(hdspm, val); | ||
2182 | spin_unlock_irq(&hdspm->lock); | ||
2183 | return change; | ||
2184 | } | ||
2185 | |||
2186 | #define HDSPM_PROFESSIONAL(xname, xindex) \ | ||
2187 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2188 | .name = xname, \ | ||
2189 | .index = xindex, \ | ||
2190 | .info = snd_hdspm_info_professional, \ | ||
2191 | .get = snd_hdspm_get_professional, \ | ||
2192 | .put = snd_hdspm_put_professional \ | ||
2193 | } | ||
2194 | |||
2195 | static int hdspm_professional(struct hdspm * hdspm) | ||
2196 | { | ||
2197 | return (hdspm->control_register & HDSPM_Professional) ? 1 : 0; | ||
2198 | } | ||
2199 | |||
2200 | static int hdspm_set_professional(struct hdspm * hdspm, int dol) | ||
2201 | { | ||
2202 | if (dol) | ||
2203 | hdspm->control_register |= HDSPM_Professional; | ||
2204 | else | ||
2205 | hdspm->control_register &= ~HDSPM_Professional; | ||
2206 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
2207 | |||
2208 | return 0; | ||
2209 | } | ||
2210 | |||
2211 | static int snd_hdspm_info_professional(struct snd_kcontrol *kcontrol, | ||
2212 | struct snd_ctl_elem_info *uinfo) | ||
2213 | { | ||
2214 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2215 | uinfo->count = 1; | ||
2216 | uinfo->value.integer.min = 0; | ||
2217 | uinfo->value.integer.max = 1; | ||
2218 | return 0; | ||
2219 | } | ||
2220 | |||
2221 | static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol, | ||
2222 | struct snd_ctl_elem_value *ucontrol) | ||
2223 | { | ||
2224 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2225 | |||
2226 | spin_lock_irq(&hdspm->lock); | ||
2227 | ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm); | ||
2228 | spin_unlock_irq(&hdspm->lock); | ||
2229 | return 0; | ||
2230 | } | ||
2231 | |||
2232 | static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol, | ||
2233 | struct snd_ctl_elem_value *ucontrol) | ||
2234 | { | ||
2235 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2236 | int change; | ||
2237 | unsigned int val; | ||
2238 | |||
2239 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
2240 | return -EBUSY; | ||
2241 | val = ucontrol->value.integer.value[0] & 1; | ||
2242 | spin_lock_irq(&hdspm->lock); | ||
2243 | change = (int) val != hdspm_professional(hdspm); | ||
2244 | hdspm_set_professional(hdspm, val); | ||
2245 | spin_unlock_irq(&hdspm->lock); | ||
2246 | return change; | ||
2247 | } | ||
2248 | |||
1844 | #define HDSPM_INPUT_SELECT(xname, xindex) \ | 2249 | #define HDSPM_INPUT_SELECT(xname, xindex) \ |
1845 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2250 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1846 | .name = xname, \ | 2251 | .name = xname, \ |
@@ -1912,6 +2317,163 @@ static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol, | |||
1912 | return change; | 2317 | return change; |
1913 | } | 2318 | } |
1914 | 2319 | ||
2320 | #define HDSPM_DS_WIRE(xname, xindex) \ | ||
2321 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2322 | .name = xname, \ | ||
2323 | .index = xindex, \ | ||
2324 | .info = snd_hdspm_info_ds_wire, \ | ||
2325 | .get = snd_hdspm_get_ds_wire, \ | ||
2326 | .put = snd_hdspm_put_ds_wire \ | ||
2327 | } | ||
2328 | |||
2329 | static int hdspm_ds_wire(struct hdspm * hdspm) | ||
2330 | { | ||
2331 | return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0; | ||
2332 | } | ||
2333 | |||
2334 | static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds) | ||
2335 | { | ||
2336 | if (ds) | ||
2337 | hdspm->control_register |= HDSPM_DS_DoubleWire; | ||
2338 | else | ||
2339 | hdspm->control_register &= ~HDSPM_DS_DoubleWire; | ||
2340 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
2341 | |||
2342 | return 0; | ||
2343 | } | ||
2344 | |||
2345 | static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol, | ||
2346 | struct snd_ctl_elem_info *uinfo) | ||
2347 | { | ||
2348 | static char *texts[] = { "Single", "Double" }; | ||
2349 | |||
2350 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2351 | uinfo->count = 1; | ||
2352 | uinfo->value.enumerated.items = 2; | ||
2353 | |||
2354 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2355 | uinfo->value.enumerated.item = | ||
2356 | uinfo->value.enumerated.items - 1; | ||
2357 | strcpy(uinfo->value.enumerated.name, | ||
2358 | texts[uinfo->value.enumerated.item]); | ||
2359 | |||
2360 | return 0; | ||
2361 | } | ||
2362 | |||
2363 | static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol, | ||
2364 | struct snd_ctl_elem_value *ucontrol) | ||
2365 | { | ||
2366 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2367 | |||
2368 | spin_lock_irq(&hdspm->lock); | ||
2369 | ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm); | ||
2370 | spin_unlock_irq(&hdspm->lock); | ||
2371 | return 0; | ||
2372 | } | ||
2373 | |||
2374 | static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol, | ||
2375 | struct snd_ctl_elem_value *ucontrol) | ||
2376 | { | ||
2377 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2378 | int change; | ||
2379 | unsigned int val; | ||
2380 | |||
2381 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
2382 | return -EBUSY; | ||
2383 | val = ucontrol->value.integer.value[0] & 1; | ||
2384 | spin_lock_irq(&hdspm->lock); | ||
2385 | change = (int) val != hdspm_ds_wire(hdspm); | ||
2386 | hdspm_set_ds_wire(hdspm, val); | ||
2387 | spin_unlock_irq(&hdspm->lock); | ||
2388 | return change; | ||
2389 | } | ||
2390 | |||
2391 | #define HDSPM_QS_WIRE(xname, xindex) \ | ||
2392 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2393 | .name = xname, \ | ||
2394 | .index = xindex, \ | ||
2395 | .info = snd_hdspm_info_qs_wire, \ | ||
2396 | .get = snd_hdspm_get_qs_wire, \ | ||
2397 | .put = snd_hdspm_put_qs_wire \ | ||
2398 | } | ||
2399 | |||
2400 | static int hdspm_qs_wire(struct hdspm * hdspm) | ||
2401 | { | ||
2402 | if (hdspm->control_register & HDSPM_QS_DoubleWire) | ||
2403 | return 1; | ||
2404 | if (hdspm->control_register & HDSPM_QS_QuadWire) | ||
2405 | return 2; | ||
2406 | return 0; | ||
2407 | } | ||
2408 | |||
2409 | static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode) | ||
2410 | { | ||
2411 | hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire); | ||
2412 | switch (mode) { | ||
2413 | case 0: | ||
2414 | break; | ||
2415 | case 1: | ||
2416 | hdspm->control_register |= HDSPM_QS_DoubleWire; | ||
2417 | break; | ||
2418 | case 2: | ||
2419 | hdspm->control_register |= HDSPM_QS_QuadWire; | ||
2420 | break; | ||
2421 | } | ||
2422 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
2423 | |||
2424 | return 0; | ||
2425 | } | ||
2426 | |||
2427 | static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol, | ||
2428 | struct snd_ctl_elem_info *uinfo) | ||
2429 | { | ||
2430 | static char *texts[] = { "Single", "Double", "Quad" }; | ||
2431 | |||
2432 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2433 | uinfo->count = 1; | ||
2434 | uinfo->value.enumerated.items = 3; | ||
2435 | |||
2436 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2437 | uinfo->value.enumerated.item = | ||
2438 | uinfo->value.enumerated.items - 1; | ||
2439 | strcpy(uinfo->value.enumerated.name, | ||
2440 | texts[uinfo->value.enumerated.item]); | ||
2441 | |||
2442 | return 0; | ||
2443 | } | ||
2444 | |||
2445 | static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol, | ||
2446 | struct snd_ctl_elem_value *ucontrol) | ||
2447 | { | ||
2448 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2449 | |||
2450 | spin_lock_irq(&hdspm->lock); | ||
2451 | ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm); | ||
2452 | spin_unlock_irq(&hdspm->lock); | ||
2453 | return 0; | ||
2454 | } | ||
2455 | |||
2456 | static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol, | ||
2457 | struct snd_ctl_elem_value *ucontrol) | ||
2458 | { | ||
2459 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2460 | int change; | ||
2461 | int val; | ||
2462 | |||
2463 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
2464 | return -EBUSY; | ||
2465 | val = ucontrol->value.integer.value[0]; | ||
2466 | if (val < 0) | ||
2467 | val = 0; | ||
2468 | if (val > 2) | ||
2469 | val = 2; | ||
2470 | spin_lock_irq(&hdspm->lock); | ||
2471 | change = (int) val != hdspm_qs_wire(hdspm); | ||
2472 | hdspm_set_qs_wire(hdspm, val); | ||
2473 | spin_unlock_irq(&hdspm->lock); | ||
2474 | return change; | ||
2475 | } | ||
2476 | |||
1915 | /* Simple Mixer | 2477 | /* Simple Mixer |
1916 | deprecated since to much faders ??? | 2478 | deprecated since to much faders ??? |
1917 | MIXER interface says output (source, destination, value) | 2479 | MIXER interface says output (source, destination, value) |
@@ -2135,14 +2697,24 @@ static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol, | |||
2135 | 2697 | ||
2136 | static int hdspm_wc_sync_check(struct hdspm * hdspm) | 2698 | static int hdspm_wc_sync_check(struct hdspm * hdspm) |
2137 | { | 2699 | { |
2138 | int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 2700 | if (hdspm->is_aes32) { |
2139 | if (status2 & HDSPM_wcLock) { | 2701 | int status = hdspm_read(hdspm, HDSPM_statusRegister); |
2140 | if (status2 & HDSPM_wcSync) | 2702 | if (status & HDSPM_AES32_wcLock) { |
2703 | /* I don't know how to differenciate sync from lock. | ||
2704 | Doing as if sync for now */ | ||
2141 | return 2; | 2705 | return 2; |
2142 | else | 2706 | } |
2143 | return 1; | 2707 | return 0; |
2708 | } else { | ||
2709 | int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
2710 | if (status2 & HDSPM_wcLock) { | ||
2711 | if (status2 & HDSPM_wcSync) | ||
2712 | return 2; | ||
2713 | else | ||
2714 | return 1; | ||
2715 | } | ||
2716 | return 0; | ||
2144 | } | 2717 | } |
2145 | return 0; | ||
2146 | } | 2718 | } |
2147 | 2719 | ||
2148 | static int snd_hdspm_get_wc_sync_check(struct snd_kcontrol *kcontrol, | 2720 | static int snd_hdspm_get_wc_sync_check(struct snd_kcontrol *kcontrol, |
@@ -2188,9 +2760,43 @@ static int snd_hdspm_get_madisync_sync_check(struct snd_kcontrol *kcontrol, | |||
2188 | } | 2760 | } |
2189 | 2761 | ||
2190 | 2762 | ||
2763 | #define HDSPM_AES_SYNC_CHECK(xname, xindex) \ | ||
2764 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2765 | .name = xname, \ | ||
2766 | .index = xindex, \ | ||
2767 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
2768 | .info = snd_hdspm_info_sync_check, \ | ||
2769 | .get = snd_hdspm_get_aes_sync_check \ | ||
2770 | } | ||
2771 | |||
2772 | static int hdspm_aes_sync_check(struct hdspm * hdspm, int idx) | ||
2773 | { | ||
2774 | int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
2775 | if (status2 & (HDSPM_LockAES >> idx)) { | ||
2776 | /* I don't know how to differenciate sync from lock. | ||
2777 | Doing as if sync for now */ | ||
2778 | return 2; | ||
2779 | } | ||
2780 | return 0; | ||
2781 | } | ||
2782 | |||
2783 | static int snd_hdspm_get_aes_sync_check(struct snd_kcontrol *kcontrol, | ||
2784 | struct snd_ctl_elem_value *ucontrol) | ||
2785 | { | ||
2786 | int offset; | ||
2787 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2788 | |||
2789 | offset = ucontrol->id.index - 1; | ||
2790 | if (offset < 0 || offset >= 8) | ||
2791 | return -EINVAL; | ||
2792 | |||
2793 | ucontrol->value.enumerated.item[0] = | ||
2794 | hdspm_aes_sync_check(hdspm, offset); | ||
2795 | return 0; | ||
2796 | } | ||
2191 | 2797 | ||
2192 | 2798 | ||
2193 | static struct snd_kcontrol_new snd_hdspm_controls[] = { | 2799 | static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { |
2194 | 2800 | ||
2195 | HDSPM_MIXER("Mixer", 0), | 2801 | HDSPM_MIXER("Mixer", 0), |
2196 | /* 'Sample Clock Source' complies with the alsa control naming scheme */ | 2802 | /* 'Sample Clock Source' complies with the alsa control naming scheme */ |
@@ -2211,6 +2817,29 @@ static struct snd_kcontrol_new snd_hdspm_controls[] = { | |||
2211 | HDSPM_INPUT_SELECT("Input Select", 0), | 2817 | HDSPM_INPUT_SELECT("Input Select", 0), |
2212 | }; | 2818 | }; |
2213 | 2819 | ||
2820 | static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = { | ||
2821 | |||
2822 | HDSPM_MIXER("Mixer", 0), | ||
2823 | /* 'Sample Clock Source' complies with the alsa control naming scheme */ | ||
2824 | HDSPM_CLOCK_SOURCE("Sample Clock Source", 0), | ||
2825 | |||
2826 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), | ||
2827 | HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), | ||
2828 | HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), | ||
2829 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), | ||
2830 | /* 'External Rate' complies with the alsa control naming scheme */ | ||
2831 | HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), | ||
2832 | HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0), | ||
2833 | /* HDSPM_AES_SYNC_CHECK("AES Lock Status", 0),*/ /* created in snd_hdspm_create_controls() */ | ||
2834 | HDSPM_LINE_OUT("Line Out", 0), | ||
2835 | HDSPM_EMPHASIS("Emphasis", 0), | ||
2836 | HDSPM_DOLBY("Non Audio", 0), | ||
2837 | HDSPM_PROFESSIONAL("Professional", 0), | ||
2838 | HDSPM_C_TMS("Clear Track Marker", 0), | ||
2839 | HDSPM_DS_WIRE("Double Speed Wire Mode", 0), | ||
2840 | HDSPM_QS_WIRE("Quad Speed Wire Mode", 0), | ||
2841 | }; | ||
2842 | |||
2214 | static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER; | 2843 | static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER; |
2215 | 2844 | ||
2216 | 2845 | ||
@@ -2245,20 +2874,40 @@ static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm | |||
2245 | struct snd_kcontrol *kctl; | 2874 | struct snd_kcontrol *kctl; |
2246 | 2875 | ||
2247 | /* add control list first */ | 2876 | /* add control list first */ |
2248 | 2877 | if (hdspm->is_aes32) { | |
2249 | for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls); idx++) { | 2878 | struct snd_kcontrol_new aes_sync_ctl = |
2250 | if ((err = | 2879 | HDSPM_AES_SYNC_CHECK("AES Lock Status", 0); |
2251 | snd_ctl_add(card, kctl = | 2880 | |
2252 | snd_ctl_new1(&snd_hdspm_controls[idx], | 2881 | for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_aes32); |
2253 | hdspm))) < 0) { | 2882 | idx++) { |
2254 | return err; | 2883 | err = snd_ctl_add(card, |
2884 | snd_ctl_new1(&snd_hdspm_controls_aes32[idx], | ||
2885 | hdspm)); | ||
2886 | if (err < 0) | ||
2887 | return err; | ||
2888 | } | ||
2889 | for (idx = 1; idx <= 8; idx++) { | ||
2890 | aes_sync_ctl.index = idx; | ||
2891 | err = snd_ctl_add(card, | ||
2892 | snd_ctl_new1(&aes_sync_ctl, hdspm)); | ||
2893 | if (err < 0) | ||
2894 | return err; | ||
2895 | } | ||
2896 | } else { | ||
2897 | for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_madi); | ||
2898 | idx++) { | ||
2899 | err = snd_ctl_add(card, | ||
2900 | snd_ctl_new1(&snd_hdspm_controls_madi[idx], | ||
2901 | hdspm)); | ||
2902 | if (err < 0) | ||
2903 | return err; | ||
2255 | } | 2904 | } |
2256 | } | 2905 | } |
2257 | 2906 | ||
2258 | /* Channel playback mixer as default control | 2907 | /* Channel playback mixer as default control |
2259 | Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer | 2908 | Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer |
2260 | they are accesible via special IOCTL on hwdep | 2909 | they are accesible via special IOCTL on hwdep |
2261 | and the mixer 2dimensional mixer control */ | 2910 | and the mixer 2dimensional mixer control */ |
2262 | 2911 | ||
2263 | snd_hdspm_playback_mixer.name = "Chn"; | 2912 | snd_hdspm_playback_mixer.name = "Chn"; |
2264 | limit = HDSPM_MAX_CHANNELS; | 2913 | limit = HDSPM_MAX_CHANNELS; |
@@ -2289,7 +2938,8 @@ static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm | |||
2289 | ------------------------------------------------------------*/ | 2938 | ------------------------------------------------------------*/ |
2290 | 2939 | ||
2291 | static void | 2940 | static void |
2292 | snd_hdspm_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer) | 2941 | snd_hdspm_proc_read_madi(struct snd_info_entry * entry, |
2942 | struct snd_info_buffer *buffer) | ||
2293 | { | 2943 | { |
2294 | struct hdspm *hdspm = (struct hdspm *) entry->private_data; | 2944 | struct hdspm *hdspm = (struct hdspm *) entry->private_data; |
2295 | unsigned int status; | 2945 | unsigned int status; |
@@ -2420,11 +3070,10 @@ snd_hdspm_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffe | |||
2420 | clock_source = "Error"; | 3070 | clock_source = "Error"; |
2421 | } | 3071 | } |
2422 | snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source); | 3072 | snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source); |
2423 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) { | 3073 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) |
2424 | system_clock_mode = "Slave"; | 3074 | system_clock_mode = "Slave"; |
2425 | } else { | 3075 | else |
2426 | system_clock_mode = "Master"; | 3076 | system_clock_mode = "Master"; |
2427 | } | ||
2428 | snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode); | 3077 | snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode); |
2429 | 3078 | ||
2430 | switch (hdspm_pref_sync_ref(hdspm)) { | 3079 | switch (hdspm_pref_sync_ref(hdspm)) { |
@@ -2484,13 +3133,213 @@ snd_hdspm_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffe | |||
2484 | snd_iprintf(buffer, "\n"); | 3133 | snd_iprintf(buffer, "\n"); |
2485 | } | 3134 | } |
2486 | 3135 | ||
3136 | static void | ||
3137 | snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | ||
3138 | struct snd_info_buffer *buffer) | ||
3139 | { | ||
3140 | struct hdspm *hdspm = (struct hdspm *) entry->private_data; | ||
3141 | unsigned int status; | ||
3142 | unsigned int status2; | ||
3143 | unsigned int timecode; | ||
3144 | int pref_syncref; | ||
3145 | char *autosync_ref; | ||
3146 | char *system_clock_mode; | ||
3147 | char *clock_source; | ||
3148 | int x; | ||
3149 | |||
3150 | status = hdspm_read(hdspm, HDSPM_statusRegister); | ||
3151 | status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
3152 | timecode = hdspm_read(hdspm, HDSPM_timecodeRegister); | ||
3153 | |||
3154 | snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n", | ||
3155 | hdspm->card_name, hdspm->card->number + 1, | ||
3156 | hdspm->firmware_rev); | ||
3157 | |||
3158 | snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n", | ||
3159 | hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase); | ||
3160 | |||
3161 | snd_iprintf(buffer, "--- System ---\n"); | ||
3162 | |||
3163 | snd_iprintf(buffer, | ||
3164 | "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n", | ||
3165 | status & HDSPM_audioIRQPending, | ||
3166 | (status & HDSPM_midi0IRQPending) ? 1 : 0, | ||
3167 | (status & HDSPM_midi1IRQPending) ? 1 : 0, | ||
3168 | hdspm->irq_count); | ||
3169 | snd_iprintf(buffer, | ||
3170 | "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n", | ||
3171 | ((status & HDSPM_BufferID) ? 1 : 0), | ||
3172 | (status & HDSPM_BufferPositionMask), | ||
3173 | (status & HDSPM_BufferPositionMask) % (2 * | ||
3174 | (int)hdspm-> | ||
3175 | period_bytes), | ||
3176 | ((status & HDSPM_BufferPositionMask) - | ||
3177 | 64) % (2 * (int)hdspm->period_bytes), | ||
3178 | (long) hdspm_hw_pointer(hdspm) * 4); | ||
3179 | |||
3180 | snd_iprintf(buffer, | ||
3181 | "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n", | ||
3182 | hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF, | ||
3183 | hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF, | ||
3184 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, | ||
3185 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); | ||
3186 | snd_iprintf(buffer, | ||
3187 | "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x, timecode=0x%x\n", | ||
3188 | hdspm->control_register, hdspm->control2_register, | ||
3189 | status, status2, timecode); | ||
3190 | |||
3191 | snd_iprintf(buffer, "--- Settings ---\n"); | ||
3192 | |||
3193 | x = 1 << (6 + | ||
3194 | hdspm_decode_latency(hdspm-> | ||
3195 | control_register & | ||
3196 | HDSPM_LatencyMask)); | ||
3197 | |||
3198 | snd_iprintf(buffer, | ||
3199 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", | ||
3200 | x, (unsigned long) hdspm->period_bytes); | ||
3201 | |||
3202 | snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n", | ||
3203 | (hdspm-> | ||
3204 | control_register & HDSPM_LineOut) ? "on " : "off", | ||
3205 | (hdspm->precise_ptr) ? "on" : "off"); | ||
3206 | |||
3207 | snd_iprintf(buffer, | ||
3208 | "ClearTrackMarker %s, Emphasis %s, Dolby %s\n", | ||
3209 | (hdspm-> | ||
3210 | control_register & HDSPM_clr_tms) ? "on" : "off", | ||
3211 | (hdspm-> | ||
3212 | control_register & HDSPM_Emphasis) ? "on" : "off", | ||
3213 | (hdspm-> | ||
3214 | control_register & HDSPM_Dolby) ? "on" : "off"); | ||
3215 | |||
3216 | switch (hdspm_clock_source(hdspm)) { | ||
3217 | case HDSPM_CLOCK_SOURCE_AUTOSYNC: | ||
3218 | clock_source = "AutoSync"; | ||
3219 | break; | ||
3220 | case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ: | ||
3221 | clock_source = "Internal 32 kHz"; | ||
3222 | break; | ||
3223 | case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ: | ||
3224 | clock_source = "Internal 44.1 kHz"; | ||
3225 | break; | ||
3226 | case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ: | ||
3227 | clock_source = "Internal 48 kHz"; | ||
3228 | break; | ||
3229 | case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ: | ||
3230 | clock_source = "Internal 64 kHz"; | ||
3231 | break; | ||
3232 | case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ: | ||
3233 | clock_source = "Internal 88.2 kHz"; | ||
3234 | break; | ||
3235 | case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ: | ||
3236 | clock_source = "Internal 96 kHz"; | ||
3237 | break; | ||
3238 | case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ: | ||
3239 | clock_source = "Internal 128 kHz"; | ||
3240 | break; | ||
3241 | case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ: | ||
3242 | clock_source = "Internal 176.4 kHz"; | ||
3243 | break; | ||
3244 | case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ: | ||
3245 | clock_source = "Internal 192 kHz"; | ||
3246 | break; | ||
3247 | default: | ||
3248 | clock_source = "Error"; | ||
3249 | } | ||
3250 | snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source); | ||
3251 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) | ||
3252 | system_clock_mode = "Slave"; | ||
3253 | else | ||
3254 | system_clock_mode = "Master"; | ||
3255 | snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode); | ||
3256 | |||
3257 | pref_syncref = hdspm_pref_sync_ref(hdspm); | ||
3258 | if (pref_syncref == 0) | ||
3259 | snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n"); | ||
3260 | else | ||
3261 | snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n", | ||
3262 | pref_syncref); | ||
3263 | |||
3264 | snd_iprintf(buffer, "System Clock Frequency: %d\n", | ||
3265 | hdspm->system_sample_rate); | ||
3266 | |||
3267 | snd_iprintf(buffer, "Double speed: %s\n", | ||
3268 | hdspm->control_register & HDSPM_DS_DoubleWire? | ||
3269 | "Double wire" : "Single wire"); | ||
3270 | snd_iprintf(buffer, "Quad speed: %s\n", | ||
3271 | hdspm->control_register & HDSPM_QS_DoubleWire? | ||
3272 | "Double wire" : | ||
3273 | hdspm->control_register & HDSPM_QS_QuadWire? | ||
3274 | "Quad wire" : "Single wire"); | ||
3275 | |||
3276 | snd_iprintf(buffer, "--- Status:\n"); | ||
3277 | |||
3278 | snd_iprintf(buffer, "Word: %s Frequency: %d\n", | ||
3279 | (status & HDSPM_AES32_wcLock)? "Sync " : "No Lock", | ||
3280 | HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF)); | ||
3281 | |||
3282 | for (x = 0; x < 8; x++) { | ||
3283 | snd_iprintf(buffer, "AES%d: %s Frequency: %d\n", | ||
3284 | x+1, | ||
3285 | (status2 & (HDSPM_LockAES >> x))? "Sync ": "No Lock", | ||
3286 | HDSPM_bit2freq((timecode >> (4*x)) & 0xF)); | ||
3287 | } | ||
3288 | |||
3289 | switch (hdspm_autosync_ref(hdspm)) { | ||
3290 | case HDSPM_AES32_AUTOSYNC_FROM_NONE: autosync_ref="None"; break; | ||
3291 | case HDSPM_AES32_AUTOSYNC_FROM_WORD: autosync_ref="Word Clock"; break; | ||
3292 | case HDSPM_AES32_AUTOSYNC_FROM_AES1: autosync_ref="AES1"; break; | ||
3293 | case HDSPM_AES32_AUTOSYNC_FROM_AES2: autosync_ref="AES2"; break; | ||
3294 | case HDSPM_AES32_AUTOSYNC_FROM_AES3: autosync_ref="AES3"; break; | ||
3295 | case HDSPM_AES32_AUTOSYNC_FROM_AES4: autosync_ref="AES4"; break; | ||
3296 | case HDSPM_AES32_AUTOSYNC_FROM_AES5: autosync_ref="AES5"; break; | ||
3297 | case HDSPM_AES32_AUTOSYNC_FROM_AES6: autosync_ref="AES6"; break; | ||
3298 | case HDSPM_AES32_AUTOSYNC_FROM_AES7: autosync_ref="AES7"; break; | ||
3299 | case HDSPM_AES32_AUTOSYNC_FROM_AES8: autosync_ref="AES8"; break; | ||
3300 | default: autosync_ref = "---"; break; | ||
3301 | } | ||
3302 | snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref); | ||
3303 | |||
3304 | snd_iprintf(buffer, "\n"); | ||
3305 | } | ||
3306 | |||
3307 | #ifdef CONFIG_SND_DEBUG | ||
3308 | static void | ||
3309 | snd_hdspm_proc_read_debug(struct snd_info_entry * entry, | ||
3310 | struct snd_info_buffer *buffer) | ||
3311 | { | ||
3312 | struct hdspm *hdspm = (struct hdspm *)entry->private_data; | ||
3313 | |||
3314 | int j,i; | ||
3315 | |||
3316 | for (i = 0; i < 256 /* 1024*64 */; i += j) | ||
3317 | { | ||
3318 | snd_iprintf(buffer, "0x%08X: ", i); | ||
3319 | for (j = 0; j < 16; j += 4) | ||
3320 | snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j)); | ||
3321 | snd_iprintf(buffer, "\n"); | ||
3322 | } | ||
3323 | } | ||
3324 | #endif | ||
3325 | |||
3326 | |||
3327 | |||
2487 | static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm) | 3328 | static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm) |
2488 | { | 3329 | { |
2489 | struct snd_info_entry *entry; | 3330 | struct snd_info_entry *entry; |
2490 | 3331 | ||
2491 | if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) | 3332 | if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) |
2492 | snd_info_set_text_ops(entry, hdspm, | 3333 | snd_info_set_text_ops(entry, hdspm, |
2493 | snd_hdspm_proc_read); | 3334 | hdspm->is_aes32 ? |
3335 | snd_hdspm_proc_read_aes32 : | ||
3336 | snd_hdspm_proc_read_madi); | ||
3337 | #ifdef CONFIG_SND_DEBUG | ||
3338 | /* debug file to read all hdspm registers */ | ||
3339 | if (!snd_card_proc_new(hdspm->card, "debug", &entry)) | ||
3340 | snd_info_set_text_ops(entry, hdspm, | ||
3341 | snd_hdspm_proc_read_debug); | ||
3342 | #endif | ||
2494 | } | 3343 | } |
2495 | 3344 | ||
2496 | /*------------------------------------------------------------ | 3345 | /*------------------------------------------------------------ |
@@ -2507,13 +3356,20 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm) | |||
2507 | 3356 | ||
2508 | /* set defaults: */ | 3357 | /* set defaults: */ |
2509 | 3358 | ||
2510 | hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */ | 3359 | if (hdspm->is_aes32) |
2511 | hdspm_encode_latency(7) | /* latency maximum = 8192 samples */ | 3360 | hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */ |
2512 | HDSPM_InputCoaxial | /* Input Coax not Optical */ | 3361 | hdspm_encode_latency(7) | /* latency maximum = 8192 samples */ |
2513 | HDSPM_SyncRef_MADI | /* Madi is syncclock */ | 3362 | HDSPM_SyncRef0 | /* AES1 is syncclock */ |
2514 | HDSPM_LineOut | /* Analog output in */ | 3363 | HDSPM_LineOut | /* Analog output in */ |
2515 | HDSPM_TX_64ch | /* transmit in 64ch mode */ | 3364 | HDSPM_Professional; /* Professional mode */ |
2516 | HDSPM_AutoInp; /* AutoInput chossing (takeover) */ | 3365 | else |
3366 | hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */ | ||
3367 | hdspm_encode_latency(7) | /* latency maximum = 8192 samples */ | ||
3368 | HDSPM_InputCoaxial | /* Input Coax not Optical */ | ||
3369 | HDSPM_SyncRef_MADI | /* Madi is syncclock */ | ||
3370 | HDSPM_LineOut | /* Analog output in */ | ||
3371 | HDSPM_TX_64ch | /* transmit in 64ch mode */ | ||
3372 | HDSPM_AutoInp; /* AutoInput chossing (takeover) */ | ||
2517 | 3373 | ||
2518 | /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */ | 3374 | /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */ |
2519 | /* ! HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */ | 3375 | /* ! HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */ |
@@ -2822,6 +3678,8 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
2822 | 3678 | ||
2823 | hdspm->playback_buffer = | 3679 | hdspm->playback_buffer = |
2824 | (unsigned char *) substream->runtime->dma_area; | 3680 | (unsigned char *) substream->runtime->dma_area; |
3681 | snd_printdd("Allocated sample buffer for playback at 0x%08X\n", | ||
3682 | hdspm->playback_buffer); | ||
2825 | } else { | 3683 | } else { |
2826 | hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn, | 3684 | hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn, |
2827 | params_channels(params)); | 3685 | params_channels(params)); |
@@ -2831,7 +3689,15 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
2831 | 3689 | ||
2832 | hdspm->capture_buffer = | 3690 | hdspm->capture_buffer = |
2833 | (unsigned char *) substream->runtime->dma_area; | 3691 | (unsigned char *) substream->runtime->dma_area; |
3692 | snd_printdd("Allocated sample buffer for capture at 0x%08X\n", | ||
3693 | hdspm->capture_buffer); | ||
2834 | } | 3694 | } |
3695 | /* | ||
3696 | snd_printdd("Allocated sample buffer for %s at 0x%08X\n", | ||
3697 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? | ||
3698 | "playback" : "capture", | ||
3699 | snd_pcm_sgbuf_get_addr(sgbuf, 0)); | ||
3700 | */ | ||
2835 | return 0; | 3701 | return 0; |
2836 | } | 3702 | } |
2837 | 3703 | ||
@@ -2982,9 +3848,10 @@ static struct snd_pcm_hardware snd_hdspm_playback_subinfo = { | |||
2982 | SNDRV_PCM_RATE_44100 | | 3848 | SNDRV_PCM_RATE_44100 | |
2983 | SNDRV_PCM_RATE_48000 | | 3849 | SNDRV_PCM_RATE_48000 | |
2984 | SNDRV_PCM_RATE_64000 | | 3850 | SNDRV_PCM_RATE_64000 | |
2985 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000), | 3851 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | |
3852 | SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ), | ||
2986 | .rate_min = 32000, | 3853 | .rate_min = 32000, |
2987 | .rate_max = 96000, | 3854 | .rate_max = 192000, |
2988 | .channels_min = 1, | 3855 | .channels_min = 1, |
2989 | .channels_max = HDSPM_MAX_CHANNELS, | 3856 | .channels_max = HDSPM_MAX_CHANNELS, |
2990 | .buffer_bytes_max = | 3857 | .buffer_bytes_max = |
@@ -3006,9 +3873,10 @@ static struct snd_pcm_hardware snd_hdspm_capture_subinfo = { | |||
3006 | SNDRV_PCM_RATE_44100 | | 3873 | SNDRV_PCM_RATE_44100 | |
3007 | SNDRV_PCM_RATE_48000 | | 3874 | SNDRV_PCM_RATE_48000 | |
3008 | SNDRV_PCM_RATE_64000 | | 3875 | SNDRV_PCM_RATE_64000 | |
3009 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000), | 3876 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | |
3877 | SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000), | ||
3010 | .rate_min = 32000, | 3878 | .rate_min = 32000, |
3011 | .rate_max = 96000, | 3879 | .rate_max = 192000, |
3012 | .channels_min = 1, | 3880 | .channels_min = 1, |
3013 | .channels_max = HDSPM_MAX_CHANNELS, | 3881 | .channels_max = HDSPM_MAX_CHANNELS, |
3014 | .buffer_bytes_max = | 3882 | .buffer_bytes_max = |
@@ -3315,7 +4183,8 @@ static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm) | |||
3315 | 4183 | ||
3316 | pcm = hdspm->pcm; | 4184 | pcm = hdspm->pcm; |
3317 | 4185 | ||
3318 | wanted = HDSPM_DMA_AREA_BYTES + 4096; /* dont know why, but it works */ | 4186 | /* wanted = HDSPM_DMA_AREA_BYTES + 4096;*/ /* dont know why, but it works */ |
4187 | wanted = HDSPM_DMA_AREA_BYTES; | ||
3319 | 4188 | ||
3320 | if ((err = | 4189 | if ((err = |
3321 | snd_pcm_lib_preallocate_pages_for_all(pcm, | 4190 | snd_pcm_lib_preallocate_pages_for_all(pcm, |
@@ -3467,9 +4336,16 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp | |||
3467 | pci_read_config_word(hdspm->pci, | 4336 | pci_read_config_word(hdspm->pci, |
3468 | PCI_CLASS_REVISION, &hdspm->firmware_rev); | 4337 | PCI_CLASS_REVISION, &hdspm->firmware_rev); |
3469 | 4338 | ||
3470 | strcpy(card->driver, "HDSPM"); | 4339 | hdspm->is_aes32 = (hdspm->firmware_rev >= HDSPM_AESREVISION); |
4340 | |||
3471 | strcpy(card->mixername, "Xilinx FPGA"); | 4341 | strcpy(card->mixername, "Xilinx FPGA"); |
3472 | hdspm->card_name = "RME HDSPM MADI"; | 4342 | if (hdspm->is_aes32) { |
4343 | strcpy(card->driver, "HDSPAES32"); | ||
4344 | hdspm->card_name = "RME HDSPM AES32"; | ||
4345 | } else { | ||
4346 | strcpy(card->driver, "HDSPM"); | ||
4347 | hdspm->card_name = "RME HDSPM MADI"; | ||
4348 | } | ||
3473 | 4349 | ||
3474 | if ((err = pci_enable_device(pci)) < 0) | 4350 | if ((err = pci_enable_device(pci)) < 0) |
3475 | return err; | 4351 | return err; |