1626bc4beSJérôme Duval// ****************************************************************************
2626bc4beSJérôme Duval//
3626bc4beSJérôme Duval//		CMia.cpp
4626bc4beSJérôme Duval//
5626bc4beSJérôme Duval//		Implementation file for the CMia driver class.
6626bc4beSJérôme Duval//		Set editor tabs to 3 for your viewing pleasure.
7626bc4beSJérôme Duval//
8626bc4beSJérôme Duval// ----------------------------------------------------------------------------
9626bc4beSJérôme Duval//
10626bc4beSJérôme Duval// This file is part of Echo Digital Audio's generic driver library.
11626bc4beSJérôme Duval// Copyright Echo Digital Audio Corporation (c) 1998 - 2005
12626bc4beSJérôme Duval// All rights reserved
13626bc4beSJérôme Duval// www.echoaudio.com
14626bc4beSJérôme Duval//
15626bc4beSJérôme Duval// This library is free software; you can redistribute it and/or
16626bc4beSJérôme Duval// modify it under the terms of the GNU Lesser General Public
17626bc4beSJérôme Duval// License as published by the Free Software Foundation; either
18626bc4beSJérôme Duval// version 2.1 of the License, or (at your option) any later version.
19626bc4beSJérôme Duval//
20626bc4beSJérôme Duval// This library is distributed in the hope that it will be useful,
21626bc4beSJérôme Duval// but WITHOUT ANY WARRANTY; without even the implied warranty of
23626bc4beSJérôme Duval// Lesser General Public License for more details.
24626bc4beSJérôme Duval//
25626bc4beSJérôme Duval// You should have received a copy of the GNU Lesser General Public
26626bc4beSJérôme Duval// License along with this library; if not, write to the Free Software
27626bc4beSJérôme Duval// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28626bc4beSJérôme Duval//
29626bc4beSJérôme Duval// ****************************************************************************
30626bc4beSJérôme Duval
31626bc4beSJérôme Duval#include "CMia.h"
32626bc4beSJérôme Duval
33626bc4beSJérôme Duval#define MIA_ANALOG_OUTPUT_LATENCY	63
34626bc4beSJérôme Duval#define MIA_ANALOG_INPUT_LATENCY		62
35626bc4beSJérôme Duval
36626bc4beSJérôme Duval
37626bc4beSJérôme Duval
38626bc4beSJérôme Duval/****************************************************************************
39626bc4beSJérôme Duval
40626bc4beSJérôme Duval	Construction and destruction
41626bc4beSJérôme Duval
42626bc4beSJérôme Duval ****************************************************************************/
43626bc4beSJérôme Duval
44626bc4beSJérôme Duval//===========================================================================
45626bc4beSJérôme Duval//
46626bc4beSJérôme Duval// Overload new & delete so memory for this object is allocated
47626bc4beSJérôme Duval//	from non-paged memory.
48626bc4beSJérôme Duval//
49626bc4beSJérôme Duval//===========================================================================
50626bc4beSJérôme Duval
51626bc4beSJérôme DuvalPVOID CMia::operator new( size_t Size )
52626bc4beSJérôme Duval{
53626bc4beSJérôme Duval	PVOID 		pMemory;
54626bc4beSJérôme Duval	ECHOSTATUS 	Status;
55626bc4beSJérôme Duval
56626bc4beSJérôme Duval	Status = OsAllocateNonPaged(Size,&pMemory);
57626bc4beSJérôme Duval
58626bc4beSJérôme Duval	if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory ))
59626bc4beSJérôme Duval	{
60626bc4beSJérôme Duval		ECHO_DEBUGPRINTF(("CMia::operator new - memory allocation failed\n"));
61626bc4beSJérôme Duval
62626bc4beSJérôme Duval		pMemory = NULL;
63626bc4beSJérôme Duval	}
64626bc4beSJérôme Duval	else
65626bc4beSJérôme Duval	{
66626bc4beSJérôme Duval		memset( pMemory, 0, Size );
67626bc4beSJérôme Duval	}
68626bc4beSJérôme Duval
69626bc4beSJérôme Duval	return pMemory;
70626bc4beSJérôme Duval
71626bc4beSJérôme Duval}	// PVOID CMia::operator new( size_t Size )
72626bc4beSJérôme Duval
73626bc4beSJérôme Duval
74626bc4beSJérôme DuvalVOID  CMia::operator delete( PVOID pVoid )
75626bc4beSJérôme Duval{
76626bc4beSJérôme Duval	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
77626bc4beSJérôme Duval	{
78626bc4beSJérôme Duval		ECHO_DEBUGPRINTF(("CMia::operator delete memory free failed\n"));
79626bc4beSJérôme Duval	}
80626bc4beSJérôme Duval}	// VOID CMia::operator delete( PVOID pVoid )
81626bc4beSJérôme Duval
82626bc4beSJérôme Duval
83626bc4beSJérôme Duval//===========================================================================
84626bc4beSJérôme Duval//
85626bc4beSJérôme Duval// Constructor and destructor
86626bc4beSJérôme Duval//
87626bc4beSJérôme Duval//===========================================================================
88626bc4beSJérôme Duval
89626bc4beSJérôme DuvalCMia::CMia( PCOsSupport pOsSupport )
90626bc4beSJérôme Duval	  : CEchoGalsVmixer( pOsSupport )
91626bc4beSJérôme Duval{
92626bc4beSJérôme Duval	ECHO_DEBUGPRINTF( ( "CMia::CMia() is born!\n" ) );
93626bc4beSJérôme Duval
94626bc4beSJérôme Duval	//
95626bc4beSJérôme Duval	// Mia's virtual outputs make things tricky, since a pipe can
96626bc4beSJérôme Duval	// go to either bus.
97626bc4beSJérôme Duval	//
98626bc4beSJérôme Duval	m_wAnalogOutputLatency = MIA_ANALOG_OUTPUT_LATENCY;
99626bc4beSJérôme Duval	m_wAnalogInputLatency = MIA_ANALOG_INPUT_LATENCY;
100626bc4beSJérôme Duval
101626bc4beSJérôme Duval}
102626bc4beSJérôme Duval
103626bc4beSJérôme DuvalCMia::~CMia()
104626bc4beSJérôme Duval{
105626bc4beSJérôme Duval	ECHO_DEBUGPRINTF( ( "CMia::~CMia() is toast!\n" ) );
106626bc4beSJérôme Duval}
107626bc4beSJérôme Duval
108626bc4beSJérôme Duval
109626bc4beSJérôme Duval
110626bc4beSJérôme Duval
111626bc4beSJérôme Duval/****************************************************************************
112626bc4beSJérôme Duval
113626bc4beSJérôme Duval	Setup and hardware initialization
114626bc4beSJérôme Duval
115626bc4beSJérôme Duval ****************************************************************************/
116626bc4beSJérôme Duval
117626bc4beSJérôme Duval//===========================================================================
118626bc4beSJérôme Duval//
119626bc4beSJérôme Duval// Every card has an InitHw method
120626bc4beSJérôme Duval//
121626bc4beSJérôme Duval//===========================================================================
122626bc4beSJérôme Duval
123626bc4beSJérôme DuvalECHOSTATUS CMia::InitHw()
124626bc4beSJérôme Duval{
125626bc4beSJérôme Duval	ECHOSTATUS	Status;
126626bc4beSJérôme Duval	WORD			i;
127626bc4beSJérôme Duval
128626bc4beSJérôme Duval	//
129626bc4beSJérôme Duval	// Call the base method
130626bc4beSJérôme Duval	//
131626bc4beSJérôme Duval	if ( ECHOSTATUS_OK != ( Status = CEchoGals::InitHw() ) )
132626bc4beSJérôme Duval		return Status;
133626bc4beSJérôme Duval
134626bc4beSJérôme Duval	//
135626bc4beSJérôme Duval	// Create the DSP comm object
136626bc4beSJérôme Duval	//
1374dd9e436SJérôme Duval	ECHO_ASSERT(NULL == m_pDspCommObject );
138626bc4beSJérôme Duval	m_pDspCommObject = new CMiaDspCommObject( (PDWORD) m_pvSharedMemory,
139626bc4beSJérôme Duval															 m_pOsSupport );
140626bc4beSJérôme Duval	if (NULL == m_pDspCommObject)
141626bc4beSJérôme Duval	{
142626bc4beSJérôme Duval		ECHO_DEBUGPRINTF(("CMia::InitHw - could not create DSP comm object\n"));
143626bc4beSJérôme Duval		return ECHOSTATUS_NO_MEM;
144626bc4beSJérôme Duval	}
145626bc4beSJérôme Duval
146626bc4beSJérôme Duval	//
147626bc4beSJérôme Duval	// Load the DSP
148626bc4beSJérôme Duval	//
149626bc4beSJérôme Duval	GetDspCommObject()->LoadFirmware();
150626bc4beSJérôme Duval	if ( GetDspCommObject()->IsBoardBad() )
151626bc4beSJérôme Duval		return ECHOSTATUS_DSP_DEAD;
152626bc4beSJérôme Duval
153626bc4beSJérôme Duval	//
154626bc4beSJérôme Duval	// Clear the "bad board" flag; set the flags to indicate that
155626bc4beSJérôme Duval	// Mia can handle super-interleave.
156626bc4beSJérôme Duval	//
157626bc4beSJérôme Duval	m_wFlags &= ~ECHOGALS_FLAG_BADBOARD;
158626bc4beSJérôme Duval	m_wFlags |= ECHOGALS_ROFLAG_SUPER_INTERLEAVE_OK;
159626bc4beSJérôme Duval
160626bc4beSJérôme Duval	//
161626bc4beSJérôme Duval	//	Must call this here after DSP is init to
162626bc4beSJérôme Duval	//	init gains and mutes
163626bc4beSJérôme Duval	//
164626bc4beSJérôme Duval	Status = InitLineLevels();
165626bc4beSJérôme Duval	if ( ECHOSTATUS_OK != Status )
166626bc4beSJérôme Duval		return Status;
167626bc4beSJérôme Duval
168626bc4beSJérôme Duval	//
169626bc4beSJérôme Duval	// Set defaults for +4/-10
170626bc4beSJérôme Duval	//
171626bc4beSJérôme Duval	for (i = 0; i < GetFirstDigitalBusOut(); i++ )
172626bc4beSJérôme Duval	{
173626bc4beSJérôme Duval		GetDspCommObject()->
174626bc4beSJérôme Duval			SetNominalLevel( i, FALSE );	// FALSE is +4 here
175626bc4beSJérôme Duval	}
176626bc4beSJérôme Duval	for ( i = 0; i < GetFirstDigitalBusIn(); i++ )
177626bc4beSJérôme Duval	{
178626bc4beSJérôme Duval		GetDspCommObject()->
179626bc4beSJérôme Duval			SetNominalLevel( GetNumBussesOut() + i, FALSE );
180626bc4beSJérôme Duval	}
181626bc4beSJérôme Duval
182626bc4beSJérôme Duval	//
183626bc4beSJérôme Duval	// Set the digital mode to S/PDIF RCA
184626bc4beSJérôme Duval	//
185626bc4beSJérôme Duval	SetDigitalMode( DIGITAL_MODE_SPDIF_RCA );
186626bc4beSJérôme Duval
187626bc4beSJérôme Duval	//
188626bc4beSJérôme Duval	//	Get default sample rate from DSP
189626bc4beSJérôme Duval	//
190626bc4beSJérôme Duval	m_dwSampleRate = GetDspCommObject()->GetSampleRate();
191626bc4beSJérôme Duval
192626bc4beSJérôme Duval	//
193626bc4beSJérôme Duval	// Is this a Mia MIDI card?
194626bc4beSJérôme Duval	//
195626bc4beSJérôme Duval	if (MIA_MIDI_REV == m_pOsSupport->GetCardRev())
196626bc4beSJérôme Duval	{
197626bc4beSJérôme Duval		Status = m_MidiIn.Init( this );
198626bc4beSJérôme Duval	}
199626bc4beSJérôme Duval
200626bc4beSJérôme Duval
201626bc4beSJérôme Duval	ECHO_DEBUGPRINTF( ( "CMia::InitHw()\n" ) );
202626bc4beSJérôme Duval	return Status;
203626bc4beSJérôme Duval
204626bc4beSJérôme Duval}	// ECHOSTATUS CMia::InitHw()
205626bc4beSJérôme Duval
206626bc4beSJérôme Duval
207626bc4beSJérôme Duval
208626bc4beSJérôme Duval
209626bc4beSJérôme Duval/****************************************************************************
210626bc4beSJérôme Duval
211626bc4beSJérôme Duval	Informational methods
212626bc4beSJérôme Duval
213626bc4beSJérôme Duval ****************************************************************************/
214626bc4beSJérôme Duval
215626bc4beSJérôme Duval//===========================================================================
216626bc4beSJérôme Duval//
217626bc4beSJérôme Duval// Override GetCapabilities to enumerate unique capabilties for this card
218626bc4beSJérôme Duval//
219626bc4beSJérôme Duval//===========================================================================
220626bc4beSJérôme Duval
221626bc4beSJérôme DuvalECHOSTATUS CMia::GetCapabilities
222626bc4beSJérôme Duval(
223626bc4beSJérôme Duval	PECHOGALS_CAPS	pCapabilities
224626bc4beSJérôme Duval)
225626bc4beSJérôme Duval{
226626bc4beSJérôme Duval	ECHOSTATUS	Status;
227626bc4beSJérôme Duval	WORD			i;
228626bc4beSJérôme Duval
229626bc4beSJérôme Duval	Status = GetBaseCapabilities(pCapabilities);
230626bc4beSJérôme Duval	if ( ECHOSTATUS_OK != Status )
231626bc4beSJérôme Duval		return Status;
232626bc4beSJérôme Duval
233626bc4beSJérôme Duval	//
234626bc4beSJérôme Duval	// Add nominal level control to analog ins & outs
235626bc4beSJérôme Duval	//
236626bc4beSJérôme Duval	for (i = 0 ; i < GetFirstDigitalBusOut(); i++)
237626bc4beSJérôme Duval	{
238626bc4beSJérôme Duval		pCapabilities->dwBusOutCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
239626bc4beSJérôme Duval	}
240626bc4beSJérôme Duval
241626bc4beSJérôme Duval	for (i = 0 ; i < GetFirstDigitalBusIn(); i++)
242626bc4beSJérôme Duval	{
243626bc4beSJérôme Duval		pCapabilities->dwBusInCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
244626bc4beSJérôme Duval	}
245626bc4beSJérôme Duval
246626bc4beSJérôme Duval	pCapabilities->dwInClockTypes |= ECHO_CLOCK_BIT_SPDIF;
247626bc4beSJérôme Duval	pCapabilities->dwOutClockTypes = 0;
248626bc4beSJérôme Duval
249626bc4beSJérôme Duval	return Status;
250626bc4beSJérôme Duval
251626bc4beSJérôme Duval}	// ECHOSTATUS CMia::GetCapabilities
252626bc4beSJérôme Duval
253626bc4beSJérôme Duval
254626bc4beSJérôme Duval//===========================================================================
255626bc4beSJérôme Duval//
256626bc4beSJérôme Duval// QueryAudioSampleRate is used to find out if this card can handle a
257626bc4beSJérôme Duval// given sample rate.
258626bc4beSJérôme Duval//
259626bc4beSJérôme Duval//===========================================================================
260626bc4beSJérôme Duval
261626bc4beSJérôme DuvalECHOSTATUS CMia::QueryAudioSampleRate
262626bc4beSJérôme Duval(
263626bc4beSJérôme Duval	DWORD		dwSampleRate
264626bc4beSJérôme Duval)
265626bc4beSJérôme Duval{
266626bc4beSJérôme Duval	if ( dwSampleRate != 32000 &&
267626bc4beSJérôme Duval		  dwSampleRate != 44100 &&
268626bc4beSJérôme Duval		  dwSampleRate != 48000 &&
269626bc4beSJérôme Duval		  dwSampleRate != 88200 &&
270626bc4beSJérôme Duval		  dwSampleRate != 96000 )
271626bc4beSJérôme Duval	{
272626bc4beSJérôme Duval		ECHO_DEBUGPRINTF(
273626bc4beSJérôme Duval			("CMia::QueryAudioSampleRate() - rate %ld invalid\n",dwSampleRate) );
274626bc4beSJérôme Duval		return ECHOSTATUS_BAD_FORMAT;
275626bc4beSJérôme Duval	}
276626bc4beSJérôme Duval
277626bc4beSJérôme Duval	ECHO_DEBUGPRINTF( ( "CMia::QueryAudioSampleRate()\n" ) );
278626bc4beSJérôme Duval	return ECHOSTATUS_OK;
279626bc4beSJérôme Duval
280626bc4beSJérôme Duval}	// ECHOSTATUS CMia::QueryAudioSampleRate
281626bc4beSJérôme Duval
282626bc4beSJérôme Duval
2834dd9e436SJérôme Duvalvoid CMia::QuerySampleRateRange(DWORD &dwMinRate,DWORD &dwMaxRate)
2844dd9e436SJérôme Duval{
2854dd9e436SJérôme Duval	dwMinRate = 32000;
2864dd9e436SJérôme Duval	dwMaxRate = 96000;
2874dd9e436SJérôme Duval}
2884dd9e436SJérôme Duval
2894dd9e436SJérôme Duval
2904dd9e436SJérôme Duval
291626bc4beSJérôme Duval//===========================================================================
292626bc4beSJérôme Duval//
293626bc4beSJérôme Duval// GetInputClockDetect returns a bitmask consisting of all the input
294626bc4beSJérôme Duval// clocks currently connected to the hardware; this changes as the user
295626bc4beSJérôme Duval// connects and disconnects clock inputs.
296626bc4beSJérôme Duval//
297626bc4beSJérôme Duval// You should use this information to determine which clocks the user is
298626bc4beSJérôme Duval// allowed to select.
299626bc4beSJérôme Duval//
300626bc4beSJérôme Duval// Mia supports S/PDIF input clock.
301626bc4beSJérôme Duval//
302626bc4beSJérôme Duval//===========================================================================
303626bc4beSJérôme Duval
304626bc4beSJérôme DuvalECHOSTATUS CMia::GetInputClockDetect(DWORD &dwClockDetectBits)
305626bc4beSJérôme Duval{
306626bc4beSJérôme Duval	//ECHO_DEBUGPRINTF(("CMia::GetInputClockDetect\n"));
307626bc4beSJérôme Duval
308626bc4beSJérôme Duval	if ( NULL == GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
309626bc4beSJérôme Duval	{
310626bc4beSJérôme Duval		//ECHO_DEBUGPRINTF( ("CMia::GetInputClockDetect: DSP Dead!\n") );
311626bc4beSJérôme Duval		return ECHOSTATUS_DSP_DEAD;
312626bc4beSJérôme Duval	}
313626bc4beSJérôme Duval
314626bc4beSJérôme Duval	//
315626bc4beSJérôme Duval	// Map the DSP clock detect bits to the generic driver clock detect bits
316626bc4beSJérôme Duval	//
317626bc4beSJérôme Duval	DWORD dwClocksFromDsp = GetDspCommObject()->GetInputClockDetect();
318626bc4beSJérôme Duval
319626bc4beSJérôme Duval	dwClockDetectBits = ECHO_CLOCK_BIT_INTERNAL;
320626bc4beSJérôme Duval
321626bc4beSJérôme Duval	if (0 != (dwClocksFromDsp & GLDM_CLOCK_DETECT_BIT_SPDIF))
322626bc4beSJérôme Duval		dwClockDetectBits |= ECHO_CLOCK_BIT_SPDIF;
323626bc4beSJérôme Duval
324626bc4beSJérôme Duval	return ECHOSTATUS_OK;
325626bc4beSJérôme Duval
326626bc4beSJérôme Duval}	// GetInputClockDetect
327626bc4beSJérôme Duval
328626bc4beSJérôme Duval
329626bc4beSJérôme Duval
330626bc4beSJérôme Duval// *** Mia.cpp ***