xref: /haiku/src/add-ons/kernel/drivers/audio/echo/generic/CMiaDspCommObject.cpp (revision 5d9e40fe9252c8f9c5e5e41594545bfa4419fcc7)
1 // ****************************************************************************
2 //
3 //  	CMiaDspCommObject.cpp
4 //
5 //		Implementation file for EchoGals generic driver Darla 24 DSP
6 //		interface class.
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 "CEchoGals.h"
42 #include "CMiaDspCommObject.h"
43 
44 #include "MiaDSP.c"
45 
46 
47 /****************************************************************************
48 
49 	Construction and destruction
50 
51  ****************************************************************************/
52 
53 //===========================================================================
54 //
55 // Constructor
56 //
57 //===========================================================================
58 
59 CMiaDspCommObject::CMiaDspCommObject
60 (
61 	PDWORD		pdwRegBase,				// Virtual ptr to DSP registers
62 	PCOsSupport	pOsSupport
63 ) : CDspCommObject( pdwRegBase, pOsSupport )
64 {
65 	strcpy( m_szCardName, "Mia" );
66 	m_pdwDspRegBase = pdwRegBase;		// Virtual addr DSP's register base
67 
68 	m_wNumPipesOut = 8;
69 	m_wNumPipesIn = 4;
70 	m_wNumBussesOut = 4;
71 	m_wNumBussesIn = 4;
72 	m_wFirstDigitalBusOut = 2;
73 	m_wFirstDigitalBusIn = 2;
74 
75 	m_fHasVmixer = TRUE;
76 
77 	m_wNumMidiOut = 0;					// # MIDI out channels
78 	m_wNumMidiIn = 0;						// # MIDI in  channels
79 
80 	m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 44100 );
81 
82 	m_bHasASIC = FALSE;
83 
84 	m_pwDspCodeToLoad = pwMiaDSP;
85 
86 	m_byDigitalMode = DIGITAL_MODE_NONE;
87 
88 	//
89 	// Since this card has no ASIC, mark it as loaded so everything works OK
90 	//
91 	m_bASICLoaded = TRUE;
92 
93 }	// CMiaDspCommObject::CMiaDspCommObject( DWORD dwPhysRegBase )
94 
95 
96 //===========================================================================
97 //
98 // Destructor
99 //
100 //===========================================================================
101 
102 CMiaDspCommObject::~CMiaDspCommObject()
103 {
104 }	// CMiaDspCommObject::~CMiaDspCommObject()
105 
106 
107 
108 
109 /****************************************************************************
110 
111 	Hardware setup and config
112 
113  ****************************************************************************/
114 
115 //===========================================================================
116 //
117 //	Set the input clock
118 //
119 //===========================================================================
120 
121 ECHOSTATUS CMiaDspCommObject::SetInputClock(WORD wClock)
122 {
123 	DWORD	dwSampleRate = GetSampleRate();
124 
125 	ECHO_DEBUGPRINTF( ("CMiaDspCommObject::SetInputClock:\n") );
126 
127 	switch ( wClock )
128 	{
129 		case ECHO_CLOCK_INTERNAL :
130 		{
131 			ECHO_DEBUGPRINTF( ( "\tSet Mia clock to INTERNAL\n" ) );
132 
133 			// If the sample rate is out of range for some reason, set it
134 			// to a reasonable value.  mattg
135 			if ( ( dwSampleRate < 8000  ) ||
136 			     ( dwSampleRate > 96000 ) )
137 			{
138 				dwSampleRate = 48000;
139 			}
140 
141 			break;
142 		} // CLK_CLOCKININTERNAL
143 
144 		case ECHO_CLOCK_SPDIF :
145 		{
146 			ECHO_DEBUGPRINTF( ( "\tSet Mia clock to SPDIF\n" ) );
147 			break;
148 		} // CLK_CLOCKINSPDIF
149 
150 		default :
151 			ECHO_DEBUGPRINTF(("Input clock 0x%x not supported for Mia\n",wClock));
152 			ECHO_DEBUGBREAK();
153 				return ECHOSTATUS_CLOCK_NOT_SUPPORTED;
154 	}	// switch (wInputClock)
155 
156 	m_wInputClock = wClock;
157 
158 	SetSampleRate( dwSampleRate );
159 
160 	return ECHOSTATUS_OK;
161 }	// ECHOSTATUS CMiaDspCommObject::SetInputClock
162 
163 
164 //===========================================================================
165 //
166 // SetSampleRate
167 //
168 // Set the audio sample rate for Mia
169 //
170 //===========================================================================
171 
172 DWORD CMiaDspCommObject::SetSampleRate( DWORD dwNewSampleRate )
173 {
174 	//
175 	// Set the sample rate
176 	//
177 	DWORD dwControlReg = MIA_48000;
178 
179 	switch ( dwNewSampleRate )
180 	{
181 		case 96000 :
182 			dwControlReg = MIA_96000;
183 			break;
184 
185 		case 88200 :
186 			dwControlReg = MIA_88200;
187 			break;
188 
189 		case 44100 :
190 			dwControlReg = MIA_44100;
191 			break;
192 
193 		case 32000 :
194 			dwControlReg = MIA_32000;
195 			break;
196 
197 		case 24000 :
198 			dwControlReg = MIA_24000;
199 			break;
200 
201 		case 22050 :
202 			dwControlReg = MIA_22050;
203 			break;
204 
205 		case 16000 :
206 			dwControlReg = MIA_16000;
207 			break;
208 
209 		case 12000 :
210 			dwControlReg = MIA_12000;
211 			break;
212 
213 		case 11025 :
214 			dwControlReg = MIA_11025;
215 			break;
216 
217 		case 8000 :
218 			dwControlReg = MIA_8000;
219 			break;
220 	}
221 
222 	//
223 	// Override the clock setting if this Mia is set to S/PDIF clock
224 	//
225 	if ( ECHO_CLOCK_SPDIF == GetInputClock() )
226 	{
227 		dwControlReg &= MIA_SRC_MASK;
228 		dwControlReg |= MIA_SPDIF;
229 	}
230 
231 	//
232 	//	Set the control register if it has changed
233 	//
234 	if (dwControlReg != GetControlRegister())
235 	{
236 		if ( !WaitForHandshake() )
237 			return 0xffffffff;
238 
239 		//
240 		// Set the values in the comm page; the dwSampleRate
241 		// field isn't used by the DSP, but is read by the call
242 		// to GetSampleRate below
243 		//
244 		m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate );
245 		SetControlRegister( dwControlReg );
246 
247 		//
248 		//	Poke the DSP
249 		//
250 		ClearHandshake();
251 		SendVector( DSP_VC_UPDATE_CLOCKS );
252 	}
253 
254 	return GetSampleRate();
255 
256 } // DWORD CMiaDspCommObject::SetSampleRate( DWORD dwNewSampleRate )
257 
258 
259 
260 //===========================================================================
261 //
262 // GetAudioMeters
263 //
264 // Meters are written to the comm page by the DSP as follows:
265 //
266 // Output busses
267 // Input busses
268 // Output pipes (vmixer cards only)
269 //
270 // This function is overridden for vmixer cards
271 //
272 //===========================================================================
273 
274 ECHOSTATUS CMiaDspCommObject::GetAudioMeters
275 (
276 	PECHOGALS_METERS	pMeters
277 )
278 {
279 	WORD i;
280 
281 	pMeters->iNumPipesIn = 0;
282 
283 	//
284 	//	Output
285 	//
286 	DWORD dwCh = 0;
287 
288 	pMeters->iNumBussesOut = (int) m_wNumBussesOut;
289 	for (i = 0; i < m_wNumBussesOut; i++)
290 	{
291 		pMeters->iBusOutVU[i] =
292 			DSP_TO_GENERIC( ((int) (char) m_pDspCommPage->VULevel[ dwCh ]) );
293 
294 		pMeters->iBusOutPeak[i] =
295 			DSP_TO_GENERIC( ((int) (char) m_pDspCommPage->PeakMeter[ dwCh ]) );
296 
297 		dwCh++;
298 	}
299 
300 	pMeters->iNumBussesIn = (int) m_wNumBussesIn;
301 	for (i = 0; i < m_wNumPipesIn; i++)
302 	{
303 		pMeters->iBusInVU[i] =
304 			DSP_TO_GENERIC( ((int) (char) m_pDspCommPage->VULevel[ dwCh ]) );
305 		pMeters->iBusInPeak[i] =
306 			DSP_TO_GENERIC( ((int) (char) m_pDspCommPage->PeakMeter[ dwCh ]) );
307 
308 		dwCh++;
309 	}
310 
311 	pMeters->iNumPipesOut = (int) m_wNumPipesOut;
312 	for (i = 0; i < m_wNumPipesOut; i++)
313 	{
314 		pMeters->iPipeOutVU[i] =
315 			DSP_TO_GENERIC( ((int) (char) m_pDspCommPage->VULevel[ dwCh ]) );
316 		pMeters->iPipeOutPeak[i] =
317 			DSP_TO_GENERIC( ((int) (char) m_pDspCommPage->PeakMeter[ dwCh ]) );
318 
319 		dwCh++;
320 	}
321 
322 	return ECHOSTATUS_OK;
323 
324 } // GetAudioMeters
325 
326 
327 //===========================================================================
328 //
329 // GetPipeOutGain and SetPipeOutGain
330 //
331 // On Mia, this doesn't set the line out volume; instead, it sets the
332 // vmixer volume.
333 //
334 //===========================================================================
335 
336 ECHOSTATUS CMiaDspCommObject::SetPipeOutGain
337 (
338 	WORD wPipeOut,
339 	WORD wBusOut,
340 	int iGain,
341 	BOOL fImmediate
342 )
343 {
344 	if (wPipeOut >= m_wNumPipesOut)
345 	{
346 		ECHO_DEBUGPRINTF( ("CDspCommObject::SetPipeOutGain: Invalid out pipe "
347 								 "%d\n",
348 								 wPipeOut) );
349 
350 		return ECHOSTATUS_INVALID_CHANNEL;
351 	}
352 
353 	iGain = GENERIC_TO_DSP(iGain);
354 
355 	if ( wBusOut < m_wNumBussesOut )
356 	{
357 		if ( !WaitForHandshake() )
358 			return ECHOSTATUS_DSP_DEAD;
359 
360 		DWORD dwIndex = wBusOut * m_wNumPipesOut + wPipeOut;
361 		m_pDspCommPage->byVmixerLevel[ dwIndex ] = (BYTE) iGain;
362 
363 		ECHO_DEBUGPRINTF( ("CMiaDspCommObject::SetPipeOutGain: Out pipe %d, "
364 								 "out bus %d = %u\n",
365 								 wPipeOut,
366 								 wBusOut,
367 								 iGain) );
368 
369 		if (fImmediate)
370 		{
371 			return UpdateVmixerLevel();
372 		}
373 
374 		return ECHOSTATUS_OK;
375 	}
376 
377 	ECHO_DEBUGPRINTF( ("CMiaDspCommObject::SetPipeOutGain: Invalid out bus "
378 							 "%d\n",
379 							 wBusOut) );
380 
381 	return ECHOSTATUS_INVALID_CHANNEL;
382 
383 }	// SetPipeOutGain
384 
385 
386 ECHOSTATUS CMiaDspCommObject::GetPipeOutGain
387 (
388 	WORD wPipeOut,
389 	WORD wBusOut,
390 	int &iGain
391 )
392 {
393 	if (wPipeOut >= m_wNumPipesOut)
394 	{
395 		ECHO_DEBUGPRINTF( ("CMiaDspCommObject::GetPipeOutGain: Invalid out pipe "
396 								 "%d\n",
397 								 wPipeOut) );
398 
399 		return ECHOSTATUS_INVALID_CHANNEL;
400 	}
401 
402 	if (wBusOut < m_wNumBussesOut)
403 	{
404 		iGain = m_pDspCommPage->byVmixerLevel[ wBusOut * m_wNumPipesOut + wPipeOut ];
405 		iGain = DSP_TO_GENERIC(iGain);
406 		return ECHOSTATUS_OK;
407 	}
408 
409 	ECHO_DEBUGPRINTF( ("CMiaDspCommObject::GetPipeOutGain: Invalid out bus "
410 							 "%d\n",
411 							 wBusOut) );
412 
413 	return ECHOSTATUS_INVALID_CHANNEL;
414 
415 }	// GetPipeOutGain
416 
417 //===========================================================================
418 //
419 // SetBusOutGain
420 //
421 //===========================================================================
422 
423 ECHOSTATUS CMiaDspCommObject::SetBusOutGain(WORD wBusOut,int iGain)
424 {
425 	if ( wBusOut < m_wNumBussesOut )
426 	{
427 		if ( !WaitForHandshake() )
428 			return ECHOSTATUS_DSP_DEAD;
429 
430 		iGain = GENERIC_TO_DSP(iGain);
431 		m_pDspCommPage->OutLineLevel[ wBusOut ] = (BYTE) iGain;
432 
433 		ECHO_DEBUGPRINTF( ("CMiaDspCommObject::SetBusOutGain: Out bus %d "
434 								 "= %u\n",
435 								 wBusOut,
436 								 iGain) );
437 
438 		return UpdateAudioOutLineLevel();
439 
440 	}
441 
442 	ECHO_DEBUGPRINTF( ("CMiaDspCommObject::SetBusOutGain: Invalid out bus "
443 							 "%d\n",
444 							 wBusOut) );
445 
446 	return ECHOSTATUS_INVALID_CHANNEL;
447 }
448 
449 
450 //===========================================================================
451 //
452 // Tell the DSP to read and update vmixer levels
453 //	from the comm page.
454 //
455 //===========================================================================
456 
457 ECHOSTATUS CMiaDspCommObject::UpdateVmixerLevel()
458 {
459 	ECHO_DEBUGPRINTF( ( "CMiaDspCommObject::UpdateVmixerLevel:\n" ) );
460 
461 	ClearHandshake();
462 	return( SendVector( DSP_VC_SET_VMIXER_GAIN ) );
463 }
464 
465 
466 // **** CMiaDspCommObject.cpp ****
467