xref: /haiku/src/add-ons/kernel/drivers/audio/echo/generic/CLayla.cpp (revision cbe0a0c436162d78cc3f92a305b64918c839d079)
1 // ****************************************************************************
2 //
3 //		CLayla.cpp
4 //
5 //		Implementation file for the CLayla driver class; this is for 20-bit
6 //		Layla.
7 //
8 //		Set editor tabs to 3 for your viewing pleasure.
9 //
10 // ----------------------------------------------------------------------------
11 //
12 // This file is part of Echo Digital Audio's generic driver library.
13 // Copyright Echo Digital Audio Corporation (c) 1998 - 2005
14 // All rights reserved
15 // www.echoaudio.com
16 //
17 // This library is free software; you can redistribute it and/or
18 // modify it under the terms of the GNU Lesser General Public
19 // License as published by the Free Software Foundation; either
20 // version 2.1 of the License, or (at your option) any later version.
21 //
22 // This library is distributed in the hope that it will be useful,
23 // but WITHOUT ANY WARRANTY; without even the implied warranty of
24 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25 // Lesser General Public License for more details.
26 //
27 // You should have received a copy of the GNU Lesser General Public
28 // License along with this library; if not, write to the Free Software
29 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30 //
31 // ****************************************************************************
32 
33 #include "CLayla.h"
34 
35 #define LAYLA20_ANALOG_OUTPUT_LATENCY		57
36 #define LAYLA20_ANALOG_INPUT_LATENCY		64
37 #define LAYLA20_DIGITAL_OUTPUT_LATENCY		32
38 #define LAYLA20_DIGITAL_INPUT_LATENCY		32
39 
40 
41 /****************************************************************************
42 
43 	Construction and destruction
44 
45  ****************************************************************************/
46 
47 //===========================================================================
48 //
49 // Overload new & delete so memory for this object is allocated
50 //	from non-paged memory.
51 //
52 //===========================================================================
53 
54 PVOID CLayla::operator new( size_t Size )
55 {
56 	PVOID 		pMemory;
57 	ECHOSTATUS 	Status;
58 
59 	Status = OsAllocateNonPaged(Size,&pMemory);
60 
61 	if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory ))
62 	{
63 		ECHO_DEBUGPRINTF(("CLayla::operator new - memory allocation failed\n"));
64 
65 		pMemory = NULL;
66 	}
67 	else
68 	{
69 		memset( pMemory, 0, Size );
70 	}
71 
72 	return pMemory;
73 
74 }	// PVOID CLayla::operator new( size_t Size )
75 
76 
77 VOID  CLayla::operator delete( PVOID pVoid )
78 {
79 	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
80 	{
81 		ECHO_DEBUGPRINTF( ("CLayla::operator delete memory free failed\n") );
82 	}
83 }	// VOID  CLayla::operator delete( PVOID pVoid )
84 
85 
86 //===========================================================================
87 //
88 // Constructor and destructor
89 //
90 //===========================================================================
91 
92 CLayla::CLayla( PCOsSupport pOsSupport )
93 		 : CEchoGalsMTC( pOsSupport )
94 {
95 	ECHO_DEBUGPRINTF( ( "CLayla::CLayla() is born!\n" ) );
96 
97 	m_wAnalogOutputLatency = LAYLA20_ANALOG_OUTPUT_LATENCY;
98 	m_wAnalogInputLatency = LAYLA20_ANALOG_INPUT_LATENCY;
99 	m_wDigitalOutputLatency = LAYLA20_DIGITAL_OUTPUT_LATENCY;
100 	m_wDigitalInputLatency = LAYLA20_DIGITAL_INPUT_LATENCY;
101 
102 }	// CLayla::CLayla()
103 
104 
105 CLayla::~CLayla()
106 {
107 	ECHO_DEBUGPRINTF( ( "CLayla::~CLayla() is toast!\n" ) );
108 }	// CLayla::~CLayla()
109 
110 
111 
112 
113 /****************************************************************************
114 
115 	Setup and hardware initialization
116 
117  ****************************************************************************/
118 
119 //===========================================================================
120 //
121 // Every card has an InitHw method
122 //
123 //===========================================================================
124 
125 ECHOSTATUS CLayla::InitHw()
126 {
127 	ECHOSTATUS	Status;
128 	WORD			i;
129 
130 	//
131 	// Call the base method
132 	//
133 	if ( ECHOSTATUS_OK != ( Status = CEchoGals::InitHw() ) )
134 		return Status;
135 
136 	//
137 	// Create the DSP comm object
138 	//
139 	ECHO_ASSERT(NULL == m_pDspCommObject );
140 	m_pDspCommObject = new CLaylaDspCommObject( (PDWORD) m_pvSharedMemory,
141 																m_pOsSupport );
142 	if (NULL == m_pDspCommObject)
143 	{
144 		ECHO_DEBUGPRINTF(("CLayla::InitHw - could not create DSP comm object\n"));
145 		return ECHOSTATUS_NO_MEM;
146 	}
147 
148 	//
149 	// Load the DSP and the external box ASIC
150 	//
151 	GetDspCommObject()->LoadFirmware();
152 	if ( GetDspCommObject()->IsBoardBad() )
153 		return ECHOSTATUS_DSP_DEAD;
154 
155 	//
156 	// Clear the "bad board" flag; set the flag to indicate that
157 	// Darla24 can handle super-interleave.
158 	//
159 	m_wFlags &= ~ECHOGALS_FLAG_BADBOARD;
160 	m_wFlags |= ECHOGALS_ROFLAG_SUPER_INTERLEAVE_OK;
161 
162 	//
163 	//	Must call this here after DSP is init to
164 	//	init gains and mutes
165 	//
166 	Status = InitLineLevels();
167 	if ( ECHOSTATUS_OK != Status )
168 		return Status;
169 
170 	//
171 	// Initialize the MIDI input
172 	//
173 	Status = m_MidiIn.Init( this );
174 	if ( ECHOSTATUS_OK != Status )
175 		return Status;
176 
177 	ECHO_DEBUGPRINTF(("\tMIDI input init done\n"));
178 
179 	//
180 	// Set defaults for +4/-10
181 	//
182 	for (i = 0; i < GetFirstDigitalBusOut(); i++ )
183 	{
184 		ECHO_DEBUGPRINTF(("\tSetting nominal output level %d\n",i));
185 		GetDspCommObject()->SetNominalLevel( i, TRUE );	// TRUE is -10 here
186 	}
187 	for ( i = 0; i < GetFirstDigitalBusIn(); i++ )
188 	{
189 		ECHO_DEBUGPRINTF(("\tSetting nominal input level %d\n",i));
190 		GetDspCommObject()->SetNominalLevel( GetNumBussesOut() + i, TRUE );
191 	}
192 
193 	ECHO_DEBUGPRINTF(("\tNominal levels done\n"));
194 
195 	//
196 	// Set the S/PDIF output format to "professional"
197 	//
198 	SetProfessionalSpdif( TRUE );
199 	ECHO_DEBUGPRINTF(("\tSet S/PDIF format OK\n"));
200 
201 	//
202 	//	Get default sample rate from DSP
203 	//
204 	m_dwSampleRate = GetDspCommObject()->GetSampleRate();
205 	ECHO_DEBUGPRINTF( ( "\tCLayla::InitHw() finished\n" ) );
206 
207 	return Status;
208 
209 }	// ECHOSTATUS CLayla::InitHw()
210 
211 
212 
213 
214 /****************************************************************************
215 
216 	Informational methods
217 
218  ****************************************************************************/
219 
220 //===========================================================================
221 //
222 // Override GetCapabilities to enumerate unique capabilties for Layla20
223 //
224 //===========================================================================
225 
226 ECHOSTATUS CLayla::GetCapabilities
227 (
228 	PECHOGALS_CAPS	pCapabilities
229 )
230 {
231 	ECHOSTATUS	Status;
232 	WORD			i;
233 
234 	Status = GetBaseCapabilities(pCapabilities);
235 
236 	//
237 	// Add input gain and nominal level to input busses
238 	//
239 	for (i = 0; i < GetFirstDigitalBusIn(); i++)
240 	{
241 		pCapabilities->dwBusInCaps[i] |= ECHOCAPS_GAIN |
242 													ECHOCAPS_MUTE |
243 													ECHOCAPS_NOMINAL_LEVEL;
244 	}
245 
246 	//
247 	// Add nominal levels to output busses
248 	//
249 	for (i = 0; i < GetFirstDigitalBusOut(); i++)
250 	{
251 		pCapabilities->dwBusOutCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
252 	}
253 
254 	if ( ECHOSTATUS_OK != Status )
255 		return Status;
256 
257 	pCapabilities->dwInClockTypes |= 	ECHO_CLOCK_BIT_WORD  |
258 													ECHO_CLOCK_BIT_SUPER |
259 													ECHO_CLOCK_BIT_SPDIF |
260 													ECHO_CLOCK_BIT_MTC;
261 
262 	pCapabilities->dwOutClockTypes |= 	ECHO_CLOCK_BIT_WORD |
263 													ECHO_CLOCK_BIT_SUPER;
264 
265 	return Status;
266 
267 }	// ECHOSTATUS CLayla::GetCapabilities
268 
269 
270 //===========================================================================
271 //
272 // QueryAudioSampleRate is used to find out if this card can handle a
273 // given sample rate.
274 //
275 //===========================================================================
276 
277 ECHOSTATUS CLayla::QueryAudioSampleRate
278 (
279 	DWORD		dwSampleRate
280 )
281 {
282 	if ( dwSampleRate <  8000 ||
283 		  dwSampleRate > 50000 )
284 	{
285 		ECHO_DEBUGPRINTF(
286 			("CLayla::QueryAudioSampleRate() - rate %ld invalid\n",dwSampleRate) );
287 		return ECHOSTATUS_BAD_FORMAT;
288 	}
289 	ECHO_DEBUGPRINTF( ( "CLayla::QueryAudioSampleRate() %ld Hz OK\n",
290 							  dwSampleRate ) );
291 	return ECHOSTATUS_OK;
292 
293 }	// ECHOSTATUS CLayla::QueryAudioSampleRate
294 
295 
296 void CLayla::QuerySampleRateRange(DWORD &dwMinRate,DWORD &dwMaxRate)
297 {
298 	dwMinRate = 8000;
299 	dwMaxRate = 50000;
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 // Layla20 supports S/PDIF clock, word clock, and super clock.
313 //
314 //===========================================================================
315 
316 ECHOSTATUS CLayla::GetInputClockDetect(DWORD &dwClockDetectBits)
317 {
318 	if ( NULL == GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
319 	{
320 		ECHO_DEBUGPRINTF( ("CLayla::GetInputClockDetect: DSP Dead!\n") );
321 		return ECHOSTATUS_DSP_DEAD;
322 	}
323 
324 	DWORD dwClocksFromDsp = GetDspCommObject()->GetInputClockDetect();
325 
326 	dwClockDetectBits = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_MTC;
327 
328 	if (0 != (dwClocksFromDsp & GLDM_CLOCK_DETECT_BIT_SPDIF))
329 		dwClockDetectBits |= ECHO_CLOCK_BIT_SPDIF;
330 
331 	if (0 != (dwClocksFromDsp & GLDM_CLOCK_DETECT_BIT_WORD))
332 	{
333 		if (0 != (dwClocksFromDsp & GLDM_CLOCK_DETECT_BIT_SUPER))
334 			dwClockDetectBits |= ECHO_CLOCK_BIT_SUPER;
335 		else
336 			dwClockDetectBits |= ECHO_CLOCK_BIT_WORD;
337 	}
338 
339 	return ECHOSTATUS_OK;
340 
341 }	// GetInputClockDetect
342 
343 
344 // *** CLayla.cpp ***
345