1 // ****************************************************************************
2 //
3 // CMonaDspCommObject.cpp
4 //
5 // Implementation file for EchoGals generic driver Mona DSP
6 // interface class.
7 //
8 // ----------------------------------------------------------------------------
9 //
10 // This file is part of Echo Digital Audio's generic driver library.
11 // Copyright Echo Digital Audio Corporation (c) 1998 - 2005
12 // All rights reserved
13 // www.echoaudio.com
14 //
15 // This library is free software; you can redistribute it and/or
16 // modify it under the terms of the GNU Lesser General Public
17 // License as published by the Free Software Foundation; either
18 // version 2.1 of the License, or (at your option) any later version.
19 //
20 // This library is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 // Lesser General Public License for more details.
24 //
25 // You should have received a copy of the GNU Lesser General Public
26 // License along with this library; if not, write to the Free Software
27 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 //
29 // ****************************************************************************
30
31 #include "CEchoGals.h"
32 #include "CMonaDspCommObject.h"
33
34 #include "MonaDSP.c"
35 #include "Mona361DSP.c"
36
37 #include "Mona1ASIC48.c"
38 #include "Mona1ASIC96.c"
39 #include "Mona1ASIC48_361.c"
40 #include "Mona1ASIC96_361.c"
41 #include "Mona2ASIC.c"
42
43
44 /****************************************************************************
45
46 Construction and destruction
47
48 ****************************************************************************/
49
50 //===========================================================================
51 //
52 // Constructor
53 //
54 //===========================================================================
55
CMonaDspCommObject(PDWORD pdwRegBase,PCOsSupport pOsSupport)56 CMonaDspCommObject::CMonaDspCommObject
57 (
58 PDWORD pdwRegBase, // Virtual ptr to DSP registers
59 PCOsSupport pOsSupport
60 ) : CGMLDspCommObject( pdwRegBase, pOsSupport )
61 {
62 strcpy( m_szCardName, "Mona" );
63 m_pdwDspRegBase = pdwRegBase; // Virtual addr DSP's register base
64
65 m_wNumPipesOut = 14;
66 m_wNumPipesIn = 12;
67 m_wNumBussesOut = 14;
68 m_wNumBussesIn = 12;
69 m_wFirstDigitalBusOut = 6;
70 m_wFirstDigitalBusIn = 4;
71
72 m_bProfessionalSpdif = FALSE;
73
74 m_fHasVmixer = FALSE;
75
76 m_wNumMidiOut = 0; // # MIDI out channels
77 m_wNumMidiIn = 0; // # MIDI in channels
78 m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 44100 );
79 // Need this in cse we start with ESYNC
80 m_bHasASIC = TRUE;
81 if ( DEVICE_ID_56361 == pOsSupport->GetDeviceId() )
82 m_pwDspCodeToLoad = pwMona361DSP;
83 else
84 m_pwDspCodeToLoad = pwMonaDSP;
85
86 m_byDigitalMode = DIGITAL_MODE_SPDIF_RCA;
87 } // CMonaDspCommObject::CMonaDspCommObject( DWORD dwPhysRegBase )
88
89
90 //===========================================================================
91 //
92 // Destructor
93 //
94 //===========================================================================
95
~CMonaDspCommObject()96 CMonaDspCommObject::~CMonaDspCommObject()
97 {
98 } // CMonaDspCommObject::~CMonaDspCommObject()
99
100
101
102
103 /****************************************************************************
104
105 Hardware setup and config
106
107 ****************************************************************************/
108
109 //===========================================================================
110 //
111 // Mona has an ASIC on the PCI card and another ASIC in the external box;
112 // both need to be loaded.
113 //
114 //===========================================================================
115
LoadASIC()116 BOOL CMonaDspCommObject::LoadASIC()
117 {
118 DWORD dwControlReg;
119 PBYTE pbAsic1;
120 DWORD dwSize;
121
122 if ( m_bASICLoaded )
123 return TRUE;
124
125 m_pOsSupport->OsSnooze( 10000 );
126
127 if ( DEVICE_ID_56361 == m_pOsSupport->GetDeviceId() )
128 {
129 pbAsic1 = pbMona1ASIC48_361;
130 dwSize = sizeof( pbMona1ASIC48_361 );
131 }
132 else
133 {
134 pbAsic1 = pbMona1ASIC48;
135 dwSize = sizeof( pbMona1ASIC48 );
136 }
137 if ( !CDspCommObject::LoadASIC( DSP_FNC_LOAD_MONA_PCI_CARD_ASIC,
138 pbAsic1,
139 dwSize ) )
140 return FALSE;
141
142 m_pbyAsic = pbAsic1;
143
144 m_pOsSupport->OsSnooze( 10000 );
145
146 // Do the external one
147 if ( !CDspCommObject::LoadASIC( DSP_FNC_LOAD_MONA_EXTERNAL_ASIC,
148 pbMona2ASIC,
149 sizeof( pbMona2ASIC ) ) )
150 return FALSE;
151
152 m_pOsSupport->OsSnooze( 10000 );
153
154 CheckAsicStatus();
155
156 //
157 // Set up the control register if the load succeeded -
158 //
159 // 48 kHz, internal clock, S/PDIF RCA mode
160 //
161 if ( m_bASICLoaded )
162 {
163 dwControlReg = GML_CONVERTER_ENABLE | GML_48KHZ;
164 ECHO_DEBUGPRINTF(("CMonaDspCommObject::LoadASIC - setting control reg for 0x%lx\n",
165 dwControlReg));
166 WriteControlReg( dwControlReg, TRUE );
167 }
168
169 return m_bASICLoaded;
170
171 } // BOOL CMonaDspCommObject::LoadASIC()
172
173
174 //===========================================================================
175 //
176 // Depending on what digital mode you want, Mona needs different ASICs
177 // loaded. This function checks the ASIC needed for the new mode and sees
178 // if it matches the one already loaded.
179 //
180 //===========================================================================
181
SwitchAsic(DWORD dwMask96)182 BOOL CMonaDspCommObject::SwitchAsic( DWORD dwMask96 )
183 {
184 BYTE * pbyAsicNeeded;
185 DWORD dwAsicSize;
186
187 //
188 // Check the clock detect bits to see if this is
189 // a single-speed clock or a double-speed clock; load
190 // a new ASIC if necessary.
191 //
192 if ( DEVICE_ID_56361 == m_pOsSupport->GetDeviceId() )
193 {
194 pbyAsicNeeded = pbMona1ASIC48_361;
195 dwAsicSize = sizeof( pbMona1ASIC48_361 );
196 if ( 0 != ( dwMask96 & GetInputClockDetect() ) )
197 {
198 pbyAsicNeeded = pbMona1ASIC96_361;
199 dwAsicSize = sizeof( pbMona1ASIC96_361 );
200 }
201 }
202 else
203 {
204 pbyAsicNeeded = pbMona1ASIC48;
205 dwAsicSize = sizeof( pbMona1ASIC48 );
206 if ( 0 != ( dwMask96 & GetInputClockDetect() ) )
207 {
208 pbyAsicNeeded = pbMona1ASIC96;
209 dwAsicSize = sizeof( pbMona1ASIC96 );
210 }
211 }
212
213 if ( pbyAsicNeeded != m_pbyAsic )
214 {
215 //
216 // Load the desired ASIC
217 //
218 if ( !CDspCommObject::LoadASIC( DSP_FNC_LOAD_MONA_PCI_CARD_ASIC,
219 pbyAsicNeeded,
220 dwAsicSize ) )
221 return FALSE;
222
223 m_pbyAsic = pbyAsicNeeded;
224
225 m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 48000 );
226 }
227
228 return TRUE;
229
230 } // BOOL CMonaDspCommObject::SwitchAsic( DWORD dwMask96 )
231
232
233 //===========================================================================
234 //
235 // SetInputClock
236 //
237 //===========================================================================
238
SetInputClock(WORD wClock)239 ECHOSTATUS CMonaDspCommObject::SetInputClock(WORD wClock)
240 {
241 BOOL bSetRate;
242 BOOL bWriteControlReg;
243 DWORD dwControlReg;
244
245 ECHO_DEBUGPRINTF( ("CMonaDspCommObject::SetInputClock: clock %d\n",wClock) );
246
247 dwControlReg = GetControlRegister();
248
249 //
250 // Mask off the clock select bits
251 //
252 dwControlReg &= GML_CLOCK_CLEAR_MASK;
253
254 bSetRate = FALSE;
255 bWriteControlReg = TRUE;
256 switch ( wClock )
257 {
258 case ECHO_CLOCK_INTERNAL :
259 {
260 ECHO_DEBUGPRINTF( ( "\tSet Mona clock to INTERNAL\n" ) );
261
262 bSetRate = TRUE;
263 bWriteControlReg = FALSE;
264
265 break;
266 } // CLK_CLOCKININTERNAL
267
268 case ECHO_CLOCK_SPDIF :
269 {
270 if ( DIGITAL_MODE_ADAT == GetDigitalMode() )
271 {
272 return ECHOSTATUS_CLOCK_NOT_AVAILABLE;
273 }
274
275 if ( FALSE == SwitchAsic( GML_CLOCK_DETECT_BIT_SPDIF96 ) )
276 {
277 return ECHOSTATUS_CLOCK_NOT_AVAILABLE;
278 }
279
280 ECHO_DEBUGPRINTF( ( "\tSet Mona clock to SPDIF\n" ) );
281
282 dwControlReg |= GML_SPDIF_CLOCK;
283
284 if ( GML_CLOCK_DETECT_BIT_SPDIF96 & GetInputClockDetect() )
285 {
286 dwControlReg |= GML_DOUBLE_SPEED_MODE;
287 }
288 else
289 {
290 dwControlReg &= ~GML_DOUBLE_SPEED_MODE;
291 }
292 break;
293 } // CLK_CLOCKINSPDIF
294
295 case ECHO_CLOCK_WORD :
296 {
297 ECHO_DEBUGPRINTF( ( "\tSet Mona clock to WORD\n" ) );
298
299 if ( FALSE == SwitchAsic( GML_CLOCK_DETECT_BIT_WORD96 ) )
300 {
301 return ECHOSTATUS_CLOCK_NOT_AVAILABLE;
302 }
303
304 dwControlReg |= GML_WORD_CLOCK;
305
306 if ( GML_CLOCK_DETECT_BIT_WORD96 & GetInputClockDetect() )
307 {
308 dwControlReg |= GML_DOUBLE_SPEED_MODE;
309 }
310 else
311 {
312 dwControlReg &= ~GML_DOUBLE_SPEED_MODE;
313 }
314 break;
315 } // CLK_CLOCKINWORD
316
317 case ECHO_CLOCK_ADAT :
318 {
319 ECHO_DEBUGPRINTF( ( "\tSet Mona clock to ADAT\n" ) );
320
321 if ( DIGITAL_MODE_ADAT != GetDigitalMode() )
322 {
323 return ECHOSTATUS_CLOCK_NOT_AVAILABLE;
324 }
325
326 dwControlReg |= GML_ADAT_CLOCK;
327 dwControlReg &= ~GML_DOUBLE_SPEED_MODE;
328 break;
329 } // CLK_CLOCKINADAT
330
331 default :
332 ECHO_DEBUGPRINTF(("Input clock 0x%x not supported for Mona\n",wClock));
333 ECHO_DEBUGBREAK();
334 return ECHOSTATUS_CLOCK_NOT_SUPPORTED;
335 } // switch (wClock)
336
337 //
338 // Winner! Save the new input clock.
339 //
340 m_wInputClock = wClock;
341
342 //
343 // Do things according to the flags
344 //
345 if ( bWriteControlReg )
346 {
347 WriteControlReg( dwControlReg, TRUE );
348 }
349
350 // Set Mona sample rate to something sane if word or superword is
351 // being turned off
352 if ( bSetRate )
353 {
354 SetSampleRate( GetSampleRate() );
355 }
356
357 return ECHOSTATUS_OK;
358
359 } // ECHOSTATUS CMonaDspCommObject::SetInputClock
360
361
362
363 //===========================================================================
364 //
365 // SetSampleRate
366 //
367 // Set the audio sample rate for CMona
368 //
369 //===========================================================================
370
SetSampleRate(DWORD dwNewSampleRate)371 DWORD CMonaDspCommObject::SetSampleRate( DWORD dwNewSampleRate )
372 {
373 BYTE *pbyAsicNeeded;
374 DWORD dwAsicSize, dwControlReg, dwNewClock;
375 BOOL fForceControlReg;
376
377 ECHO_DEBUGPRINTF(("CMonaDspCommObject::SetSampleRate to %ld\n",dwNewSampleRate));
378
379 fForceControlReg = FALSE;
380
381 //
382 // Only set the clock for internal mode. If the clock is not set to
383 // internal, try and re-set the input clock; this more transparently
384 // handles switching between single and double-speed mode
385 //
386 if ( GetInputClock() != ECHO_CLOCK_INTERNAL )
387 {
388 ECHO_DEBUGPRINTF( ( "CMonaDspCommObject::SetSampleRate: Cannot set sample rate - "
389 "clock not set to CLK_CLOCKININTERNAL\n" ) );
390
391 //
392 // Save the rate anyhow
393 //
394 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate );
395
396 //
397 // Set the input clock to the current value
398 //
399 SetInputClock( m_wInputClock );
400
401 return GetSampleRate();
402 }
403
404 //
405 // Now, check to see if the required ASIC is loaded
406 //
407 if ( dwNewSampleRate >= 88200 )
408 {
409 if ( DIGITAL_MODE_ADAT == GetDigitalMode() )
410 return( GetSampleRate() );
411
412 if ( DEVICE_ID_56361 == m_pOsSupport->GetDeviceId() )
413 {
414 pbyAsicNeeded = pbMona1ASIC96_361;
415 dwAsicSize = sizeof(pbMona1ASIC96_361);
416 }
417 else
418 {
419 pbyAsicNeeded = pbMona1ASIC96;
420 dwAsicSize = sizeof(pbMona1ASIC96);
421 }
422 }
423 else
424 {
425 if ( DEVICE_ID_56361 == m_pOsSupport->GetDeviceId() )
426 {
427 pbyAsicNeeded = pbMona1ASIC48_361;
428 dwAsicSize = sizeof(pbMona1ASIC48_361);
429 }
430 else
431 {
432 pbyAsicNeeded = pbMona1ASIC48;
433 dwAsicSize = sizeof(pbMona1ASIC48);
434 }
435 }
436
437 if ( pbyAsicNeeded != m_pbyAsic )
438 {
439 ECHO_DEBUGPRINTF(("\tLoading a new ASIC\n"));
440 //
441 // Load the desired ASIC
442 //
443 if ( FALSE == CDspCommObject::LoadASIC
444 ( DSP_FNC_LOAD_MONA_PCI_CARD_ASIC,
445 pbyAsicNeeded,
446 dwAsicSize ) )
447 return( GetSampleRate() );
448
449 m_pbyAsic = pbyAsicNeeded;
450
451 fForceControlReg = TRUE;
452 }
453
454 //
455 // Get the new control register value
456 //
457 dwNewClock = 0;
458
459 dwControlReg = GetControlRegister();
460 dwControlReg &= GML_CLOCK_CLEAR_MASK;
461 dwControlReg &= GML_SPDIF_RATE_CLEAR_MASK;
462
463 switch ( dwNewSampleRate )
464 {
465 case 96000 :
466 dwNewClock = GML_96KHZ;
467 break;
468
469 case 88200 :
470 dwNewClock = GML_88KHZ;
471 break;
472
473 case 48000 :
474 dwNewClock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1;
475 break;
476
477 case 44100 :
478 dwNewClock = GML_44KHZ;
479 //
480 // Professional mode
481 //
482 if ( dwControlReg & GML_SPDIF_PRO_MODE )
483 {
484 dwNewClock |= GML_SPDIF_SAMPLE_RATE0;
485 }
486 break;
487
488 case 32000 :
489 dwNewClock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 | GML_SPDIF_SAMPLE_RATE1;
490 break;
491
492 case 22050 :
493 dwNewClock = GML_22KHZ;
494 break;
495
496 case 16000 :
497 dwNewClock = GML_16KHZ;
498 break;
499
500 case 11025 :
501 dwNewClock = GML_11KHZ;
502 break;
503
504 case 8000 :
505 dwNewClock = GML_8KHZ;
506 break;
507 }
508
509 dwControlReg |= dwNewClock;
510
511 //
512 // Send the new value to the card
513 //
514 if ( ECHOSTATUS_OK == WriteControlReg( dwControlReg, fForceControlReg ) )
515 {
516 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate );
517
518 ECHO_DEBUGPRINTF( ("CMonaDspCommObject::SetSampleRate: %ld "
519 "clock %ld\n", dwNewSampleRate, dwNewClock) );
520 }
521
522 return GetSampleRate();
523
524 } // DWORD CMonaDspCommObject::SetSampleRate( DWORD dwNewSampleRate )
525
526
527 //===========================================================================
528 //
529 // Set digital mode
530 //
531 //===========================================================================
532
SetDigitalMode(BYTE byNewMode)533 ECHOSTATUS CMonaDspCommObject::SetDigitalMode
534 (
535 BYTE byNewMode
536 )
537 {
538 ECHO_DEBUGPRINTF(("CMonaDspCommObject::SetDigitalMode %d\n",byNewMode));
539
540 //
541 // If the new mode is ADAT mode, make sure that the single speed ASIC is loaded
542 //
543 BYTE *pbAsic96;
544
545 if (DIGITAL_MODE_ADAT == byNewMode)
546 {
547 switch (m_pOsSupport->GetDeviceId())
548 {
549 case DEVICE_ID_56301 :
550 pbAsic96 = pbMona1ASIC96;
551 break;
552
553 case DEVICE_ID_56361 :
554 pbAsic96 = pbMona1ASIC96_361;
555 break;
556
557 default : // should never happen, but it's good to cover all the bases
558 return ECHOSTATUS_BAD_CARDID;
559 }
560 if (pbAsic96 == m_pbyAsic)
561 SetSampleRate( 48000 );
562 }
563
564 //
565 // Call the base class to tweak the input clock if necessary
566 //
567 return CGMLDspCommObject::SetDigitalMode(byNewMode);
568
569 } // ECHOSTATUS CMonaDspCommObject::SetDigitalMode
570
571
572 // **** CMonaDspCommObject.cpp ****
573