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
operator new(size_t Size)53 PVOID 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
operator delete(PVOID pVoid)76 VOID 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
CLayla24(PCOsSupport pOsSupport)91 CLayla24::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
~CLayla24()104 CLayla24::~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
InitHw()124 ECHOSTATUS 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
GetCapabilities(PECHOGALS_CAPS pCapabilities)229 ECHOSTATUS 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
QueryAudioSampleRate(DWORD dwSampleRate)272 ECHOSTATUS 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
326 qasr_ex:
327 ECHO_DEBUGPRINTF( ( "CLayla24::QueryAudioSampleRate() %ld Hz OK\n",
328 dwSampleRate ) );
329 return ECHOSTATUS_OK;
330 } // ECHOSTATUS CLayla24::QueryAudioSampleRate
331
332
QuerySampleRateRange(DWORD & dwMinRate,DWORD & dwMaxRate)333 void 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
GetInputClockDetect(DWORD & dwClockDetectBits)354 ECHOSTATUS 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