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
51PVOID 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
74VOID  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
89CMia::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
103CMia::~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
123ECHOSTATUS 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
221ECHOSTATUS 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
261ECHOSTATUS 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
283void 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
304ECHOSTATUS 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