xref: /haiku/src/add-ons/kernel/drivers/audio/echo/generic/CLayla24.cpp (revision f2b4344867e97c3f4e742a1b4a15e6879644601a)
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 // ----------------------------------------------------------------------------
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 "CLayla24.h"
32 
33 #define LAYLA24_ANALOG_OUTPUT_LATENCY		59
34 #define LAYLA24_ANALOG_INPUT_LATENCY		71
35 #define LAYLA24_DIGITAL_OUTPUT_LATENCY		32
36 #define LAYLA24_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 
53 PVOID CLayla24::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(("CLayla24::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 CLayla24::operator new( size_t Size )
74 
75 
76 VOID  CLayla24::operator delete( PVOID pVoid )
77 {
78 	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
79 	{
80 		ECHO_DEBUGPRINTF( ("CLayla24::operator delete memory free failed\n") );
81 	}
82 }	// VOID  CLayla24::operator delete( PVOID pVoid )
83 
84 
85 //===========================================================================
86 //
87 // Constructor and destructor
88 //
89 //===========================================================================
90 
91 CLayla24::CLayla24( PCOsSupport pOsSupport )
92 		  : CEchoGalsMTC( pOsSupport )
93 {
94 	ECHO_DEBUGPRINTF( ( "CLayla24::CLayla24() is born!\n" ) );
95 
96 	m_wAnalogOutputLatency = LAYLA24_ANALOG_OUTPUT_LATENCY;
97 	m_wAnalogInputLatency = LAYLA24_ANALOG_INPUT_LATENCY;
98 	m_wDigitalOutputLatency = LAYLA24_DIGITAL_OUTPUT_LATENCY;
99 	m_wDigitalInputLatency = LAYLA24_DIGITAL_INPUT_LATENCY;
100 
101 }	// CLayla24::CLayla24()
102 
103 
104 CLayla24::~CLayla24()
105 {
106 	ECHO_DEBUGPRINTF( ( "CLayla24::~CLayla24() is toast!\n" ) );
107 }	// CLayla24::~CLayla24()
108 
109 
110 
111 
112 /****************************************************************************
113 
114 	Setup and hardware initialization
115 
116  ****************************************************************************/
117 
118 //===========================================================================
119 //
120 // Every card has an InitHw method
121 //
122 //===========================================================================
123 
124 ECHOSTATUS CLayla24::InitHw()
125 {
126 	ECHOSTATUS	Status;
127 	WORD			i;
128 
129 	//
130 	// Call the base method
131 	//
132 	if ( ECHOSTATUS_OK != ( Status = CEchoGals::InitHw() ) )
133 		return Status;
134 
135 	//
136 	// Create the DSP comm object
137 	//
138 	ECHO_ASSERT(NULL == m_pDspCommObject );
139 	m_pDspCommObject = new CLayla24DspCommObject( (PDWORD) m_pvSharedMemory,
140 																 m_pOsSupport );
141 	if (NULL == m_pDspCommObject)
142 	{
143 		ECHO_DEBUGPRINTF(("CLayla24::InitHw - could not create DSP comm object\n"));
144 		return ECHOSTATUS_NO_MEM;
145 	}
146 
147 	//
148 	// Load the DSP, the PCI card ASIC, and the external box ASIC
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 	// Layla24 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 	// Initialize the MIDI input
173 	//
174 	Status = m_MidiIn.Init( this );
175 	if ( ECHOSTATUS_OK != Status )
176 		return Status;
177 
178 
179 	//
180 	// Set defaults for +4/-10
181 	//
182 	for (i = 0; i < GetFirstDigitalBusOut(); i++ )
183 	{
184 		GetDspCommObject()->
185 			SetNominalLevel( i, FALSE );	// FALSE is +4 here
186 	}
187 
188 	for ( i = 0; i < GetNumBussesIn(); i++ )
189 	{
190 		GetDspCommObject()->
191 			SetNominalLevel( GetNumBussesOut() + i, FALSE );
192 	}
193 
194 	//
195 	// Set the digital mode to S/PDIF RCA
196 	//
197 	SetDigitalMode( DIGITAL_MODE_SPDIF_RCA );
198 
199 	//
200 	// Set the S/PDIF output format to "professional"
201 	//
202 	SetProfessionalSpdif( TRUE );
203 
204 	//
205 	//	Get default sample rate from DSP
206 	//
207 	m_dwSampleRate = GetDspCommObject()->GetSampleRate();
208 
209 	ECHO_DEBUGPRINTF( ( "CLayla24::InitHw()\n" ) );
210 	return Status;
211 
212 }	// ECHOSTATUS CLayla24::InitHw()
213 
214 
215 
216 
217 /****************************************************************************
218 
219 	Informational methods
220 
221  ****************************************************************************/
222 
223 //===========================================================================
224 //
225 // Override GetCapabilities to enumerate unique capabilties for this card
226 //
227 //===========================================================================
228 
229 ECHOSTATUS CLayla24::GetCapabilities
230 (
231 	PECHOGALS_CAPS	pCapabilities
232 )
233 {
234 	ECHOSTATUS	Status;
235 	WORD			i;
236 
237 	Status = GetBaseCapabilities(pCapabilities);
238 
239 	if ( ECHOSTATUS_OK != Status )
240 		return Status;
241 
242 	//
243 	// Add nominal level control to analog ins & outs
244 	//
245 	for (i = 0 ; i < GetFirstDigitalBusOut(); i++)
246 	{
247 		pCapabilities->dwBusOutCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
248 	}
249 
250 	for (i = 0 ; i < GetNumBussesIn(); i++)
251 	{
252 		pCapabilities->dwBusInCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
253 	}
254 
255 	pCapabilities->dwInClockTypes |= ECHO_CLOCK_BIT_WORD		|
256 												ECHO_CLOCK_BIT_SPDIF		|
257 												ECHO_CLOCK_BIT_ADAT		|
258 												ECHO_CLOCK_BIT_MTC;
259 
260 	return Status;
261 
262 }	// ECHOSTATUS CLayla24::GetCapabilities
263 
264 
265 //===========================================================================
266 //
267 // QueryAudioSampleRate is used to find out if this card can handle a
268 // given sample rate.
269 //
270 //===========================================================================
271 
272 ECHOSTATUS CLayla24::QueryAudioSampleRate
273 (
274 	DWORD		dwSampleRate
275 )
276 {
277 	//
278 	// Standard sample rates are allowed (like Mona & Layla24)
279 	//
280 	switch ( dwSampleRate )
281 	{
282 		case 8000 :
283 		case 11025 :
284 		case 16000 :
285 		case 22050 :
286 		case 32000 :
287 		case 44100 :
288 		case 48000 :
289 			goto qasr_ex;
290 
291 		case 88200 :
292 		case 96000 :
293 
294 			//
295 			// Double speed sample rates not allowed in ADAT mode
296 			//
297 			if ( DIGITAL_MODE_ADAT == GetDigitalMode() )
298 			{
299 				ECHO_DEBUGPRINTF(
300 					("CLayla24::QueryAudioSampleRate() Sample rate must be < "
301 					 "50,000 Hz in ADAT mode\n") );
302 				return ECHOSTATUS_BAD_FORMAT;
303 			}
304 			goto qasr_ex;
305 	}
306 
307 	//
308 	// Any rate from 25000 to 50000 is allowed
309 	//
310 	if ( ( dwSampleRate >= 25000 ) &&
311 	  	  ( dwSampleRate <= 50000 ) )
312 		goto qasr_ex;
313 
314 	//
315 	//	If not in ADAT mode, any rate from 50,000 to 100,000 is allowed
316 	//
317 	if ( DIGITAL_MODE_ADAT != GetDigitalMode() &&
318 		  ( dwSampleRate >= 50000 ) &&
319 		  ( dwSampleRate <= 100000 ) )
320 		goto qasr_ex;
321 
322 	ECHO_DEBUGPRINTF(
323 		("CLayla24::QueryAudioSampleRate() - rate %ld invalid\n",dwSampleRate) );
324 	return ECHOSTATUS_BAD_FORMAT;
325 
326 qasr_ex:
327 	ECHO_DEBUGPRINTF( ( "CLayla24::QueryAudioSampleRate() %ld Hz OK\n",
328 							  dwSampleRate ) );
329 	return ECHOSTATUS_OK;
330 }	// ECHOSTATUS CLayla24::QueryAudioSampleRate
331 
332 
333 void CLayla24::QuerySampleRateRange(DWORD &dwMinRate,DWORD &dwMaxRate)
334 {
335 	dwMinRate = 8000;
336 	dwMaxRate = 96000;
337 }
338 
339 
340 
341 //===========================================================================
342 //
343 // GetInputClockDetect returns a bitmask consisting of all the input
344 // clocks currently connected to the hardware; this changes as the user
345 // connects and disconnects clock inputs.
346 //
347 // You should use this information to determine which clocks the user is
348 // allowed to select.
349 //
350 // Layla24 supports S/PDIF, word, and ADAT input clocks.
351 //
352 //===========================================================================
353 
354 ECHOSTATUS CLayla24::GetInputClockDetect(DWORD &dwClockDetectBits)
355 {
356 	if ( NULL == GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
357 	{
358 		ECHO_DEBUGPRINTF( ("CLayla24::GetInputClockDetect: DSP Dead!\n") );
359 		return ECHOSTATUS_DSP_DEAD;
360 	}
361 
362 	//
363 	// Map the DSP clock detect bits to the generic driver clock detect bits
364 	//
365 	DWORD dwClocksFromDsp = GetDspCommObject()->GetInputClockDetect();
366 
367 	dwClockDetectBits = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_MTC;
368 
369 	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_SPDIF))
370 		dwClockDetectBits |= ECHO_CLOCK_BIT_SPDIF;
371 
372 	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_ADAT))
373 		dwClockDetectBits |= ECHO_CLOCK_BIT_ADAT;
374 
375 	if (0 != (dwClocksFromDsp & GML_CLOCK_DETECT_BIT_WORD))
376 		dwClockDetectBits |= ECHO_CLOCK_BIT_WORD;
377 
378 	return ECHOSTATUS_OK;
379 
380 }	// GetInputClockDetect
381 
382 
383 // *** Layla24.cpp ***
384