1 // **************************************************************************** 2 // 3 // CGina24DspCommObject.cpp 4 // 5 // Implementation file for Gina24 DSP interface class. 6 // 7 // Copyright Echo Digital Audio Corporation (c) 1998 - 2002 8 // All rights reserved 9 // www.echoaudio.com 10 // 11 // Permission is hereby granted, free of charge, to any person obtaining a 12 // copy of this software and associated documentation files (the 13 // "Software"), to deal with the Software without restriction, including 14 // without limitation the rights to use, copy, modify, merge, publish, 15 // distribute, sublicense, and/or sell copies of the Software, and to 16 // permit persons to whom the Software is furnished to do so, subject to 17 // the following conditions: 18 // 19 // - Redistributions of source code must retain the above copyright 20 // notice, this list of conditions and the following disclaimers. 21 // 22 // - Redistributions in binary form must reproduce the above copyright 23 // notice, this list of conditions and the following disclaimers in the 24 // documentation and/or other materials provided with the distribution. 25 // 26 // - Neither the name of Echo Digital Audio, nor the names of its 27 // contributors may be used to endorse or promote products derived from 28 // this Software without specific prior written permission. 29 // 30 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 33 // IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR 34 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 35 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 36 // SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. 37 // 38 // **************************************************************************** 39 40 #include "CEchoGals.h" 41 #include "CGina24DspCommObject.h" 42 43 #include "Gina24DSP.c" 44 #include "Gina24_361DSP.c" 45 46 #include "Gina24ASIC.c" 47 #include "Gina24ASIC_361.c" 48 49 50 /**************************************************************************** 51 52 Construction and destruction 53 54 ****************************************************************************/ 55 56 //=========================================================================== 57 // 58 // Constructor 59 // 60 //=========================================================================== 61 62 CGina24DspCommObject::CGina24DspCommObject 63 ( 64 PDWORD pdwRegBase, // Virtual ptr to DSP registers 65 PCOsSupport pOsSupport 66 ) : CGMLDspCommObject( pdwRegBase, pOsSupport ) 67 { 68 strcpy( m_szCardName, "Gina24" ); 69 m_pdwDspRegBase = pdwRegBase; // Virtual addr DSP's register base 70 71 m_wNumPipesOut = 16; 72 m_wNumPipesIn = 10; 73 m_wNumBussesOut = 16; 74 m_wNumBussesIn = 10; 75 m_wFirstDigitalBusOut = 8; 76 m_wFirstDigitalBusIn = 2; 77 78 m_fHasVmixer = FALSE; 79 80 m_wNumMidiOut = 0; // # MIDI out channels 81 m_wNumMidiIn = 0; // # MIDI in channels 82 m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 44100 ); 83 // Need this in cse we start with ESYNC 84 m_bHasASIC = TRUE; 85 86 // 87 // Gina24 comes in both '301 and '361 flavors; pick the correct one. 88 // 89 if ( DEVICE_ID_56361 == m_pOsSupport->GetDeviceId() ) 90 m_pwDspCodeToLoad = pwGina24_361DSP; 91 else 92 m_pwDspCodeToLoad = pwGina24DSP; 93 94 m_byDigitalMode = DIGITAL_MODE_SPDIF_RCA; 95 m_bProfessionalSpdif = FALSE; 96 } // CGina24DspCommObject::CGina24DspCommObject( DWORD dwPhysRegBase ) 97 98 99 //=========================================================================== 100 // 101 // Destructor 102 // 103 //=========================================================================== 104 105 CGina24DspCommObject::~CGina24DspCommObject() 106 { 107 ECHO_DEBUGPRINTF(("CGina24DspCommObject::~CGina24DspCommObject - " 108 "hasta la vista!\n")); 109 } // CGina24DspCommObject::~CGina24DspCommObject() 110 111 112 113 114 /**************************************************************************** 115 116 Hardware setup and config 117 118 ****************************************************************************/ 119 120 //=========================================================================== 121 // 122 // Gina24 has an ASIC on the PCI card which must be loaded for anything 123 // interesting to happen. 124 // 125 //=========================================================================== 126 127 BOOL CGina24DspCommObject::LoadASIC() 128 { 129 DWORD dwControlReg, dwSize; 130 PBYTE pbAsic; 131 132 if ( m_bASICLoaded ) 133 return TRUE; 134 135 // 136 // Give the DSP a few milliseconds to settle down 137 // 138 m_pOsSupport->OsSnooze( 10000 ); 139 140 // 141 // Pick the correct ASIC for '301 or '361 Gina24 142 // 143 if ( DEVICE_ID_56361 == m_pOsSupport->GetDeviceId() ) 144 { 145 pbAsic = pbGina24ASIC_361; 146 dwSize = sizeof( pbGina24ASIC_361 ); 147 } 148 else 149 { 150 pbAsic = pbGina24ASIC; 151 dwSize = sizeof( pbGina24ASIC ); 152 } 153 if ( !CDspCommObject::LoadASIC( DSP_FNC_LOAD_GINA24_ASIC, 154 pbAsic, 155 dwSize ) ) 156 return FALSE; 157 158 m_pbyAsic = pbAsic; 159 160 // 161 // Now give the new ASIC a little time to set up 162 // 163 m_pOsSupport->OsSnooze( 10000 ); 164 165 // 166 // See if it worked 167 // 168 CheckAsicStatus(); 169 170 // 171 // Set up the control register if the load succeeded - 172 // 173 // 48 kHz, internal clock, S/PDIF RCA mode 174 // 175 if ( m_bASICLoaded ) 176 { 177 dwControlReg = GML_CONVERTER_ENABLE | GML_48KHZ; 178 WriteControlReg( dwControlReg ); 179 } 180 181 return m_bASICLoaded; 182 183 } // BOOL CGina24DspCommObject::LoadASIC() 184 185 186 //=========================================================================== 187 // 188 // Set the input clock to internal, S/PDIF, ADAT 189 // 190 //=========================================================================== 191 192 ECHOSTATUS CGina24DspCommObject::SetInputClock(WORD wClock) 193 { 194 BOOL bSetRate; 195 BOOL bWriteControlReg; 196 DWORD dwControlReg, dwSampleRate; 197 198 ECHO_DEBUGPRINTF( ("CGina24DspCommObject::SetInputClock:\n") ); 199 200 dwControlReg = GetControlRegister(); 201 202 // 203 // Mask off the clock select bits 204 // 205 dwControlReg &= GML_CLOCK_CLEAR_MASK; 206 dwSampleRate = GetSampleRate(); 207 208 bSetRate = FALSE; 209 bWriteControlReg = TRUE; 210 switch ( wClock ) 211 { 212 case ECHO_CLOCK_INTERNAL : 213 { 214 ECHO_DEBUGPRINTF( ( "\tSet Gina24 clock to INTERNAL\n" ) ); 215 216 // If the sample rate is out of range for some reason, set it 217 // to a reasonable value. mattg 218 if ( ( dwSampleRate < 8000 ) || 219 ( dwSampleRate > 96000 ) ) 220 { 221 dwSampleRate = 48000; 222 } 223 224 bSetRate = TRUE; 225 bWriteControlReg = FALSE; 226 227 break; 228 } // ECHO_CLOCK_INTERNAL 229 230 case ECHO_CLOCK_SPDIF : 231 { 232 if ( DIGITAL_MODE_ADAT == GetDigitalMode() ) 233 { 234 return ECHOSTATUS_CLOCK_NOT_AVAILABLE; 235 } 236 237 ECHO_DEBUGPRINTF( ( "\tSet Gina24 clock to SPDIF\n" ) ); 238 239 dwControlReg |= GML_SPDIF_CLOCK; 240 241 if ( GML_CLOCK_DETECT_BIT_SPDIF96 & GetInputClockDetect() ) 242 { 243 dwControlReg |= GML_DOUBLE_SPEED_MODE; 244 } 245 else 246 { 247 dwControlReg &= ~GML_DOUBLE_SPEED_MODE; 248 } 249 break; 250 } // ECHO_CLOCK_SPDIF 251 252 case ECHO_CLOCK_ADAT : 253 { 254 ECHO_DEBUGPRINTF( ( "\tSet Gina24 clock to ADAT\n" ) ); 255 256 if ( DIGITAL_MODE_ADAT != GetDigitalMode() ) 257 { 258 return ECHOSTATUS_CLOCK_NOT_AVAILABLE; 259 } 260 261 dwControlReg |= GML_ADAT_CLOCK; 262 dwControlReg &= ~GML_DOUBLE_SPEED_MODE; 263 break; 264 } // ECHO_CLOCK_ADAT 265 266 case ECHO_CLOCK_ESYNC : 267 { 268 ECHO_DEBUGPRINTF( ( "\tSet Gina24 clock to ESYNC\n" ) ); 269 270 dwControlReg |= GML_ESYNC_CLOCK; 271 dwControlReg &= ~GML_DOUBLE_SPEED_MODE; 272 break; 273 } // ECHO_CLOCK_ESYNC 274 275 case ECHO_CLOCK_ESYNC96 : 276 { 277 ECHO_DEBUGPRINTF( ( "\tSet Gina24 clock to ESYNC96\n" ) ); 278 279 dwControlReg |= GML_ESYNC_CLOCK | GML_DOUBLE_SPEED_MODE; 280 break; 281 } // ECHO_CLOCK_ESYNC96 282 283 default : 284 ECHO_DEBUGPRINTF(("Input clock 0x%x not supported for Gina24\n",wClock)); 285 ECHO_DEBUGBREAK(); 286 return ECHOSTATUS_CLOCK_NOT_SUPPORTED; 287 } // switch (wInputClock) 288 289 290 // 291 // Winner! Save the new input clock. 292 // 293 m_wInputClock = wClock; 294 295 // 296 // Write the control reg if that's called for 297 // 298 if ( bWriteControlReg ) 299 { 300 WriteControlReg( dwControlReg ); 301 } 302 303 // Set Gina24 sample rate to something sane if word or superword is 304 // being turned off 305 if ( bSetRate ) 306 { 307 SetSampleRate( GetSampleRate() ); 308 } 309 return ECHOSTATUS_OK; 310 311 } // ECHOSTATUS CGina24DspCommObject::SetInputClock 312 313 314 //=========================================================================== 315 // 316 // SetSampleRate 317 // 318 // Set the audio sample rate for Gina24 - fixme make this common for 319 // Gina24 & Mona 320 // 321 //=========================================================================== 322 323 DWORD CGina24DspCommObject::SetSampleRate( DWORD dwNewSampleRate ) 324 { 325 DWORD dwControlReg, dwNewClock; 326 327 // 328 // Only set the clock for internal mode. If the clock is not set to 329 // internal, try and re-set the input clock; this more transparently 330 // handles switching between single and double-speed mode 331 // 332 if ( GetInputClock() != ECHO_CLOCK_INTERNAL ) 333 { 334 ECHO_DEBUGPRINTF( ( "CGina24DspCommObject::SetSampleRate: Cannot set sample rate - " 335 "clock not set to CLK_CLOCKININTERNAL\n" ) ); 336 337 // 338 // Save the rate anyhow 339 // 340 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate ); 341 342 // 343 // Set the input clock to the current value 344 // 345 SetInputClock( m_wInputClock ); 346 347 return GetSampleRate(); 348 } 349 350 // 351 // Set the sample rate 352 // 353 dwNewClock = 0; 354 355 dwControlReg = GetControlRegister(); 356 dwControlReg &= GML_CLOCK_CLEAR_MASK; 357 dwControlReg &= GML_SPDIF_RATE_CLEAR_MASK; 358 359 switch ( dwNewSampleRate ) 360 { 361 case 96000 : 362 dwNewClock = GML_96KHZ; 363 break; 364 365 case 88200 : 366 dwNewClock = GML_88KHZ; 367 break; 368 369 case 48000 : 370 dwNewClock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1; 371 break; 372 373 case 44100 : 374 dwNewClock = GML_44KHZ; 375 // 376 // Professional mode 377 // 378 if ( dwControlReg & GML_SPDIF_PRO_MODE ) 379 { 380 dwNewClock |= GML_SPDIF_SAMPLE_RATE0; 381 } 382 break; 383 384 case 32000 : 385 dwNewClock = GML_32KHZ | 386 GML_SPDIF_SAMPLE_RATE0 | 387 GML_SPDIF_SAMPLE_RATE1; 388 break; 389 390 case 22050 : 391 dwNewClock = GML_22KHZ; 392 break; 393 394 case 16000 : 395 dwNewClock = GML_16KHZ; 396 break; 397 398 case 11025 : 399 dwNewClock = GML_11KHZ; 400 break; 401 402 case 8000 : 403 dwNewClock = GML_8KHZ; 404 break; 405 406 default : 407 ECHO_DEBUGPRINTF( ("CGina24DspCommObject::SetSampleRate: %ld " 408 "invalid!\n", dwNewSampleRate) ); 409 ECHO_DEBUGBREAK(); 410 return( GetSampleRate() ); 411 } 412 413 dwControlReg |= dwNewClock; 414 415 // 416 // Send the new value to the DSP 417 // 418 if ( ECHOSTATUS_OK == WriteControlReg( dwControlReg ) ) 419 { 420 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate ); 421 422 ECHO_DEBUGPRINTF( ("CGina24DspCommObject::SetSampleRate: %ld " 423 "clock %ld\n", dwNewSampleRate, dwNewClock) ); 424 } 425 426 return GetSampleRate(); 427 428 } // DWORD CGina24DspCommObject::SetSampleRate( DWORD dwNewSampleRate ) 429 430 431 //=========================================================================== 432 // 433 // SetDigitalMode 434 // 435 //=========================================================================== 436 437 ECHOSTATUS CGina24DspCommObject::SetDigitalMode 438 ( 439 BYTE byNewMode 440 ) 441 { 442 DWORD dwControlReg; 443 // 444 // '361 Gina24 cards do not have the S/PDIF CD-ROM mode 445 // 446 if ( DEVICE_ID_56361 == m_pOsSupport->GetDeviceId() && 447 ( DIGITAL_MODE_SPDIF_CDROM == byNewMode ) ) 448 { 449 return FALSE; 450 } 451 452 dwControlReg = GetControlRegister(); 453 // 454 // Clear the current digital mode 455 // 456 dwControlReg &= GML_DIGITAL_MODE_CLEAR_MASK; 457 458 // 459 // Tweak the control reg 460 // 461 switch ( byNewMode ) 462 { 463 default : 464 return ECHOSTATUS_DIGITAL_MODE_NOT_SUPPORTED; 465 466 case DIGITAL_MODE_SPDIF_OPTICAL : 467 468 dwControlReg |= GML_SPDIF_OPTICAL_MODE; 469 goto ChkClk; 470 471 case DIGITAL_MODE_SPDIF_CDROM : 472 473 dwControlReg |= GML_SPDIF_CDROM_MODE; 474 475 // fall through 476 477 case DIGITAL_MODE_SPDIF_RCA : 478 ChkClk: 479 // 480 // If the input clock is set to ADAT, set the 481 // input clock to internal and the sample rate to 48 KHz 482 // 483 if ( ECHO_CLOCK_ADAT == GetInputClock() ) 484 { 485 m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 48000 ); 486 SetInputClock( ECHO_CLOCK_INTERNAL ); 487 } 488 489 break; 490 491 case DIGITAL_MODE_ADAT : 492 // 493 // If the input clock is set to S/PDIF, set the 494 // input clock to internal and the sample rate to 48 KHz 495 // 496 if ( ECHO_CLOCK_SPDIF == GetInputClock() ) 497 { 498 m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 48000 ); 499 SetInputClock( ECHO_CLOCK_INTERNAL ); 500 } 501 502 dwControlReg |= GML_ADAT_MODE; 503 dwControlReg &= ~GML_DOUBLE_SPEED_MODE; 504 break; 505 } 506 507 // 508 // Write the control reg 509 // 510 WriteControlReg( dwControlReg ); 511 512 m_byDigitalMode = byNewMode; 513 514 ECHO_DEBUGPRINTF( ("CGina24DspCommObject::SetDigitalMode to %ld\n", 515 (DWORD) m_byDigitalMode) ); 516 517 return ECHOSTATUS_OK; 518 } // ECHOSTATUS CGina24DspCommObject::SetDigitalMode 519 520 521 522 523 /**************************************************************************** 524 525 Common for Gina24, Layla24, and Mona. These methods are from 526 CGMLDspCommObject, not CGina24DspCommObject; this is to avoid code 527 duplication. 528 529 ****************************************************************************/ 530 531 //=========================================================================== 532 // 533 // Set the S/PDIF output format 534 // 535 //=========================================================================== 536 537 void CGMLDspCommObject::SetProfessionalSpdif 538 ( 539 BOOL bNewStatus 540 ) 541 { 542 DWORD dwControlReg; 543 544 dwControlReg = GetControlRegister(); 545 // 546 // Clear the current S/PDIF flags 547 // 548 dwControlReg &= GML_SPDIF_FORMAT_CLEAR_MASK; 549 550 // 551 // Set the new S/PDIF flags depending on the mode 552 // 553 dwControlReg |= GML_SPDIF_TWO_CHANNEL | 554 GML_SPDIF_24_BIT | 555 GML_SPDIF_COPY_PERMIT; 556 if ( bNewStatus ) 557 { 558 // 559 // Professional mode 560 // 561 dwControlReg |= GML_SPDIF_PRO_MODE; 562 563 switch ( GetSampleRate() ) 564 { 565 case 32000 : 566 dwControlReg |= GML_SPDIF_SAMPLE_RATE0 | 567 GML_SPDIF_SAMPLE_RATE1; 568 break; 569 570 case 44100 : 571 dwControlReg |= GML_SPDIF_SAMPLE_RATE0; 572 break; 573 574 case 48000 : 575 dwControlReg |= GML_SPDIF_SAMPLE_RATE1; 576 break; 577 } 578 } 579 else 580 { 581 // 582 // Consumer mode 583 // 584 switch ( GetSampleRate() ) 585 { 586 case 32000 : 587 dwControlReg |= GML_SPDIF_SAMPLE_RATE0 | 588 GML_SPDIF_SAMPLE_RATE1; 589 break; 590 591 case 48000 : 592 dwControlReg |= GML_SPDIF_SAMPLE_RATE1; 593 break; 594 } 595 } 596 597 // 598 // Write the control reg 599 // 600 WriteControlReg( dwControlReg ); 601 602 m_bProfessionalSpdif = bNewStatus; 603 604 ECHO_DEBUGPRINTF( ("CGMLDspCommObject::SetProfessionalSpdif to %s\n", 605 ( bNewStatus ) ? "Professional" : "Consumer") ); 606 607 } // void CGina24DspCommObject::SetProfessionalSpdif( ... ) 608 609 610 611 612 //=========================================================================== 613 // 614 // WriteControlReg 615 // 616 // Most configuration of Gina24, Layla24, or Mona is 617 // accomplished by writing the control register. WriteControlReg 618 // sends the new control register value to the DSP. 619 // 620 //=========================================================================== 621 622 ECHOSTATUS CGMLDspCommObject::WriteControlReg( DWORD dwControlReg ) 623 { 624 if ( !m_bASICLoaded ) 625 return( ECHOSTATUS_ASIC_NOT_LOADED ); 626 627 if ( !WaitForHandshake() ) 628 return ECHOSTATUS_DSP_DEAD; 629 630 #ifdef DIGITAL_INPUT_AUTO_MUTE_SUPPORT 631 // 632 // Handle the digital input auto-mute 633 // 634 if (TRUE == m_fDigitalInAutoMute) 635 dwControlReg |= GML_DIGITAL_IN_AUTO_MUTE; 636 else 637 dwControlReg &= ~GML_DIGITAL_IN_AUTO_MUTE; 638 #endif 639 640 // 641 // Write the control register 642 // 643 if (dwControlReg != GetControlRegister() ) 644 { 645 SetControlRegister( dwControlReg ); 646 647 ECHO_DEBUGPRINTF( ("CGMLDspCommObject::WriteControlReg: 0x%lx\n", 648 dwControlReg) ); 649 650 ClearHandshake(); 651 return SendVector( DSP_VC_WRITE_CONTROL_REG ); 652 } 653 654 return ECHOSTATUS_OK; 655 656 } // ECHOSTATUS CGMLDspCommObject::WriteControlReg( DWORD dwControlReg ) 657 658 // **** CGina24DspCommObject.cpp **** 659