1// ****************************************************************************
2//
3//		CMona.cpp
4//
5//		Implementation file for the CMona 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 "CMona.h"
32
33#define MONA_ANALOG_OUTPUT_LATENCY		59
34#define MONA_ANALOG_INPUT_LATENCY		71
35#define MONA_DIGITAL_OUTPUT_LATENCY		32
36#define MONA_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 CMona::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(("CMona::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 CMona::operator new( size_t Size )
74
75
76VOID  CMona::operator delete( PVOID pVoid )
77{
78	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
79	{
80		ECHO_DEBUGPRINTF(("CMona::operator delete memory free failed\n"));
81	}
82}	// VOID CMona::operator delete( PVOID pVoid )
83
84
85//===========================================================================
86//
87// Constructor and destructor
88//
89//===========================================================================
90
91CMona::CMona( PCOsSupport pOsSupport )
92		: CEchoGals( pOsSupport )
93{
94	ECHO_DEBUGPRINTF( ( "CMona::CMona() is born!\n" ) );
95
96	m_wAnalogOutputLatency = MONA_ANALOG_OUTPUT_LATENCY;
97	m_wAnalogInputLatency = MONA_ANALOG_INPUT_LATENCY;
98	m_wDigitalOutputLatency = MONA_DIGITAL_OUTPUT_LATENCY;
99	m_wDigitalInputLatency = MONA_DIGITAL_INPUT_LATENCY;
100}
101
102CMona::~CMona()
103{
104	ECHO_DEBUGPRINTF( ( "CMona::~CMona() is toast!\n" ) );
105}
106
107
108
109
110/****************************************************************************
111
112	Setup and hardware initialization
113
114 ****************************************************************************/
115
116//===========================================================================
117//
118// Every card has an InitHw method
119//
120//===========================================================================
121
122ECHOSTATUS CMona::InitHw()
123{
124	ECHOSTATUS	Status;
125
126	//
127	// Call the base method
128	//
129	if ( ECHOSTATUS_OK != ( Status = CEchoGals::InitHw() ) )
130		return Status;
131
132	//
133	// Create the DSP comm object
134	//
135	ECHO_ASSERT(NULL == m_pDspCommObject );
136	m_pDspCommObject = new CMonaDspCommObject( (PDWORD) m_pvSharedMemory,
137															 m_pOsSupport );
138	if (NULL == m_pDspCommObject)
139	{
140		ECHO_DEBUGPRINTF(("CMona::InitHw - could not create DSP comm object\n"));
141		return ECHOSTATUS_NO_MEM;
142	}
143
144	//
145	// Load the DSP, the PCI card ASIC, and the external box ASIC
146	//
147	GetDspCommObject()->LoadFirmware();
148	if ( GetDspCommObject()->IsBoardBad() )
149		return ECHOSTATUS_DSP_DEAD;
150
151	//
152	// Clear the "bad board" flag; set the flags to indicate that
153	// Mona can handle super-interleave and supports the digital
154	// input auto-mute.
155	//
156	m_wFlags &= ~ECHOGALS_FLAG_BADBOARD;
157	m_wFlags |= ECHOGALS_ROFLAG_SUPER_INTERLEAVE_OK |
158				ECHOGALS_ROFLAG_DIGITAL_IN_AUTOMUTE;
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 the digital mode to S/PDIF RCA
170	//
171	SetDigitalMode( DIGITAL_MODE_SPDIF_RCA );
172
173	//
174	// Set the S/PDIF output format to "professional"
175	//
176	SetProfessionalSpdif( TRUE );
177
178	//
179	//	Get default sample rate from DSP
180	//
181	m_dwSampleRate = GetDspCommObject()->GetSampleRate();
182
183	ECHO_DEBUGPRINTF( ( "CMona::InitHw()\n" ) );
184	return Status;
185
186}	// ECHOSTATUS CMona::InitHw()
187
188
189
190
191/****************************************************************************
192
193	Informational methods
194
195 ****************************************************************************/
196
197//===========================================================================
198//
199// Override GetCapabilities to enumerate unique capabilties for this card
200//
201//===========================================================================
202
203ECHOSTATUS CMona::GetCapabilities
204(
205	PECHOGALS_CAPS	pCapabilities
206)
207{
208	ECHOSTATUS	Status;
209
210	Status = GetBaseCapabilities(pCapabilities);
211	if ( ECHOSTATUS_OK != Status )
212		return Status;
213
214	pCapabilities->dwInClockTypes |= ECHO_CLOCK_BIT_WORD		|
215												ECHO_CLOCK_BIT_SPDIF		|
216												ECHO_CLOCK_BIT_ADAT;
217
218	return Status;
219
220}	// ECHOSTATUS CMona::GetCapabilities
221
222
223//===========================================================================
224//
225// QueryAudioSampleRate is used to find out if this card can handle a
226// given sample rate.
227//
228//===========================================================================
229
230ECHOSTATUS CMona::QueryAudioSampleRate
231(
232	DWORD		dwSampleRate
233)
234{
235	if ( dwSampleRate !=  8000 &&
236		  dwSampleRate != 11025 &&
237		  dwSampleRate != 16000 &&
238		  dwSampleRate != 22050 &&
239		  dwSampleRate != 32000 &&
240		  dwSampleRate != 44100 &&
241		  dwSampleRate != 48000 &&
242		  dwSampleRate != 88200 &&
243		  dwSampleRate != 96000 )
244	{
245		ECHO_DEBUGPRINTF(
246			("CMona::QueryAudioSampleRate() - rate %ld invalid\n",dwSampleRate) );
247		return ECHOSTATUS_BAD_FORMAT;
248	}
249	if ( dwSampleRate >= 88200 && DIGITAL_MODE_ADAT == GetDigitalMode() )
250	{
251		ECHO_DEBUGPRINTF(
252			("CMona::QueryAudioSampleRate() Sample rate cannot be "
253			 "set to 88,200 Hz or 96,000 Hz in ADAT mode\n") );
254		return ECHOSTATUS_BAD_FORMAT;
255	}
256
257	ECHO_DEBUGPRINTF( ( "CMona::QueryAudioSampleRate()\n" ) );
258	return ECHOSTATUS_OK;
259}	// ECHOSTATUS CMona::QueryAudioSampleRate
260
261
262void CMona::QuerySampleRateRange(DWORD &dwMinRate,DWORD &dwMaxRate)
263{
264	dwMinRate = 8000;
265	dwMaxRate = 96000;
266}
267
268
269//===========================================================================
270//
271// GetInputClockDetect returns a bitmask consisting of all the input
272// clocks currently connected to the hardware; this changes as the user
273// connects and disconnects clock inputs.
274//
275// You should use this information to determine which clocks the user is
276// allowed to select.
277//
278// Mona supports S/PDIF, word, and ADAT input clocks.
279//
280//===========================================================================
281
282ECHOSTATUS CMona::GetInputClockDetect(DWORD &dwClockDetectBits)
283{
284	//ECHO_DEBUGPRINTF(("CMona::GetInputClockDetect\n"));
285
286	if ( NULL == GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
287	{
288		ECHO_DEBUGPRINTF( ("CMona::GetInputClockDetect: DSP Dead!\n") );
289		return ECHOSTATUS_DSP_DEAD;
290	}
291
292	//
293	// Map the DSP clock detect bits to the generic driver clock detect bits
294	//
295	DWORD dwClocksFromDsp = GetDspCommObject()->GetInputClockDetect();
296
297	dwClockDetectBits = ECHO_CLOCK_BIT_INTERNAL;
298
299	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_SPDIF))
300		dwClockDetectBits |= ECHO_CLOCK_BIT_SPDIF;
301
302	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_ADAT))
303		dwClockDetectBits |= ECHO_CLOCK_BIT_ADAT;
304
305	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_WORD))
306		dwClockDetectBits |= ECHO_CLOCK_BIT_WORD;
307
308	return ECHOSTATUS_OK;
309
310}	// GetInputClockDetect
311
312
313// *** CMona.cpp ***
314