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