xref: /haiku/src/add-ons/kernel/drivers/audio/echo/generic/CGina24.cpp (revision 4dd9e43637031d2c5a6755a0184040f0de8f2884)
1 // ****************************************************************************
2 //
3 //		CGina24.cpp
4 //
5 //		Implementation file for the CGina24 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 "CGina24.h"
32 
33 #define GINA24_ANALOG_OUTPUT_LATENCY		59
34 #define GINA24_ANALOG_INPUT_LATENCY			71
35 #define GINA24_DIGITAL_OUTPUT_LATENCY		32
36 #define GINA24_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 
operator new(size_t Size)53 PVOID CGina24::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(("CGina::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 CGina24::operator new( size_t Size )
74 
75 
operator delete(PVOID pVoid)76 VOID  CGina24::operator delete( PVOID pVoid )
77 {
78 	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
79 	{
80 		ECHO_DEBUGPRINTF(("CGina24::operator delete memory free failed\n"));
81 	}
82 }	// VOID CGina24::operator delete( PVOID pVoid )
83 
84 
85 //===========================================================================
86 //
87 // Constructor and destructor
88 //
89 //===========================================================================
90 
CGina24(PCOsSupport pOsSupport)91 CGina24::CGina24( PCOsSupport pOsSupport )
92 		 : CEchoGals( pOsSupport )
93 {
94 	ECHO_DEBUGPRINTF( ( "CGina24::CGina24() is born!\n" ) );
95 
96 	m_wAnalogOutputLatency = GINA24_ANALOG_OUTPUT_LATENCY;
97 	m_wAnalogInputLatency = GINA24_ANALOG_INPUT_LATENCY;
98 	m_wDigitalOutputLatency = GINA24_DIGITAL_OUTPUT_LATENCY;
99 	m_wDigitalInputLatency = GINA24_DIGITAL_INPUT_LATENCY;
100 
101 }
102 
~CGina24()103 CGina24::~CGina24()
104 {
105 	ECHO_DEBUGPRINTF( ( "CGina24::~CGina24() 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 
InitHw()123 ECHOSTATUS CGina24::InitHw()
124 {
125 	ECHOSTATUS	Status;
126 
127 	//
128 	// Call the base method
129 	//
130 	if ( ECHOSTATUS_OK != ( Status = CEchoGals::InitHw() ) )
131 		return Status;
132 
133 	//
134 	// Create the DSP comm object
135 	//
136 	ECHO_ASSERT(NULL == m_pDspCommObject );
137 	m_pDspCommObject = new CGina24DspCommObject( (PDWORD) m_pvSharedMemory,
138 																 m_pOsSupport );
139 	if (NULL == m_pDspCommObject)
140 	{
141 		ECHO_DEBUGPRINTF(("CGina24::InitHw - could not create DSP comm object\n"));
142 		return ECHOSTATUS_NO_MEM;
143 	}
144 
145 	ECHO_ASSERT(GetDspCommObject() );
146 
147 	//
148 	// Load the DSP and the ASIC on the PCI card
149 	//
150 	GetDspCommObject()->LoadFirmware();
151 	if ( GetDspCommObject()->IsBoardBad() )
152 		return ECHOSTATUS_DSP_DEAD;
153 
154 	//
155 	// Clear the "bad board" flag; set the flags to indicate that
156 	// Gina24 can handle super-interleave and supports the digital
157 	// input auto-mute.
158 	//
159 	m_wFlags &= ~ECHOGALS_FLAG_BADBOARD;
160 	m_wFlags |= ECHOGALS_ROFLAG_SUPER_INTERLEAVE_OK |
161 					ECHOGALS_ROFLAG_DIGITAL_IN_AUTOMUTE;
162 
163 	//
164 	//	Must call this here after DSP is init to
165 	//	init gains and mutes
166 	//
167 	Status = InitLineLevels();
168 	if ( ECHOSTATUS_OK != Status )
169 		return Status;
170 
171 	//
172 	// Set defaults for +4/-10
173 	//
174 	WORD i;
175 	for (i = 0; i < GetFirstDigitalBusOut(); i++ )
176 	{
177 		Status = GetDspCommObject()->
178 						SetNominalLevel( i, FALSE );	// FALSE is +4 here
179 	}
180 	for ( i = 0; i < GetFirstDigitalBusIn(); i++ )
181 	{
182 		Status = GetDspCommObject()->
183 						SetNominalLevel( GetNumBussesOut() + i, FALSE );
184 	}
185 
186 	//
187 	// Set the digital mode to S/PDIF RCA
188 	//
189 	SetDigitalMode( DIGITAL_MODE_SPDIF_RCA );
190 
191 	//
192 	// Set the S/PDIF output format to "professional"
193 	//
194 	SetProfessionalSpdif( TRUE );
195 
196 	//
197 	//	Get default sample rate from DSP
198 	//
199 	m_dwSampleRate = GetDspCommObject()->GetSampleRate();
200 
201 	ECHO_DEBUGPRINTF( ( "CGina24::InitHw()\n" ) );
202 	return Status;
203 
204 }	// ECHOSTATUS CGina24::InitHw()
205 
206 
207 
208 
209 /****************************************************************************
210 
211 	Informational methods
212 
213  ****************************************************************************/
214 
215 //===========================================================================
216 //
217 // Override GetCapabilities to enumerate unique capabilties for Gina24
218 //
219 //===========================================================================
220 
GetCapabilities(PECHOGALS_CAPS pCapabilities)221 ECHOSTATUS CGina24::GetCapabilities
222 (
223 	PECHOGALS_CAPS	pCapabilities
224 )
225 {
226 	ECHOSTATUS	Status;
227 
228 	Status = GetBaseCapabilities(pCapabilities);
229 
230 	//
231 	// Add nominal level control to analog ins & outs
232 	//
233 	WORD i;
234 	for (i = 0 ; i < GetFirstDigitalBusOut(); i++)
235 	{
236 		pCapabilities->dwBusOutCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
237 	}
238 
239 	for (i = 0 ; i < GetFirstDigitalBusIn(); i++)
240 	{
241 		pCapabilities->dwBusInCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
242 	}
243 
244 	if ( ECHOSTATUS_OK != Status )
245 		return Status;
246 
247 	pCapabilities->dwInClockTypes |=
248 		ECHO_CLOCK_BIT_SPDIF |
249 		ECHO_CLOCK_BIT_ESYNC |
250 		ECHO_CLOCK_BIT_ESYNC96 |
251 		ECHO_CLOCK_BIT_ADAT;
252 
253 	return Status;
254 }	// ECHOSTATUS CGina24::GetCapabilities
255 
256 
257 //===========================================================================
258 //
259 // QueryAudioSampleRate is used to find out if this card can handle a
260 // given sample rate.
261 //
262 //===========================================================================
263 
QueryAudioSampleRate(DWORD dwSampleRate)264 ECHOSTATUS CGina24::QueryAudioSampleRate
265 (
266 	DWORD		dwSampleRate
267 )
268 {
269 	if ( dwSampleRate !=  8000 &&
270 		  dwSampleRate != 11025 &&
271 		  dwSampleRate != 16000 &&
272 		  dwSampleRate != 22050 &&
273 		  dwSampleRate != 32000 &&
274 		  dwSampleRate != 44100 &&
275 		  dwSampleRate != 48000 &&
276 		  dwSampleRate != 88200 &&
277 		  dwSampleRate != 96000 )
278 	{
279 		ECHO_DEBUGPRINTF(
280 			("CGina24::QueryAudioSampleRate() - rate %ld invalid\n",dwSampleRate) );
281 		return ECHOSTATUS_BAD_FORMAT;
282 	}
283 	if ( dwSampleRate >= 88200 && DIGITAL_MODE_ADAT == GetDigitalMode() )
284 	{
285 		ECHO_DEBUGPRINTF(
286 			("CGina24::QueryAudioSampleRate() Sample rate cannot be "
287 			 "set to 88,200 Hz or 96,000 Hz in ADAT mode\n") );
288 		return ECHOSTATUS_BAD_FORMAT;
289 	}
290 
291 	ECHO_DEBUGPRINTF( ( "CGina24::QueryAudioSampleRate()\n" ) );
292 	return ECHOSTATUS_OK;
293 }	// ECHOSTATUS CGina24::QueryAudioSampleRate
294 
295 
QuerySampleRateRange(DWORD & dwMinRate,DWORD & dwMaxRate)296 void CGina24::QuerySampleRateRange(DWORD &dwMinRate,DWORD &dwMaxRate)
297 {
298 	dwMinRate = 8000;
299 	dwMaxRate = 96000;
300 }
301 
302 
303 //===========================================================================
304 //
305 // GetInputClockDetect returns a bitmask consisting of all the input
306 // clocks currently connected to the hardware; this changes as the user
307 // connects and disconnects clock inputs.
308 //
309 // You should use this information to determine which clocks the user is
310 // allowed to select.
311 //
312 // Gina24 supports S/PDIF, Esync, and ADAT input clocks.
313 //
314 //===========================================================================
315 
GetInputClockDetect(DWORD & dwClockDetectBits)316 ECHOSTATUS CGina24::GetInputClockDetect(DWORD &dwClockDetectBits)
317 {
318 	//ECHO_DEBUGPRINTF(("CGina24::GetInputClockDetect\n"));
319 
320 	if ( NULL == GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
321 	{
322 		ECHO_DEBUGPRINTF( ("CGina24::GetInputClockDetect: DSP Dead!\n") );
323 		return ECHOSTATUS_DSP_DEAD;
324 	}
325 
326 	//
327 	// Map the DSP clock detect bits to the generic driver clock detect bits
328 	//
329 	DWORD dwClocksFromDsp = GetDspCommObject()->GetInputClockDetect();
330 
331 	dwClockDetectBits = ECHO_CLOCK_BIT_INTERNAL;
332 
333 	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_SPDIF))
334 		dwClockDetectBits |= ECHO_CLOCK_BIT_SPDIF;
335 
336 	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_ADAT))
337 		dwClockDetectBits |= ECHO_CLOCK_BIT_ADAT;
338 
339 	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_ESYNC))
340 		dwClockDetectBits |= ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96;
341 
342 	return ECHOSTATUS_OK;
343 
344 }	// GetInputClockDetect
345 
346 
347 // *** CGina24.cpp ***
348