xref: /haiku/src/add-ons/kernel/drivers/audio/echo/generic/CGina24DspCommObject.cpp (revision 02354704729d38c3b078c696adc1bbbd33cbcf72)
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 
52 CGina24DspCommObject::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 
95 CGina24DspCommObject::~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 
117 BOOL 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 
182 ECHOSTATUS 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 
302 DWORD 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