1 // **************************************************************************** 2 // 3 // CMia.cpp 4 // 5 // Implementation file for the CMia 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 "CMia.h" 32 33 #define MIA_ANALOG_OUTPUT_LATENCY 63 34 #define MIA_ANALOG_INPUT_LATENCY 62 35 36 37 38 /**************************************************************************** 39 40 Construction and destruction 41 42 ****************************************************************************/ 43 44 //=========================================================================== 45 // 46 // Overload new & delete so memory for this object is allocated 47 // from non-paged memory. 48 // 49 //=========================================================================== 50 51 PVOID CMia::operator new( size_t Size ) 52 { 53 PVOID pMemory; 54 ECHOSTATUS Status; 55 56 Status = OsAllocateNonPaged(Size,&pMemory); 57 58 if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory )) 59 { 60 ECHO_DEBUGPRINTF(("CMia::operator new - memory allocation failed\n")); 61 62 pMemory = NULL; 63 } 64 else 65 { 66 memset( pMemory, 0, Size ); 67 } 68 69 return pMemory; 70 71 } // PVOID CMia::operator new( size_t Size ) 72 73 74 VOID CMia::operator delete( PVOID pVoid ) 75 { 76 if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) ) 77 { 78 ECHO_DEBUGPRINTF(("CMia::operator delete memory free failed\n")); 79 } 80 } // VOID CMia::operator delete( PVOID pVoid ) 81 82 83 //=========================================================================== 84 // 85 // Constructor and destructor 86 // 87 //=========================================================================== 88 89 CMia::CMia( PCOsSupport pOsSupport ) 90 : CEchoGalsVmixer( pOsSupport ) 91 { 92 ECHO_DEBUGPRINTF( ( "CMia::CMia() is born!\n" ) ); 93 94 // 95 // Mia's virtual outputs make things tricky, since a pipe can 96 // go to either bus. 97 // 98 m_wAnalogOutputLatency = MIA_ANALOG_OUTPUT_LATENCY; 99 m_wAnalogInputLatency = MIA_ANALOG_INPUT_LATENCY; 100 101 } 102 103 CMia::~CMia() 104 { 105 ECHO_DEBUGPRINTF( ( "CMia::~CMia() is toast!\n" ) ); 106 } 107 108 109 110 111 /**************************************************************************** 112 113 Setup and hardware initialization 114 115 ****************************************************************************/ 116 117 //=========================================================================== 118 // 119 // Every card has an InitHw method 120 // 121 //=========================================================================== 122 123 ECHOSTATUS CMia::InitHw() 124 { 125 ECHOSTATUS Status; 126 WORD i; 127 128 // 129 // Call the base method 130 // 131 if ( ECHOSTATUS_OK != ( Status = CEchoGals::InitHw() ) ) 132 return Status; 133 134 // 135 // Create the DSP comm object 136 // 137 ECHO_ASSERT(NULL == m_pDspCommObject ); 138 m_pDspCommObject = new CMiaDspCommObject( (PDWORD) m_pvSharedMemory, 139 m_pOsSupport ); 140 if (NULL == m_pDspCommObject) 141 { 142 ECHO_DEBUGPRINTF(("CMia::InitHw - could not create DSP comm object\n")); 143 return ECHOSTATUS_NO_MEM; 144 } 145 146 // 147 // Load the DSP 148 // 149 GetDspCommObject()->LoadFirmware(); 150 if ( GetDspCommObject()->IsBoardBad() ) 151 return ECHOSTATUS_DSP_DEAD; 152 153 // 154 // Clear the "bad board" flag; set the flags to indicate that 155 // Mia can handle super-interleave. 156 // 157 m_wFlags &= ~ECHOGALS_FLAG_BADBOARD; 158 m_wFlags |= ECHOGALS_ROFLAG_SUPER_INTERLEAVE_OK; 159 160 // 161 // Must call this here after DSP is init to 162 // init gains and mutes 163 // 164 Status = InitLineLevels(); 165 if ( ECHOSTATUS_OK != Status ) 166 return Status; 167 168 // 169 // Set defaults for +4/-10 170 // 171 for (i = 0; i < GetFirstDigitalBusOut(); i++ ) 172 { 173 GetDspCommObject()-> 174 SetNominalLevel( i, FALSE ); // FALSE is +4 here 175 } 176 for ( i = 0; i < GetFirstDigitalBusIn(); i++ ) 177 { 178 GetDspCommObject()-> 179 SetNominalLevel( GetNumBussesOut() + i, FALSE ); 180 } 181 182 // 183 // Set the digital mode to S/PDIF RCA 184 // 185 SetDigitalMode( DIGITAL_MODE_SPDIF_RCA ); 186 187 // 188 // Get default sample rate from DSP 189 // 190 m_dwSampleRate = GetDspCommObject()->GetSampleRate(); 191 192 // 193 // Is this a Mia MIDI card? 194 // 195 if (MIA_MIDI_REV == m_pOsSupport->GetCardRev()) 196 { 197 Status = m_MidiIn.Init( this ); 198 } 199 200 201 ECHO_DEBUGPRINTF( ( "CMia::InitHw()\n" ) ); 202 return Status; 203 204 } // ECHOSTATUS CMia::InitHw() 205 206 207 208 209 /**************************************************************************** 210 211 Informational methods 212 213 ****************************************************************************/ 214 215 //=========================================================================== 216 // 217 // Override GetCapabilities to enumerate unique capabilties for this card 218 // 219 //=========================================================================== 220 221 ECHOSTATUS CMia::GetCapabilities 222 ( 223 PECHOGALS_CAPS pCapabilities 224 ) 225 { 226 ECHOSTATUS Status; 227 WORD i; 228 229 Status = GetBaseCapabilities(pCapabilities); 230 if ( ECHOSTATUS_OK != Status ) 231 return Status; 232 233 // 234 // Add nominal level control to analog ins & outs 235 // 236 for (i = 0 ; i < GetFirstDigitalBusOut(); i++) 237 { 238 pCapabilities->dwBusOutCaps[i] |= ECHOCAPS_NOMINAL_LEVEL; 239 } 240 241 for (i = 0 ; i < GetFirstDigitalBusIn(); i++) 242 { 243 pCapabilities->dwBusInCaps[i] |= ECHOCAPS_NOMINAL_LEVEL; 244 } 245 246 pCapabilities->dwInClockTypes |= ECHO_CLOCK_BIT_SPDIF; 247 pCapabilities->dwOutClockTypes = 0; 248 249 return Status; 250 251 } // ECHOSTATUS CMia::GetCapabilities 252 253 254 //=========================================================================== 255 // 256 // QueryAudioSampleRate is used to find out if this card can handle a 257 // given sample rate. 258 // 259 //=========================================================================== 260 261 ECHOSTATUS CMia::QueryAudioSampleRate 262 ( 263 DWORD dwSampleRate 264 ) 265 { 266 if ( dwSampleRate != 32000 && 267 dwSampleRate != 44100 && 268 dwSampleRate != 48000 && 269 dwSampleRate != 88200 && 270 dwSampleRate != 96000 ) 271 { 272 ECHO_DEBUGPRINTF( 273 ("CMia::QueryAudioSampleRate() - rate %ld invalid\n",dwSampleRate) ); 274 return ECHOSTATUS_BAD_FORMAT; 275 } 276 277 ECHO_DEBUGPRINTF( ( "CMia::QueryAudioSampleRate()\n" ) ); 278 return ECHOSTATUS_OK; 279 280 } // ECHOSTATUS CMia::QueryAudioSampleRate 281 282 283 void CMia::QuerySampleRateRange(DWORD &dwMinRate,DWORD &dwMaxRate) 284 { 285 dwMinRate = 32000; 286 dwMaxRate = 96000; 287 } 288 289 290 291 //=========================================================================== 292 // 293 // GetInputClockDetect returns a bitmask consisting of all the input 294 // clocks currently connected to the hardware; this changes as the user 295 // connects and disconnects clock inputs. 296 // 297 // You should use this information to determine which clocks the user is 298 // allowed to select. 299 // 300 // Mia supports S/PDIF input clock. 301 // 302 //=========================================================================== 303 304 ECHOSTATUS CMia::GetInputClockDetect(DWORD &dwClockDetectBits) 305 { 306 //ECHO_DEBUGPRINTF(("CMia::GetInputClockDetect\n")); 307 308 if ( NULL == GetDspCommObject() || GetDspCommObject()->IsBoardBad() ) 309 { 310 //ECHO_DEBUGPRINTF( ("CMia::GetInputClockDetect: DSP Dead!\n") ); 311 return ECHOSTATUS_DSP_DEAD; 312 } 313 314 // 315 // Map the DSP clock detect bits to the generic driver clock detect bits 316 // 317 DWORD dwClocksFromDsp = GetDspCommObject()->GetInputClockDetect(); 318 319 dwClockDetectBits = ECHO_CLOCK_BIT_INTERNAL; 320 321 if (0 != (dwClocksFromDsp & GLDM_CLOCK_DETECT_BIT_SPDIF)) 322 dwClockDetectBits |= ECHO_CLOCK_BIT_SPDIF; 323 324 return ECHOSTATUS_OK; 325 326 } // GetInputClockDetect 327 328 329 330 // *** Mia.cpp *** 331