1// **************************************************************************** 2// 3// CLayla24.cpp 4// 5// Implementation file for the CLayla24 driver class. 6// Set editor tabs to 3 for your viewing pleasure. 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 "CLayla24.h" 32 33#define LAYLA24_ANALOG_OUTPUT_LATENCY 59 34#define LAYLA24_ANALOG_INPUT_LATENCY 71 35#define LAYLA24_DIGITAL_OUTPUT_LATENCY 32 36#define LAYLA24_DIGITAL_INPUT_LATENCY 32 37 38 39 40/**************************************************************************** 41 42 Construction and destruction 43 44 ****************************************************************************/ 45 46//=========================================================================== 47// 48// Overload new & delete so memory for this object is allocated 49// from non-paged memory. 50// 51//=========================================================================== 52 53PVOID CLayla24::operator new( size_t Size ) 54{ 55 PVOID pMemory; 56 ECHOSTATUS Status; 57 58 Status = OsAllocateNonPaged(Size,&pMemory); 59 60 if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory )) 61 { 62 ECHO_DEBUGPRINTF(("CLayla24::operator new - memory allocation failed\n")); 63 64 pMemory = NULL; 65 } 66 else 67 { 68 memset( pMemory, 0, Size ); 69 } 70 71 return pMemory; 72 73} // PVOID CLayla24::operator new( size_t Size ) 74 75 76VOID CLayla24::operator delete( PVOID pVoid ) 77{ 78 if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) ) 79 { 80 ECHO_DEBUGPRINTF( ("CLayla24::operator delete memory free failed\n") ); 81 } 82} // VOID CLayla24::operator delete( PVOID pVoid ) 83 84 85//=========================================================================== 86// 87// Constructor and destructor 88// 89//=========================================================================== 90 91CLayla24::CLayla24( PCOsSupport pOsSupport ) 92 : CEchoGalsMTC( pOsSupport ) 93{ 94 ECHO_DEBUGPRINTF( ( "CLayla24::CLayla24() is born!\n" ) ); 95 96 m_wAnalogOutputLatency = LAYLA24_ANALOG_OUTPUT_LATENCY; 97 m_wAnalogInputLatency = LAYLA24_ANALOG_INPUT_LATENCY; 98 m_wDigitalOutputLatency = LAYLA24_DIGITAL_OUTPUT_LATENCY; 99 m_wDigitalInputLatency = LAYLA24_DIGITAL_INPUT_LATENCY; 100 101} // CLayla24::CLayla24() 102 103 104CLayla24::~CLayla24() 105{ 106 ECHO_DEBUGPRINTF( ( "CLayla24::~CLayla24() is toast!\n" ) ); 107} // CLayla24::~CLayla24() 108 109 110 111 112/**************************************************************************** 113 114 Setup and hardware initialization 115 116 ****************************************************************************/ 117 118//=========================================================================== 119// 120// Every card has an InitHw method 121// 122//=========================================================================== 123 124ECHOSTATUS CLayla24::InitHw() 125{ 126 ECHOSTATUS Status; 127 WORD i; 128 129 // 130 // Call the base method 131 // 132 if ( ECHOSTATUS_OK != ( Status = CEchoGals::InitHw() ) ) 133 return Status; 134 135 // 136 // Create the DSP comm object 137 // 138 ECHO_ASSERT(NULL == m_pDspCommObject ); 139 m_pDspCommObject = new CLayla24DspCommObject( (PDWORD) m_pvSharedMemory, 140 m_pOsSupport ); 141 if (NULL == m_pDspCommObject) 142 { 143 ECHO_DEBUGPRINTF(("CLayla24::InitHw - could not create DSP comm object\n")); 144 return ECHOSTATUS_NO_MEM; 145 } 146 147 // 148 // Load the DSP, the PCI card ASIC, and the external box ASIC 149 // 150 GetDspCommObject()->LoadFirmware(); 151 if ( GetDspCommObject()->IsBoardBad() ) 152 return ECHOSTATUS_DSP_DEAD; 153 154 // 155 // Clear the "bad board" flag; set the flags to indicate that 156 // Layla24 can handle super-interleave and supports the digital 157 // input auto-mute. 158 // 159 m_wFlags &= ~ECHOGALS_FLAG_BADBOARD; 160 m_wFlags |= ECHOGALS_ROFLAG_SUPER_INTERLEAVE_OK | 161 ECHOGALS_ROFLAG_DIGITAL_IN_AUTOMUTE; 162 163 // 164 // Must call this here after DSP is init to 165 // init gains and mutes 166 // 167 Status = InitLineLevels(); 168 if ( ECHOSTATUS_OK != Status ) 169 return Status; 170 171 // 172 // Initialize the MIDI input 173 // 174 Status = m_MidiIn.Init( this ); 175 if ( ECHOSTATUS_OK != Status ) 176 return Status; 177 178 179 // 180 // Set defaults for +4/-10 181 // 182 for (i = 0; i < GetFirstDigitalBusOut(); i++ ) 183 { 184 GetDspCommObject()-> 185 SetNominalLevel( i, FALSE ); // FALSE is +4 here 186 } 187 188 for ( i = 0; i < GetNumBussesIn(); i++ ) 189 { 190 GetDspCommObject()-> 191 SetNominalLevel( GetNumBussesOut() + i, FALSE ); 192 } 193 194 // 195 // Set the digital mode to S/PDIF RCA 196 // 197 SetDigitalMode( DIGITAL_MODE_SPDIF_RCA ); 198 199 // 200 // Set the S/PDIF output format to "professional" 201 // 202 SetProfessionalSpdif( TRUE ); 203 204 // 205 // Get default sample rate from DSP 206 // 207 m_dwSampleRate = GetDspCommObject()->GetSampleRate(); 208 209 ECHO_DEBUGPRINTF( ( "CLayla24::InitHw()\n" ) ); 210 return Status; 211 212} // ECHOSTATUS CLayla24::InitHw() 213 214 215 216 217/**************************************************************************** 218 219 Informational methods 220 221 ****************************************************************************/ 222 223//=========================================================================== 224// 225// Override GetCapabilities to enumerate unique capabilties for this card 226// 227//=========================================================================== 228 229ECHOSTATUS CLayla24::GetCapabilities 230( 231 PECHOGALS_CAPS pCapabilities 232) 233{ 234 ECHOSTATUS Status; 235 WORD i; 236 237 Status = GetBaseCapabilities(pCapabilities); 238 239 if ( ECHOSTATUS_OK != Status ) 240 return Status; 241 242 // 243 // Add nominal level control to analog ins & outs 244 // 245 for (i = 0 ; i < GetFirstDigitalBusOut(); i++) 246 { 247 pCapabilities->dwBusOutCaps[i] |= ECHOCAPS_NOMINAL_LEVEL; 248 } 249 250 for (i = 0 ; i < GetNumBussesIn(); i++) 251 { 252 pCapabilities->dwBusInCaps[i] |= ECHOCAPS_NOMINAL_LEVEL; 253 } 254 255 pCapabilities->dwInClockTypes |= ECHO_CLOCK_BIT_WORD | 256 ECHO_CLOCK_BIT_SPDIF | 257 ECHO_CLOCK_BIT_ADAT | 258 ECHO_CLOCK_BIT_MTC; 259 260 return Status; 261 262} // ECHOSTATUS CLayla24::GetCapabilities 263 264 265//=========================================================================== 266// 267// QueryAudioSampleRate is used to find out if this card can handle a 268// given sample rate. 269// 270//=========================================================================== 271 272ECHOSTATUS CLayla24::QueryAudioSampleRate 273( 274 DWORD dwSampleRate 275) 276{ 277 // 278 // Standard sample rates are allowed (like Mona & Layla24) 279 // 280 switch ( dwSampleRate ) 281 { 282 case 8000 : 283 case 11025 : 284 case 16000 : 285 case 22050 : 286 case 32000 : 287 case 44100 : 288 case 48000 : 289 goto qasr_ex; 290 291 case 88200 : 292 case 96000 : 293 294 // 295 // Double speed sample rates not allowed in ADAT mode 296 // 297 if ( DIGITAL_MODE_ADAT == GetDigitalMode() ) 298 { 299 ECHO_DEBUGPRINTF( 300 ("CLayla24::QueryAudioSampleRate() Sample rate must be < " 301 "50,000 Hz in ADAT mode\n") ); 302 return ECHOSTATUS_BAD_FORMAT; 303 } 304 goto qasr_ex; 305 } 306 307 // 308 // Any rate from 25000 to 50000 is allowed 309 // 310 if ( ( dwSampleRate >= 25000 ) && 311 ( dwSampleRate <= 50000 ) ) 312 goto qasr_ex; 313 314 // 315 // If not in ADAT mode, any rate from 50,000 to 100,000 is allowed 316 // 317 if ( DIGITAL_MODE_ADAT != GetDigitalMode() && 318 ( dwSampleRate >= 50000 ) && 319 ( dwSampleRate <= 100000 ) ) 320 goto qasr_ex; 321 322 ECHO_DEBUGPRINTF( 323 ("CLayla24::QueryAudioSampleRate() - rate %ld invalid\n",dwSampleRate) ); 324 return ECHOSTATUS_BAD_FORMAT; 325 326qasr_ex: 327 ECHO_DEBUGPRINTF( ( "CLayla24::QueryAudioSampleRate() %ld Hz OK\n", 328 dwSampleRate ) ); 329 return ECHOSTATUS_OK; 330} // ECHOSTATUS CLayla24::QueryAudioSampleRate 331 332 333void CLayla24::QuerySampleRateRange(DWORD &dwMinRate,DWORD &dwMaxRate) 334{ 335 dwMinRate = 8000; 336 dwMaxRate = 96000; 337} 338 339 340 341//=========================================================================== 342// 343// GetInputClockDetect returns a bitmask consisting of all the input 344// clocks currently connected to the hardware; this changes as the user 345// connects and disconnects clock inputs. 346// 347// You should use this information to determine which clocks the user is 348// allowed to select. 349// 350// Layla24 supports S/PDIF, word, and ADAT input clocks. 351// 352//=========================================================================== 353 354ECHOSTATUS CLayla24::GetInputClockDetect(DWORD &dwClockDetectBits) 355{ 356 if ( NULL == GetDspCommObject() || GetDspCommObject()->IsBoardBad() ) 357 { 358 ECHO_DEBUGPRINTF( ("CLayla24::GetInputClockDetect: DSP Dead!\n") ); 359 return ECHOSTATUS_DSP_DEAD; 360 } 361 362 // 363 // Map the DSP clock detect bits to the generic driver clock detect bits 364 // 365 DWORD dwClocksFromDsp = GetDspCommObject()->GetInputClockDetect(); 366 367 dwClockDetectBits = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_MTC; 368 369 if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_SPDIF)) 370 dwClockDetectBits |= ECHO_CLOCK_BIT_SPDIF; 371 372 if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_ADAT)) 373 dwClockDetectBits |= ECHO_CLOCK_BIT_ADAT; 374 375 if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_WORD)) 376 dwClockDetectBits |= ECHO_CLOCK_BIT_WORD; 377 378 return ECHOSTATUS_OK; 379 380} // GetInputClockDetect 381 382 383// *** Layla24.cpp *** 384