1// ****************************************************************************
2//
3//  	CGina24DspCommObject.cpp
4//
5//		Implementation file for Gina24 DSP interface class.
6//
7// ----------------------------------------------------------------------------
8//
9// This file is part of Echo Digital Audio's generic driver library.
10// Copyright Echo Digital Audio Corporation (c) 1998 - 2005
11// All rights reserved
12// www.echoaudio.com
13//
14// This library is free software; you can redistribute it and/or
15// modify it under the terms of the GNU Lesser General Public
16// License as published by the Free Software Foundation; either
17// version 2.1 of the License, or (at your option) any later version.
18//
19// This library is distributed in the hope that it will be useful,
20// but WITHOUT ANY WARRANTY; without even the implied warranty of
21// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22// Lesser General Public License for more details.
23//
24// You should have received a copy of the GNU Lesser General Public
25// License along with this library; if not, write to the Free Software
26// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27//
28// ****************************************************************************
29
30#include "CEchoGals.h"
31#include "CGina24DspCommObject.h"
32
33#include "Gina24DSP.c"
34#include "Gina24_361DSP.c"
35
36#include "Gina24ASIC.c"
37#include "Gina24ASIC_361.c"
38
39
40/****************************************************************************
41
42	Construction and destruction
43
44 ****************************************************************************/
45
46//===========================================================================
47//
48// Constructor
49//
50//===========================================================================
51
52CGina24DspCommObject::CGina24DspCommObject
53(
54	PDWORD		pdwRegBase,				// Virtual ptr to DSP registers
55	PCOsSupport	pOsSupport
56) : CGMLDspCommObject( pdwRegBase, pOsSupport )
57{
58	strcpy( m_szCardName, "Gina24" );
59	m_pdwDspRegBase = pdwRegBase;		// Virtual addr DSP's register base
60
61	m_wNumPipesOut = 16;
62	m_wNumPipesIn = 10;
63	m_wNumBussesOut = 16;
64	m_wNumBussesIn = 10;
65	m_wFirstDigitalBusOut = 8;
66	m_wFirstDigitalBusIn = 2;
67
68	m_fHasVmixer = FALSE;
69
70	m_wNumMidiOut = 0;					// # MIDI out channels
71	m_wNumMidiIn = 0;						// # MIDI in  channels
72	m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 44100 );
73												// Need this in cse we start with ESYNC
74	m_bHasASIC = TRUE;
75
76	//
77	//	Gina24 comes in both '301 and '361 flavors; pick the correct one.
78 	//
79	if ( DEVICE_ID_56361 == m_pOsSupport->GetDeviceId() )
80		m_pwDspCodeToLoad = pwGina24_361DSP;
81	else
82		m_pwDspCodeToLoad = pwGina24DSP;
83
84	m_byDigitalMode = DIGITAL_MODE_SPDIF_RCA;
85	m_bProfessionalSpdif = FALSE;
86}	// CGina24DspCommObject::CGina24DspCommObject( DWORD dwPhysRegBase )
87
88
89//===========================================================================
90//
91// Destructor
92//
93//===========================================================================
94
95CGina24DspCommObject::~CGina24DspCommObject()
96{
97	ECHO_DEBUGPRINTF(("CGina24DspCommObject::~CGina24DspCommObject - "
98							"hasta la vista!\n"));
99}	// CGina24DspCommObject::~CGina24DspCommObject()
100
101
102
103
104/****************************************************************************
105
106	Hardware setup and config
107
108 ****************************************************************************/
109
110//===========================================================================
111//
112// Gina24 has an ASIC on the PCI card which must be loaded for anything
113// interesting to happen.
114//
115//===========================================================================
116
117BOOL CGina24DspCommObject::LoadASIC()
118{
119	DWORD	dwControlReg, dwSize;
120	PBYTE	pbAsic;
121
122	if ( m_bASICLoaded )
123		return TRUE;
124
125	//
126	// Give the DSP a few milliseconds to settle down
127	//
128	m_pOsSupport->OsSnooze( 10000 );
129
130	//
131	// Pick the correct ASIC for '301 or '361 Gina24
132	//
133	if ( DEVICE_ID_56361 == m_pOsSupport->GetDeviceId() )
134	{
135		pbAsic = pbGina24ASIC_361;
136		dwSize = sizeof( pbGina24ASIC_361 );
137	}
138	else
139	{
140		pbAsic = pbGina24ASIC;
141		dwSize = sizeof( pbGina24ASIC );
142	}
143	if ( !CDspCommObject::LoadASIC( DSP_FNC_LOAD_GINA24_ASIC,
144											  pbAsic,
145											  dwSize ) )
146			return FALSE;
147
148	m_pbyAsic = pbAsic;
149
150	//
151	// Now give the new ASIC a little time to set up
152	//
153	m_pOsSupport->OsSnooze( 10000 );
154
155	//
156	// See if it worked
157	//
158	CheckAsicStatus();
159
160	//
161	// Set up the control register if the load succeeded -
162	//
163	// 48 kHz, internal clock, S/PDIF RCA mode
164	//
165	if ( m_bASICLoaded )
166	{
167		dwControlReg = GML_CONVERTER_ENABLE | GML_48KHZ;
168		WriteControlReg( dwControlReg, TRUE );
169	}
170
171	return m_bASICLoaded;
172
173}	// BOOL CGina24DspCommObject::LoadASIC()
174
175
176//===========================================================================
177//
178// Set the input clock to internal, S/PDIF, ADAT
179//
180//===========================================================================
181
182ECHOSTATUS CGina24DspCommObject::SetInputClock(WORD wClock)
183{
184	BOOL			bSetRate;
185	BOOL			bWriteControlReg;
186	DWORD			dwControlReg;
187
188	ECHO_DEBUGPRINTF( ("CGina24DspCommObject::SetInputClock:\n") );
189
190	dwControlReg = GetControlRegister();
191
192	//
193	// Mask off the clock select bits
194	//
195	dwControlReg &= GML_CLOCK_CLEAR_MASK;
196
197	bSetRate = FALSE;
198	bWriteControlReg = TRUE;
199	switch ( wClock )
200	{
201		case ECHO_CLOCK_INTERNAL :
202		{
203			ECHO_DEBUGPRINTF( ( "\tSet Gina24 clock to INTERNAL\n" ) );
204
205			bSetRate = TRUE;
206			bWriteControlReg = FALSE;
207			break;
208		} // ECHO_CLOCK_INTERNAL
209
210		case ECHO_CLOCK_SPDIF :
211		{
212			if ( DIGITAL_MODE_ADAT == GetDigitalMode() )
213			{
214				return ECHOSTATUS_CLOCK_NOT_AVAILABLE;
215			}
216
217			ECHO_DEBUGPRINTF( ( "\tSet Gina24 clock to SPDIF\n" ) );
218
219			dwControlReg |= GML_SPDIF_CLOCK;
220
221			if ( GML_CLOCK_DETECT_BIT_SPDIF96 & GetInputClockDetect() )
222			{
223				dwControlReg |= GML_DOUBLE_SPEED_MODE;
224			}
225			else
226			{
227				dwControlReg &= ~GML_DOUBLE_SPEED_MODE;
228			}
229			break;
230		} // ECHO_CLOCK_SPDIF
231
232		case ECHO_CLOCK_ADAT :
233		{
234			ECHO_DEBUGPRINTF( ( "\tSet Gina24 clock to ADAT\n" ) );
235
236			if ( DIGITAL_MODE_ADAT != GetDigitalMode() )
237			{
238				return ECHOSTATUS_CLOCK_NOT_AVAILABLE;
239			}
240
241			dwControlReg |= GML_ADAT_CLOCK;
242			dwControlReg &= ~GML_DOUBLE_SPEED_MODE;
243			break;
244		} // ECHO_CLOCK_ADAT
245
246		case ECHO_CLOCK_ESYNC :
247		{
248			ECHO_DEBUGPRINTF( ( "\tSet Gina24 clock to ESYNC\n" ) );
249
250			dwControlReg |= GML_ESYNC_CLOCK;
251			dwControlReg &= ~GML_DOUBLE_SPEED_MODE;
252			break;
253		} // ECHO_CLOCK_ESYNC
254
255		case ECHO_CLOCK_ESYNC96 :
256		{
257			ECHO_DEBUGPRINTF( ( "\tSet Gina24 clock to ESYNC96\n" ) );
258
259			dwControlReg |= GML_ESYNC_CLOCK | GML_DOUBLE_SPEED_MODE;
260			break;
261		} // ECHO_CLOCK_ESYNC96
262
263		default :
264			ECHO_DEBUGPRINTF(("Input clock 0x%x not supported for Gina24\n",wClock));
265			ECHO_DEBUGBREAK();
266				return ECHOSTATUS_CLOCK_NOT_SUPPORTED;
267	}	// switch (wInputClock)
268
269
270	//
271	// Winner! Save the new input clock.
272	//
273	m_wInputClock = wClock;
274
275	//
276	// Write the control reg if that's called for
277	//
278	if ( bWriteControlReg )
279	{
280		WriteControlReg( dwControlReg, TRUE );
281	}
282
283	// Set Gina24 sample rate to something sane if word or superword is
284	// being turned off
285	if ( bSetRate )
286	{
287		SetSampleRate( GetSampleRate() );
288	}
289	return ECHOSTATUS_OK;
290
291}	// ECHOSTATUS CGina24DspCommObject::SetInputClock
292
293
294//===========================================================================
295//
296// SetSampleRate
297//
298// Set the audio sample rate for Gina24
299//
300//===========================================================================
301
302DWORD CGina24DspCommObject::SetSampleRate( DWORD dwNewSampleRate )
303{
304	DWORD	dwControlReg, dwNewClock;
305
306	//
307	// Only set the clock for internal mode.  If the clock is not set to
308	// internal, try and re-set the input clock; this more transparently
309	// handles switching between single and double-speed mode
310	//
311	if ( GetInputClock() != ECHO_CLOCK_INTERNAL )
312	{
313		ECHO_DEBUGPRINTF( ( "CGina24DspCommObject::SetSampleRate: Cannot set sample rate - "
314								  "clock not set to CLK_CLOCKININTERNAL\n" ) );
315
316		//
317		// Save the rate anyhow
318		//
319		m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate );
320
321		//
322		// Set the input clock to the current value
323		//
324		SetInputClock( m_wInputClock );
325
326		return GetSampleRate();
327	}
328
329	//
330	// Set the sample rate
331	//
332	dwNewClock = 0;
333
334	dwControlReg = GetControlRegister();
335	dwControlReg &= GML_CLOCK_CLEAR_MASK;
336	dwControlReg &= GML_SPDIF_RATE_CLEAR_MASK;
337
338	switch ( dwNewSampleRate )
339	{
340		case 96000 :
341			dwNewClock = GML_96KHZ;
342			break;
343
344		case 88200 :
345			dwNewClock = GML_88KHZ;
346			break;
347
348		case 48000 :
349			dwNewClock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1;
350			break;
351
352		case 44100 :
353			dwNewClock = GML_44KHZ;
354			//
355			// Professional mode
356			//
357			if ( dwControlReg & GML_SPDIF_PRO_MODE )
358			{
359				dwNewClock |= GML_SPDIF_SAMPLE_RATE0;
360			}
361			break;
362
363		case 32000 :
364			dwNewClock = GML_32KHZ |
365							 GML_SPDIF_SAMPLE_RATE0 |
366							 GML_SPDIF_SAMPLE_RATE1;
367			break;
368
369		case 22050 :
370			dwNewClock = GML_22KHZ;
371			break;
372
373		case 16000 :
374			dwNewClock = GML_16KHZ;
375			break;
376
377		case 11025 :
378			dwNewClock = GML_11KHZ;
379			break;
380
381		case 8000 :
382			dwNewClock = GML_8KHZ;
383			break;
384
385		default :
386			ECHO_DEBUGPRINTF( ("CGina24DspCommObject::SetSampleRate: %ld "
387									 "invalid!\n", dwNewSampleRate) );
388			ECHO_DEBUGBREAK();
389			return( GetSampleRate() );
390	}
391
392	dwControlReg |= dwNewClock;
393
394	//
395	// Send the new value to the DSP
396	//
397	if ( ECHOSTATUS_OK == WriteControlReg( dwControlReg ) )
398	{
399		m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate );
400
401		ECHO_DEBUGPRINTF( ("CGina24DspCommObject::SetSampleRate: %ld "
402								 "clock %ld\n", dwNewSampleRate, dwNewClock) );
403	}
404
405	return GetSampleRate();
406
407} // DWORD CGina24DspCommObject::SetSampleRate( DWORD dwNewSampleRate )
408
409
410
411// **** CGina24DspCommObject.cpp ****
412