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 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 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 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 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 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 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 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