xref: /haiku/src/add-ons/kernel/drivers/audio/echo/generic/CLayla24.cpp (revision d5cd5d63ff0ad395989db6cf4841a64d5b545d1d)
1 // ****************************************************************************
2 //
3 //		CLayla24.cpp
4 //
5 //		Implementation file for the CLayla24 driver class.
6 //		Set editor tabs to 3 for your viewing pleasure.
7 //
8 //		Copyright Echo Digital Audio Corporation (c) 1998 - 2002
9 //		All rights reserved
10 //		www.echoaudio.com
11 //
12 //		Permission is hereby granted, free of charge, to any person obtaining a
13 //		copy of this software and associated documentation files (the
14 //		"Software"), to deal with the Software without restriction, including
15 //		without limitation the rights to use, copy, modify, merge, publish,
16 //		distribute, sublicense, and/or sell copies of the Software, and to
17 //		permit persons to whom the Software is furnished to do so, subject to
18 //		the following conditions:
19 //
20 //		- Redistributions of source code must retain the above copyright
21 //		notice, this list of conditions and the following disclaimers.
22 //
23 //		- Redistributions in binary form must reproduce the above copyright
24 //		notice, this list of conditions and the following disclaimers in the
25 //		documentation and/or other materials provided with the distribution.
26 //
27 //		- Neither the name of Echo Digital Audio, nor the names of its
28 //		contributors may be used to endorse or promote products derived from
29 //		this Software without specific prior written permission.
30 //
31 //		THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 //		EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 //		MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
34 //		IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
35 //		ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
36 //		TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
37 //		SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
38 //
39 // ****************************************************************************
40 
41 #include "CLayla24.h"
42 
43 
44 /****************************************************************************
45 
46 	Construction and destruction
47 
48  ****************************************************************************/
49 
50 //===========================================================================
51 //
52 // Overload new & delete so memory for this object is allocated
53 //	from non-paged memory.
54 //
55 //===========================================================================
56 
57 PVOID CLayla24::operator new( size_t Size )
58 {
59 	PVOID 		pMemory;
60 	ECHOSTATUS 	Status;
61 
62 	Status = OsAllocateNonPaged(Size,&pMemory);
63 
64 	if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory ))
65 	{
66 		ECHO_DEBUGPRINTF(("CLayla24::operator new - memory allocation failed\n"));
67 
68 		pMemory = NULL;
69 	}
70 	else
71 	{
72 		memset( pMemory, 0, Size );
73 	}
74 
75 	return pMemory;
76 
77 }	// PVOID CLayla24::operator new( size_t Size )
78 
79 
80 VOID  CLayla24::operator delete( PVOID pVoid )
81 {
82 	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
83 	{
84 		ECHO_DEBUGPRINTF( ("CLayla24::operator delete memory free failed\n") );
85 	}
86 }	// VOID  CLayla24::operator delete( PVOID pVoid )
87 
88 
89 //===========================================================================
90 //
91 // Constructor and destructor
92 //
93 //===========================================================================
94 
95 CLayla24::CLayla24( PCOsSupport pOsSupport )
96 		  : CEchoGals( pOsSupport )
97 {
98 	ECHO_DEBUGPRINTF( ( "CLayla24::CLayla24() is born!\n" ) );
99 }	// CLayla24::CLayla24()
100 
101 
102 CLayla24::~CLayla24()
103 {
104 	ECHO_DEBUGPRINTF( ( "CLayla24::~CLayla24() is toast!\n" ) );
105 }	// CLayla24::~CLayla24()
106 
107 
108 
109 
110 /****************************************************************************
111 
112 	Setup and hardware initialization
113 
114  ****************************************************************************/
115 
116 //===========================================================================
117 //
118 // Every card has an InitHw method
119 //
120 //===========================================================================
121 
122 ECHOSTATUS CLayla24::InitHw()
123 {
124 	ECHOSTATUS	Status;
125 	WORD			i;
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 	ASSERT( NULL == m_pDspCommObject );
137 	m_pDspCommObject = new CLayla24DspCommObject( (PDWORD) m_pvSharedMemory,
138 																 m_pOsSupport );
139 	if (NULL == m_pDspCommObject)
140 	{
141 		ECHO_DEBUGPRINTF(("CLayla24::InitHw - could not create DSP comm object\n"));
142 		return ECHOSTATUS_NO_MEM;
143 	}
144 
145 	//
146 	// Load the DSP, the PCI card ASIC, and the external box ASIC
147 	//
148 	GetDspCommObject()->LoadFirmware();
149 	if ( GetDspCommObject()->IsBoardBad() )
150 		return ECHOSTATUS_DSP_DEAD;
151 
152 	//
153 	// Clear the "bad board" flag; set the flags to indicate that
154 	// Layla24 can handle super-interleave and supports the digital
155 	// input auto-mute.
156 	//
157 	m_wFlags &= ~ECHOGALS_FLAG_BADBOARD;
158 	m_wFlags |= ECHOGALS_ROFLAG_SUPER_INTERLEAVE_OK |
159 					ECHOGALS_ROFLAG_DIGITAL_IN_AUTOMUTE;
160 
161 	//
162 	//	Must call this here after DSP is init to
163 	//	init gains and mutes
164 	//
165 	Status = InitLineLevels();
166 	if ( ECHOSTATUS_OK != Status )
167 		return Status;
168 
169 	//
170 	// Initialize the MIDI input
171 	//
172 	Status = m_MidiIn.Init( this );
173 	if ( ECHOSTATUS_OK != Status )
174 		return Status;
175 
176 
177 	//
178 	// Set defaults for +4/-10
179 	//
180 	for (i = 0; i < GetFirstDigitalBusOut(); i++ )
181 	{
182 		GetDspCommObject()->
183 			SetNominalLevel( i, FALSE );	// FALSE is +4 here
184 	}
185 
186 	for ( i = 0; i < GetFirstDigitalBusIn(); i++ )
187 	{
188 		GetDspCommObject()->
189 			SetNominalLevel( GetNumBussesOut() + i, FALSE );
190 	}
191 	//
192 	// Set the digital mode to S/PDIF RCA
193 	//
194 	SetDigitalMode( DIGITAL_MODE_SPDIF_RCA );
195 
196 	//
197 	// Set the S/PDIF output format to "professional"
198 	//
199 	SetProfessionalSpdif( TRUE );
200 
201 	//
202 	//	Get default sample rate from DSP
203 	//
204 	m_dwSampleRate = GetDspCommObject()->GetSampleRate();
205 
206 	ECHO_DEBUGPRINTF( ( "CLayla24::InitHw()\n" ) );
207 	return Status;
208 
209 }	// ECHOSTATUS CLayla24::InitHw()
210 
211 
212 
213 
214 /****************************************************************************
215 
216 	Informational methods
217 
218  ****************************************************************************/
219 
220 //===========================================================================
221 //
222 // Override GetCapabilities to enumerate unique capabilties for this card
223 //
224 //===========================================================================
225 
226 ECHOSTATUS CLayla24::GetCapabilities
227 (
228 	PECHOGALS_CAPS	pCapabilities
229 )
230 {
231 	ECHOSTATUS	Status;
232 	WORD			i;
233 
234 	Status = GetBaseCapabilities(pCapabilities);
235 
236 	if ( ECHOSTATUS_OK != Status )
237 		return Status;
238 
239 	//
240 	// Add nominal level control to analog ins & outs
241 	//
242 	for (i = 0 ; i < GetFirstDigitalBusOut(); i++)
243 	{
244 		pCapabilities->dwBusOutCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
245 	}
246 
247 	for (i = 0 ; i < GetFirstDigitalBusIn(); i++)
248 	{
249 		pCapabilities->dwBusInCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
250 	}
251 
252 	pCapabilities->dwInClockTypes |= ECHO_CLOCK_BIT_WORD		|
253 												ECHO_CLOCK_BIT_SPDIF		|
254 												ECHO_CLOCK_BIT_ADAT;
255 
256 	return Status;
257 
258 }	// ECHOSTATUS CLayla24::GetCapabilities
259 
260 
261 //===========================================================================
262 //
263 // QueryAudioSampleRate is used to find out if this card can handle a
264 // given sample rate.
265 //
266 //===========================================================================
267 
268 ECHOSTATUS CLayla24::QueryAudioSampleRate
269 (
270 	DWORD		dwSampleRate
271 )
272 {
273 	//
274 	// Standard sample rates are allowed (like Mona & Layla24)
275 	//
276 	switch ( dwSampleRate )
277 	{
278 		case 8000 :
279 		case 11025 :
280 		case 16000 :
281 		case 22050 :
282 		case 32000 :
283 		case 44100 :
284 		case 48000 :
285 			goto qasr_ex;
286 
287 		case 88200 :
288 		case 96000 :
289 
290 			//
291 			// Double speed sample rates not allowed in ADAT mode
292 			//
293 			if ( DIGITAL_MODE_ADAT == GetDigitalMode() )
294 			{
295 				ECHO_DEBUGPRINTF(
296 					("CLayla24::QueryAudioSampleRate() Sample rate must be < "
297 					 "50,000 Hz in ADAT mode\n") );
298 				return ECHOSTATUS_BAD_FORMAT;
299 			}
300 			goto qasr_ex;
301 	}
302 
303 	//
304 	// Any rate from 25000 to 50000 is allowed
305 	//
306 	if ( ( dwSampleRate >= 25000 ) &&
307 	  	  ( dwSampleRate <= 50000 ) )
308 		goto qasr_ex;
309 
310 	//
311 	//	If not in ADAT mode, any rate from 50,000 to 100,000 is allowed
312 	//
313 	if ( DIGITAL_MODE_ADAT != GetDigitalMode() &&
314 		  ( dwSampleRate >= 50000 ) &&
315 		  ( dwSampleRate <= 100000 ) )
316 		goto qasr_ex;
317 
318 	ECHO_DEBUGPRINTF(
319 		("CLayla24::QueryAudioSampleRate() Sample rate must be >= 50,000 Hz"
320 		 " and <= 100,000 Hz and NOT in ADAT mode\n") );
321 	return ECHOSTATUS_BAD_FORMAT;
322 
323 qasr_ex:
324 	ECHO_DEBUGPRINTF( ( "CLayla24::QueryAudioSampleRate() %ld Hz OK\n",
325 							  dwSampleRate ) );
326 	return ECHOSTATUS_OK;
327 }	// ECHOSTATUS CLayla24::QueryAudioSampleRate
328 
329 
330 //===========================================================================
331 //
332 // GetInputClockDetect returns a bitmask consisting of all the input
333 // clocks currently connected to the hardware; this changes as the user
334 // connects and disconnects clock inputs.
335 //
336 // You should use this information to determine which clocks the user is
337 // allowed to select.
338 //
339 // Layla24 supports S/PDIF, word, and ADAT input clocks.
340 //
341 //===========================================================================
342 
343 ECHOSTATUS CLayla24::GetInputClockDetect(DWORD &dwClockDetectBits)
344 {
345 	if ( NULL == GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
346 	{
347 		ECHO_DEBUGPRINTF( ("CLayla24::GetInputClockDetect: DSP Dead!\n") );
348 		return ECHOSTATUS_DSP_DEAD;
349 	}
350 
351 	//
352 	// Map the DSP clock detect bits to the generic driver clock detect bits
353 	//
354 	DWORD dwClocksFromDsp = GetDspCommObject()->GetInputClockDetect();
355 
356 	dwClockDetectBits = ECHO_CLOCK_BIT_INTERNAL;
357 
358 	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_SPDIF))
359 		dwClockDetectBits |= ECHO_CLOCK_BIT_SPDIF;
360 
361 	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_ADAT))
362 		dwClockDetectBits |= ECHO_CLOCK_BIT_ADAT;
363 
364 	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_WORD))
365 		dwClockDetectBits |= ECHO_CLOCK_BIT_WORD;
366 
367 	return ECHOSTATUS_OK;
368 
369 }	// GetInputClockDetect
370 
371 
372 // *** Layla24.cpp ***
373