xref: /haiku/src/add-ons/kernel/drivers/audio/echo/generic/CMia.cpp (revision 1acbe440b8dd798953bec31d18ee589aa3f71b73)
1 // ****************************************************************************
2 //
3 //		CMia.cpp
4 //
5 //		Implementation file for the CMia 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 "CMia.h"
32 
33 #define MIA_ANALOG_OUTPUT_LATENCY	63
34 #define MIA_ANALOG_INPUT_LATENCY		62
35 
36 
37 
38 /****************************************************************************
39 
40 	Construction and destruction
41 
42  ****************************************************************************/
43 
44 //===========================================================================
45 //
46 // Overload new & delete so memory for this object is allocated
47 //	from non-paged memory.
48 //
49 //===========================================================================
50 
51 PVOID CMia::operator new( size_t Size )
52 {
53 	PVOID 		pMemory;
54 	ECHOSTATUS 	Status;
55 
56 	Status = OsAllocateNonPaged(Size,&pMemory);
57 
58 	if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory ))
59 	{
60 		ECHO_DEBUGPRINTF(("CMia::operator new - memory allocation failed\n"));
61 
62 		pMemory = NULL;
63 	}
64 	else
65 	{
66 		memset( pMemory, 0, Size );
67 	}
68 
69 	return pMemory;
70 
71 }	// PVOID CMia::operator new( size_t Size )
72 
73 
74 VOID  CMia::operator delete( PVOID pVoid )
75 {
76 	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
77 	{
78 		ECHO_DEBUGPRINTF(("CMia::operator delete memory free failed\n"));
79 	}
80 }	// VOID CMia::operator delete( PVOID pVoid )
81 
82 
83 //===========================================================================
84 //
85 // Constructor and destructor
86 //
87 //===========================================================================
88 
89 CMia::CMia( PCOsSupport pOsSupport )
90 	  : CEchoGalsVmixer( pOsSupport )
91 {
92 	ECHO_DEBUGPRINTF( ( "CMia::CMia() is born!\n" ) );
93 
94 	//
95 	// Mia's virtual outputs make things tricky, since a pipe can
96 	// go to either bus.
97 	//
98 	m_wAnalogOutputLatency = MIA_ANALOG_OUTPUT_LATENCY;
99 	m_wAnalogInputLatency = MIA_ANALOG_INPUT_LATENCY;
100 
101 }
102 
103 CMia::~CMia()
104 {
105 	ECHO_DEBUGPRINTF( ( "CMia::~CMia() 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 
123 ECHOSTATUS CMia::InitHw()
124 {
125 	ECHOSTATUS	Status;
126 	WORD			i;
127 
128 	//
129 	// Call the base method
130 	//
131 	if ( ECHOSTATUS_OK != ( Status = CEchoGals::InitHw() ) )
132 		return Status;
133 
134 	//
135 	// Create the DSP comm object
136 	//
137 	ECHO_ASSERT(NULL == m_pDspCommObject );
138 	m_pDspCommObject = new CMiaDspCommObject( (PDWORD) m_pvSharedMemory,
139 															 m_pOsSupport );
140 	if (NULL == m_pDspCommObject)
141 	{
142 		ECHO_DEBUGPRINTF(("CMia::InitHw - could not create DSP comm object\n"));
143 		return ECHOSTATUS_NO_MEM;
144 	}
145 
146 	//
147 	// Load the DSP
148 	//
149 	GetDspCommObject()->LoadFirmware();
150 	if ( GetDspCommObject()->IsBoardBad() )
151 		return ECHOSTATUS_DSP_DEAD;
152 
153 	//
154 	// Clear the "bad board" flag; set the flags to indicate that
155 	// Mia can handle super-interleave.
156 	//
157 	m_wFlags &= ~ECHOGALS_FLAG_BADBOARD;
158 	m_wFlags |= ECHOGALS_ROFLAG_SUPER_INTERLEAVE_OK;
159 
160 	//
161 	//	Must call this here after DSP is init to
162 	//	init gains and mutes
163 	//
164 	Status = InitLineLevels();
165 	if ( ECHOSTATUS_OK != Status )
166 		return Status;
167 
168 	//
169 	// Set defaults for +4/-10
170 	//
171 	for (i = 0; i < GetFirstDigitalBusOut(); i++ )
172 	{
173 		GetDspCommObject()->
174 			SetNominalLevel( i, FALSE );	// FALSE is +4 here
175 	}
176 	for ( i = 0; i < GetFirstDigitalBusIn(); i++ )
177 	{
178 		GetDspCommObject()->
179 			SetNominalLevel( GetNumBussesOut() + i, FALSE );
180 	}
181 
182 	//
183 	// Set the digital mode to S/PDIF RCA
184 	//
185 	SetDigitalMode( DIGITAL_MODE_SPDIF_RCA );
186 
187 	//
188 	//	Get default sample rate from DSP
189 	//
190 	m_dwSampleRate = GetDspCommObject()->GetSampleRate();
191 
192 	//
193 	// Is this a Mia MIDI card?
194 	//
195 	if (MIA_MIDI_REV == m_pOsSupport->GetCardRev())
196 	{
197 		Status = m_MidiIn.Init( this );
198 	}
199 
200 
201 	ECHO_DEBUGPRINTF( ( "CMia::InitHw()\n" ) );
202 	return Status;
203 
204 }	// ECHOSTATUS CMia::InitHw()
205 
206 
207 
208 
209 /****************************************************************************
210 
211 	Informational methods
212 
213  ****************************************************************************/
214 
215 //===========================================================================
216 //
217 // Override GetCapabilities to enumerate unique capabilties for this card
218 //
219 //===========================================================================
220 
221 ECHOSTATUS CMia::GetCapabilities
222 (
223 	PECHOGALS_CAPS	pCapabilities
224 )
225 {
226 	ECHOSTATUS	Status;
227 	WORD			i;
228 
229 	Status = GetBaseCapabilities(pCapabilities);
230 	if ( ECHOSTATUS_OK != Status )
231 		return Status;
232 
233 	//
234 	// Add nominal level control to analog ins & outs
235 	//
236 	for (i = 0 ; i < GetFirstDigitalBusOut(); i++)
237 	{
238 		pCapabilities->dwBusOutCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
239 	}
240 
241 	for (i = 0 ; i < GetFirstDigitalBusIn(); i++)
242 	{
243 		pCapabilities->dwBusInCaps[i] |= ECHOCAPS_NOMINAL_LEVEL;
244 	}
245 
246 	pCapabilities->dwInClockTypes |= ECHO_CLOCK_BIT_SPDIF;
247 	pCapabilities->dwOutClockTypes = 0;
248 
249 	return Status;
250 
251 }	// ECHOSTATUS CMia::GetCapabilities
252 
253 
254 //===========================================================================
255 //
256 // QueryAudioSampleRate is used to find out if this card can handle a
257 // given sample rate.
258 //
259 //===========================================================================
260 
261 ECHOSTATUS CMia::QueryAudioSampleRate
262 (
263 	DWORD		dwSampleRate
264 )
265 {
266 	if ( dwSampleRate != 32000 &&
267 		  dwSampleRate != 44100 &&
268 		  dwSampleRate != 48000 &&
269 		  dwSampleRate != 88200 &&
270 		  dwSampleRate != 96000 )
271 	{
272 		ECHO_DEBUGPRINTF(
273 			("CMia::QueryAudioSampleRate() - rate %ld invalid\n",dwSampleRate) );
274 		return ECHOSTATUS_BAD_FORMAT;
275 	}
276 
277 	ECHO_DEBUGPRINTF( ( "CMia::QueryAudioSampleRate()\n" ) );
278 	return ECHOSTATUS_OK;
279 
280 }	// ECHOSTATUS CMia::QueryAudioSampleRate
281 
282 
283 void CMia::QuerySampleRateRange(DWORD &dwMinRate,DWORD &dwMaxRate)
284 {
285 	dwMinRate = 32000;
286 	dwMaxRate = 96000;
287 }
288 
289 
290 
291 //===========================================================================
292 //
293 // GetInputClockDetect returns a bitmask consisting of all the input
294 // clocks currently connected to the hardware; this changes as the user
295 // connects and disconnects clock inputs.
296 //
297 // You should use this information to determine which clocks the user is
298 // allowed to select.
299 //
300 // Mia supports S/PDIF input clock.
301 //
302 //===========================================================================
303 
304 ECHOSTATUS CMia::GetInputClockDetect(DWORD &dwClockDetectBits)
305 {
306 	//ECHO_DEBUGPRINTF(("CMia::GetInputClockDetect\n"));
307 
308 	if ( NULL == GetDspCommObject() || GetDspCommObject()->IsBoardBad() )
309 	{
310 		//ECHO_DEBUGPRINTF( ("CMia::GetInputClockDetect: DSP Dead!\n") );
311 		return ECHOSTATUS_DSP_DEAD;
312 	}
313 
314 	//
315 	// Map the DSP clock detect bits to the generic driver clock detect bits
316 	//
317 	DWORD dwClocksFromDsp = GetDspCommObject()->GetInputClockDetect();
318 
319 	dwClockDetectBits = ECHO_CLOCK_BIT_INTERNAL;
320 
321 	if (0 != (dwClocksFromDsp & GLDM_CLOCK_DETECT_BIT_SPDIF))
322 		dwClockDetectBits |= ECHO_CLOCK_BIT_SPDIF;
323 
324 	return ECHOSTATUS_OK;
325 
326 }	// GetInputClockDetect
327 
328 
329 
330 // *** Mia.cpp ***
331