1// ****************************************************************************
2//
3//		CGina24.cpp
4//
5//		Implementation file for the CGina24 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 "CGina24.h"
32
33#define GINA24_ANALOG_OUTPUT_LATENCY		59
34#define GINA24_ANALOG_INPUT_LATENCY			71
35#define GINA24_DIGITAL_OUTPUT_LATENCY		32
36#define GINA24_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 CGina24::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(("CGina::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 CGina24::operator new( size_t Size )
74
75
76VOID  CGina24::operator delete( PVOID pVoid )
77{
78	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
79	{
80		ECHO_DEBUGPRINTF(("CGina24::operator delete memory free failed\n"));
81	}
82}	// VOID CGina24::operator delete( PVOID pVoid )
83
84
85//===========================================================================
86//
87// Constructor and destructor
88//
89//===========================================================================
90
91CGina24::CGina24( PCOsSupport pOsSupport )
92		 : CEchoGals( pOsSupport )
93{
94	ECHO_DEBUGPRINTF( ( "CGina24::CGina24() is born!\n" ) );
95
96	m_wAnalogOutputLatency = GINA24_ANALOG_OUTPUT_LATENCY;
97	m_wAnalogInputLatency = GINA24_ANALOG_INPUT_LATENCY;
98	m_wDigitalOutputLatency = GINA24_DIGITAL_OUTPUT_LATENCY;
99	m_wDigitalInputLatency = GINA24_DIGITAL_INPUT_LATENCY;
100
101}
102
103CGina24::~CGina24()
104{
105	ECHO_DEBUGPRINTF( ( "CGina24::~CGina24() 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
123ECHOSTATUS CGina24::InitHw()
124{
125	ECHOSTATUS	Status;
126
127	//
128	// Call the base method
129	//
130	if ( ECHOSTATUS_OK != ( Status = CEchoGals::InitHw() ) )
131		return Status;
132
133	//
134	// Create the DSP comm object
135	//
136	ECHO_ASSERT(NULL == m_pDspCommObject );
137	m_pDspCommObject = new CGina24DspCommObject( (PDWORD) m_pvSharedMemory,
138																 m_pOsSupport );
139	if (NULL == m_pDspCommObject)
140	{
141		ECHO_DEBUGPRINTF(("CGina24::InitHw - could not create DSP comm object\n"));
142		return ECHOSTATUS_NO_MEM;
143	}
144
145	ECHO_ASSERT(GetDspCommObject() );
146
147	//
148	// Load the DSP and the ASIC on the PCI card
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	// Gina24 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	// Set defaults for +4/-10
173	//
174	WORD i;
175	for (i = 0; i < GetFirstDigitalBusOut(); i++ )
176	{
177		Status = GetDspCommObject()->
178						SetNominalLevel( i, FALSE );	// FALSE is +4 here
179	}
180	for ( i = 0; i < GetFirstDigitalBusIn(); i++ )
181	{
182		Status = GetDspCommObject()->
183						SetNominalLevel( GetNumBussesOut() + i, FALSE );
184	}
185
186	//
187	// Set the digital mode to S/PDIF RCA
188	//
189	SetDigitalMode( DIGITAL_MODE_SPDIF_RCA );
190
191	//
192	// Set the S/PDIF output format to "professional"
193	//
194	SetProfessionalSpdif( TRUE );
195
196	//
197	//	Get default sample rate from DSP
198	//
199	m_dwSampleRate = GetDspCommObject()->GetSampleRate();
200
201	ECHO_DEBUGPRINTF( ( "CGina24::InitHw()\n" ) );
202	return Status;
203
204}	// ECHOSTATUS CGina24::InitHw()
205
206
207
208
209/****************************************************************************
210
211	Informational methods
212
213 ****************************************************************************/
214
215//===========================================================================
216//
217// Override GetCapabilities to enumerate unique capabilties for Gina24
218//
219//===========================================================================
220
221ECHOSTATUS CGina24::GetCapabilities
222(
223	PECHOGALS_CAPS	pCapabilities
224)
225{
226	ECHOSTATUS	Status;
227
228	Status = GetBaseCapabilities(pCapabilities);
229
230	//
231	// Add nominal level control to analog ins & outs
232	//
233	WORD i;
234	for (i = 0 ; i < GetFirstDigitalBusOut(); i++)
235	{
236		pCapabilities->dwBusOutCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
237	}
238
239	for (i = 0 ; i < GetFirstDigitalBusIn(); i++)
240	{
241		pCapabilities->dwBusInCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
242	}
243
244	if ( ECHOSTATUS_OK != Status )
245		return Status;
246
247	pCapabilities->dwInClockTypes |=
248		ECHO_CLOCK_BIT_SPDIF |
249		ECHO_CLOCK_BIT_ESYNC |
250		ECHO_CLOCK_BIT_ESYNC96 |
251		ECHO_CLOCK_BIT_ADAT;
252
253	return Status;
254}	// ECHOSTATUS CGina24::GetCapabilities
255
256
257//===========================================================================
258//
259// QueryAudioSampleRate is used to find out if this card can handle a
260// given sample rate.
261//
262//===========================================================================
263
264ECHOSTATUS CGina24::QueryAudioSampleRate
265(
266	DWORD		dwSampleRate
267)
268{
269	if ( dwSampleRate !=  8000 &&
270		  dwSampleRate != 11025 &&
271		  dwSampleRate != 16000 &&
272		  dwSampleRate != 22050 &&
273		  dwSampleRate != 32000 &&
274		  dwSampleRate != 44100 &&
275		  dwSampleRate != 48000 &&
276		  dwSampleRate != 88200 &&
277		  dwSampleRate != 96000 )
278	{
279		ECHO_DEBUGPRINTF(
280			("CGina24::QueryAudioSampleRate() - rate %ld invalid\n",dwSampleRate) );
281		return ECHOSTATUS_BAD_FORMAT;
282	}
283	if ( dwSampleRate >= 88200 && DIGITAL_MODE_ADAT == GetDigitalMode() )
284	{
285		ECHO_DEBUGPRINTF(
286			("CGina24::QueryAudioSampleRate() Sample rate cannot be "
287			 "set to 88,200 Hz or 96,000 Hz in ADAT mode\n") );
288		return ECHOSTATUS_BAD_FORMAT;
289	}
290
291	ECHO_DEBUGPRINTF( ( "CGina24::QueryAudioSampleRate()\n" ) );
292	return ECHOSTATUS_OK;
293}	// ECHOSTATUS CGina24::QueryAudioSampleRate
294
295
296void CGina24::QuerySampleRateRange(DWORD &dwMinRate,DWORD &dwMaxRate)
297{
298	dwMinRate = 8000;
299	dwMaxRate = 96000;
300}
301
302
303//===========================================================================
304//
305// GetInputClockDetect returns a bitmask consisting of all the input
306// clocks currently connected to the hardware; this changes as the user
307// connects and disconnects clock inputs.
308//
309// You should use this information to determine which clocks the user is
310// allowed to select.
311//
312// Gina24 supports S/PDIF, Esync, and ADAT input clocks.
313//
314//===========================================================================
315
316ECHOSTATUS CGina24::GetInputClockDetect(DWORD &dwClockDetectBits)
317{
318	//ECHO_DEBUGPRINTF(("CGina24::GetInputClockDetect\n"));
319
320	if ( NULL == GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
321	{
322		ECHO_DEBUGPRINTF( ("CGina24::GetInputClockDetect: DSP Dead!\n") );
323		return ECHOSTATUS_DSP_DEAD;
324	}
325
326	//
327	// Map the DSP clock detect bits to the generic driver clock detect bits
328	//
329	DWORD dwClocksFromDsp = GetDspCommObject()->GetInputClockDetect();
330
331	dwClockDetectBits = ECHO_CLOCK_BIT_INTERNAL;
332
333	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_SPDIF))
334		dwClockDetectBits |= ECHO_CLOCK_BIT_SPDIF;
335
336	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_ADAT))
337		dwClockDetectBits |= ECHO_CLOCK_BIT_ADAT;
338
339	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_ESYNC))
340		dwClockDetectBits |= ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96;
341
342	return ECHOSTATUS_OK;
343
344}	// GetInputClockDetect
345
346
347// *** CGina24.cpp ***
348