• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * sound/oss/sb_mixer.c
3  *
4  * The low level mixer driver for the Sound Blaster compatible cards.
5  */
6 /*
7  * Copyright (C) by Hannu Savolainen 1993-1997
8  *
9  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
10  * Version 2 (June 1991). See the "COPYING" file distributed with this software
11  * for more info.
12  *
13  *
14  * Thomas Sailer				: ioctl code reworked (vmalloc/vfree removed)
15  * Rolf Fokkens (Dec 20 1998)	: Moved ESS stuff into sb_ess.[ch]
16  * Stanislav Voronyi <stas@esc.kharkov.com>	: Support for AWE 3DSE device (Jun 7 1999)
17  */
18 
19 #include "sound_config.h"
20 
21 #define __SB_MIXER_C__
22 
23 #include "sb.h"
24 #include "sb_mixer.h"
25 
26 #include "sb_ess.h"
27 
28 #define SBPRO_RECORDING_DEVICES	(SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
29 
30 /* Same as SB Pro, unless I find otherwise */
31 #define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
32 
33 #define SBPRO_MIXER_DEVICES		(SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
34 					 SOUND_MASK_CD | SOUND_MASK_VOLUME)
35 
36 /* SG NX Pro has treble and bass settings on the mixer. The 'speaker'
37  * channel is the COVOX/DisneySoundSource emulation volume control
38  * on the mixer. It does NOT control speaker volume. Should have own
39  * mask eventually?
40  */
41 #define SGNXPRO_MIXER_DEVICES	(SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
42 				 SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
43 
44 #define SB16_RECORDING_DEVICES		(SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
45 					 SOUND_MASK_CD)
46 
47 #define SB16_OUTFILTER_DEVICES		(SOUND_MASK_LINE | SOUND_MASK_MIC | \
48 					 SOUND_MASK_CD)
49 
50 #define SB16_MIXER_DEVICES		(SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
51 					 SOUND_MASK_CD | \
52 					 SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
53 					 SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
54 					SOUND_MASK_IMIX)
55 
56 /* These are the only devices that are working at the moment.  Others could
57  * be added once they are identified and a method is found to control them.
58  */
59 #define ALS007_MIXER_DEVICES	(SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
60 				 SOUND_MASK_PCM | SOUND_MASK_MIC | \
61 				 SOUND_MASK_CD | \
62 				 SOUND_MASK_VOLUME)
63 
64 static mixer_tab sbpro_mix = {
65 MIX_ENT(SOUND_MIXER_VOLUME,	0x22, 7, 4, 0x22, 3, 4),
66 MIX_ENT(SOUND_MIXER_BASS,	0x00, 0, 0, 0x00, 0, 0),
67 MIX_ENT(SOUND_MIXER_TREBLE,	0x00, 0, 0, 0x00, 0, 0),
68 MIX_ENT(SOUND_MIXER_SYNTH,	0x26, 7, 4, 0x26, 3, 4),
69 MIX_ENT(SOUND_MIXER_PCM,	0x04, 7, 4, 0x04, 3, 4),
70 MIX_ENT(SOUND_MIXER_SPEAKER,	0x00, 0, 0, 0x00, 0, 0),
71 MIX_ENT(SOUND_MIXER_LINE,	0x2e, 7, 4, 0x2e, 3, 4),
72 MIX_ENT(SOUND_MIXER_MIC,	0x0a, 2, 3, 0x00, 0, 0),
73 MIX_ENT(SOUND_MIXER_CD,		0x28, 7, 4, 0x28, 3, 4),
74 MIX_ENT(SOUND_MIXER_IMIX,	0x00, 0, 0, 0x00, 0, 0),
75 MIX_ENT(SOUND_MIXER_ALTPCM,	0x00, 0, 0, 0x00, 0, 0),
76 MIX_ENT(SOUND_MIXER_RECLEV,	0x00, 0, 0, 0x00, 0, 0)
77 };
78 
79 static mixer_tab sb16_mix = {
80 MIX_ENT(SOUND_MIXER_VOLUME,	0x30, 7, 5, 0x31, 7, 5),
81 MIX_ENT(SOUND_MIXER_BASS,	0x46, 7, 4, 0x47, 7, 4),
82 MIX_ENT(SOUND_MIXER_TREBLE,	0x44, 7, 4, 0x45, 7, 4),
83 MIX_ENT(SOUND_MIXER_SYNTH,	0x34, 7, 5, 0x35, 7, 5),
84 MIX_ENT(SOUND_MIXER_PCM,	0x32, 7, 5, 0x33, 7, 5),
85 MIX_ENT(SOUND_MIXER_SPEAKER,	0x3b, 7, 2, 0x00, 0, 0),
86 MIX_ENT(SOUND_MIXER_LINE,	0x38, 7, 5, 0x39, 7, 5),
87 MIX_ENT(SOUND_MIXER_MIC,	0x3a, 7, 5, 0x00, 0, 0),
88 MIX_ENT(SOUND_MIXER_CD,		0x36, 7, 5, 0x37, 7, 5),
89 MIX_ENT(SOUND_MIXER_IMIX,	0x3c, 0, 1, 0x00, 0, 0),
90 MIX_ENT(SOUND_MIXER_ALTPCM,	0x00, 0, 0, 0x00, 0, 0),
91 MIX_ENT(SOUND_MIXER_RECLEV,	0x3f, 7, 2, 0x40, 7, 2), /* Obsolete. Use IGAIN */
92 MIX_ENT(SOUND_MIXER_IGAIN,	0x3f, 7, 2, 0x40, 7, 2),
93 MIX_ENT(SOUND_MIXER_OGAIN,	0x41, 7, 2, 0x42, 7, 2)
94 };
95 
96 static mixer_tab als007_mix =
97 {
98 MIX_ENT(SOUND_MIXER_VOLUME,	0x62, 7, 4, 0x62, 3, 4),
99 MIX_ENT(SOUND_MIXER_BASS,	0x00, 0, 0, 0x00, 0, 0),
100 MIX_ENT(SOUND_MIXER_TREBLE,	0x00, 0, 0, 0x00, 0, 0),
101 MIX_ENT(SOUND_MIXER_SYNTH,	0x66, 7, 4, 0x66, 3, 4),
102 MIX_ENT(SOUND_MIXER_PCM,	0x64, 7, 4, 0x64, 3, 4),
103 MIX_ENT(SOUND_MIXER_SPEAKER,	0x00, 0, 0, 0x00, 0, 0),
104 MIX_ENT(SOUND_MIXER_LINE,	0x6e, 7, 4, 0x6e, 3, 4),
105 MIX_ENT(SOUND_MIXER_MIC,	0x6a, 2, 3, 0x00, 0, 0),
106 MIX_ENT(SOUND_MIXER_CD,		0x68, 7, 4, 0x68, 3, 4),
107 MIX_ENT(SOUND_MIXER_IMIX,	0x00, 0, 0, 0x00, 0, 0),
108 MIX_ENT(SOUND_MIXER_ALTPCM,	0x00, 0, 0, 0x00, 0, 0),
109 MIX_ENT(SOUND_MIXER_RECLEV,	0x00, 0, 0, 0x00, 0, 0), /* Obsolete. Use IGAIN */
110 MIX_ENT(SOUND_MIXER_IGAIN,	0x00, 0, 0, 0x00, 0, 0),
111 MIX_ENT(SOUND_MIXER_OGAIN,	0x00, 0, 0, 0x00, 0, 0)
112 };
113 
114 
115 /* SM_GAMES          Master volume is lower and PCM & FM volumes
116 			     higher than with SB Pro. This improves the
117 			     sound quality */
118 
119 static int smg_default_levels[32] =
120 {
121   0x2020,			/* Master Volume */
122   0x4b4b,			/* Bass */
123   0x4b4b,			/* Treble */
124   0x6464,			/* FM */
125   0x6464,			/* PCM */
126   0x4b4b,			/* PC Speaker */
127   0x4b4b,			/* Ext Line */
128   0x0000,			/* Mic */
129   0x4b4b,			/* CD */
130   0x4b4b,			/* Recording monitor */
131   0x4b4b,			/* SB PCM */
132   0x4b4b,			/* Recording level */
133   0x4b4b,			/* Input gain */
134   0x4b4b,			/* Output gain */
135   0x4040,			/* Line1 */
136   0x4040,			/* Line2 */
137   0x1515			/* Line3 */
138 };
139 
140 static int sb_default_levels[32] =
141 {
142   0x5a5a,			/* Master Volume */
143   0x4b4b,			/* Bass */
144   0x4b4b,			/* Treble */
145   0x4b4b,			/* FM */
146   0x4b4b,			/* PCM */
147   0x4b4b,			/* PC Speaker */
148   0x4b4b,			/* Ext Line */
149   0x1010,			/* Mic */
150   0x4b4b,			/* CD */
151   0x0000,			/* Recording monitor */
152   0x4b4b,			/* SB PCM */
153   0x4b4b,			/* Recording level */
154   0x4b4b,			/* Input gain */
155   0x4b4b,			/* Output gain */
156   0x4040,			/* Line1 */
157   0x4040,			/* Line2 */
158   0x1515			/* Line3 */
159 };
160 
161 static unsigned char sb16_recmasks_L[SOUND_MIXER_NRDEVICES] =
162 {
163 	0x00,	/* SOUND_MIXER_VOLUME	*/
164 	0x00,	/* SOUND_MIXER_BASS	*/
165 	0x00,	/* SOUND_MIXER_TREBLE	*/
166 	0x40,	/* SOUND_MIXER_SYNTH	*/
167 	0x00,	/* SOUND_MIXER_PCM	*/
168 	0x00,	/* SOUND_MIXER_SPEAKER	*/
169 	0x10,	/* SOUND_MIXER_LINE	*/
170 	0x01,	/* SOUND_MIXER_MIC	*/
171 	0x04,	/* SOUND_MIXER_CD	*/
172 	0x00,	/* SOUND_MIXER_IMIX	*/
173 	0x00,	/* SOUND_MIXER_ALTPCM	*/
174 	0x00,	/* SOUND_MIXER_RECLEV	*/
175 	0x00,	/* SOUND_MIXER_IGAIN	*/
176 	0x00	/* SOUND_MIXER_OGAIN	*/
177 };
178 
179 static unsigned char sb16_recmasks_R[SOUND_MIXER_NRDEVICES] =
180 {
181 	0x00,	/* SOUND_MIXER_VOLUME	*/
182 	0x00,	/* SOUND_MIXER_BASS	*/
183 	0x00,	/* SOUND_MIXER_TREBLE	*/
184 	0x20,	/* SOUND_MIXER_SYNTH	*/
185 	0x00,	/* SOUND_MIXER_PCM	*/
186 	0x00,	/* SOUND_MIXER_SPEAKER	*/
187 	0x08,	/* SOUND_MIXER_LINE	*/
188 	0x01,	/* SOUND_MIXER_MIC	*/
189 	0x02,	/* SOUND_MIXER_CD	*/
190 	0x00,	/* SOUND_MIXER_IMIX	*/
191 	0x00,	/* SOUND_MIXER_ALTPCM	*/
192 	0x00,	/* SOUND_MIXER_RECLEV	*/
193 	0x00,	/* SOUND_MIXER_IGAIN	*/
194 	0x00	/* SOUND_MIXER_OGAIN	*/
195 };
196 
197 static char     smw_mix_regs[] =	/* Left mixer registers */
198 {
199   0x0b,				/* SOUND_MIXER_VOLUME */
200   0x0d,				/* SOUND_MIXER_BASS */
201   0x0d,				/* SOUND_MIXER_TREBLE */
202   0x05,				/* SOUND_MIXER_SYNTH */
203   0x09,				/* SOUND_MIXER_PCM */
204   0x00,				/* SOUND_MIXER_SPEAKER */
205   0x03,				/* SOUND_MIXER_LINE */
206   0x01,				/* SOUND_MIXER_MIC */
207   0x07,				/* SOUND_MIXER_CD */
208   0x00,				/* SOUND_MIXER_IMIX */
209   0x00,				/* SOUND_MIXER_ALTPCM */
210   0x00,				/* SOUND_MIXER_RECLEV */
211   0x00,				/* SOUND_MIXER_IGAIN */
212   0x00,				/* SOUND_MIXER_OGAIN */
213   0x00,				/* SOUND_MIXER_LINE1 */
214   0x00,				/* SOUND_MIXER_LINE2 */
215   0x00				/* SOUND_MIXER_LINE3 */
216 };
217 
218 static int      sbmixnum = 1;
219 
220 static void     sb_mixer_reset(sb_devc * devc);
221 
sb_mixer_set_stereo(sb_devc * devc,int mode)222 void sb_mixer_set_stereo(sb_devc * devc, int mode)
223 {
224 	sb_chgmixer(devc, OUT_FILTER, STEREO_DAC, (mode ? STEREO_DAC : MONO_DAC));
225 }
226 
detect_mixer(sb_devc * devc)227 static int detect_mixer(sb_devc * devc)
228 {
229 	/* Just trust the mixer is there */
230 	return 1;
231 }
232 
change_bits(sb_devc * devc,unsigned char * regval,int dev,int chn,int newval)233 static void change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval)
234 {
235 	unsigned char mask;
236 	int shift;
237 
238 	mask = (1 << (*devc->iomap)[dev][chn].nbits) - 1;
239 	newval = (int) ((newval * mask) + 50) / 100;	/* Scale */
240 
241 	shift = (*devc->iomap)[dev][chn].bitoffs - (*devc->iomap)[dev][LEFT_CHN].nbits + 1;
242 
243 	*regval &= ~(mask << shift);	/* Mask out previous value */
244 	*regval |= (newval & mask) << shift;	/* Set the new value */
245 }
246 
sb_mixer_get(sb_devc * devc,int dev)247 static int sb_mixer_get(sb_devc * devc, int dev)
248 {
249 	if (!((1 << dev) & devc->supported_devices))
250 		return -EINVAL;
251 	return devc->levels[dev];
252 }
253 
smw_mixer_init(sb_devc * devc)254 void smw_mixer_init(sb_devc * devc)
255 {
256 	int i;
257 
258 	sb_setmixer(devc, 0x00, 0x18);	/* Mute unused (Telephone) line */
259 	sb_setmixer(devc, 0x10, 0x38);	/* Config register 2 */
260 
261 	devc->supported_devices = 0;
262 	for (i = 0; i < sizeof(smw_mix_regs); i++)
263 		if (smw_mix_regs[i] != 0)
264 			devc->supported_devices |= (1 << i);
265 
266 	devc->supported_rec_devices = devc->supported_devices &
267 		~(SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_PCM | SOUND_MASK_VOLUME);
268 	sb_mixer_reset(devc);
269 }
270 
sb_common_mixer_set(sb_devc * devc,int dev,int left,int right)271 int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right)
272 {
273 	int regoffs;
274 	unsigned char val;
275 
276 	if ((dev < 0) || (dev >= devc->iomap_sz))
277 		return -EINVAL;
278 
279 	regoffs = (*devc->iomap)[dev][LEFT_CHN].regno;
280 
281 	if (regoffs == 0)
282 		return -EINVAL;
283 
284 	val = sb_getmixer(devc, regoffs);
285 	change_bits(devc, &val, dev, LEFT_CHN, left);
286 
287 	if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs)	/*
288 								 * Change register
289 								 */
290 	{
291 		sb_setmixer(devc, regoffs, val);	/*
292 							 * Save the old one
293 							 */
294 		regoffs = (*devc->iomap)[dev][RIGHT_CHN].regno;
295 
296 		if (regoffs == 0)
297 			return left | (left << 8);	/*
298 							 * Just left channel present
299 							 */
300 
301 		val = sb_getmixer(devc, regoffs);	/*
302 							 * Read the new one
303 							 */
304 	}
305 	change_bits(devc, &val, dev, RIGHT_CHN, right);
306 
307 	sb_setmixer(devc, regoffs, val);
308 
309 	return left | (right << 8);
310 }
311 
smw_mixer_set(sb_devc * devc,int dev,int left,int right)312 static int smw_mixer_set(sb_devc * devc, int dev, int left, int right)
313 {
314 	int reg, val;
315 
316 	switch (dev)
317 	{
318 		case SOUND_MIXER_VOLUME:
319 			sb_setmixer(devc, 0x0b, 96 - (96 * left / 100));	/* 96=mute, 0=max */
320 			sb_setmixer(devc, 0x0c, 96 - (96 * right / 100));
321 			break;
322 
323 		case SOUND_MIXER_BASS:
324 		case SOUND_MIXER_TREBLE:
325 			devc->levels[dev] = left | (right << 8);
326 			/* Set left bass and treble values */
327 			val = ((devc->levels[SOUND_MIXER_TREBLE] & 0xff) * 16 / (unsigned) 100) << 4;
328 			val |= ((devc->levels[SOUND_MIXER_BASS] & 0xff) * 16 / (unsigned) 100) & 0x0f;
329 			sb_setmixer(devc, 0x0d, val);
330 
331 			/* Set right bass and treble values */
332 			val = (((devc->levels[SOUND_MIXER_TREBLE] >> 8) & 0xff) * 16 / (unsigned) 100) << 4;
333 			val |= (((devc->levels[SOUND_MIXER_BASS] >> 8) & 0xff) * 16 / (unsigned) 100) & 0x0f;
334 			sb_setmixer(devc, 0x0e, val);
335 
336 			break;
337 
338 		default:
339 			/* bounds check */
340 			if (dev < 0 || dev >= ARRAY_SIZE(smw_mix_regs))
341 				return -EINVAL;
342 			reg = smw_mix_regs[dev];
343 			if (reg == 0)
344 				return -EINVAL;
345 			sb_setmixer(devc, reg, (24 - (24 * left / 100)) | 0x20);	/* 24=mute, 0=max */
346 			sb_setmixer(devc, reg + 1, (24 - (24 * right / 100)) | 0x40);
347 	}
348 
349 	devc->levels[dev] = left | (right << 8);
350 	return left | (right << 8);
351 }
352 
sb_mixer_set(sb_devc * devc,int dev,int value)353 static int sb_mixer_set(sb_devc * devc, int dev, int value)
354 {
355 	int left = value & 0x000000ff;
356 	int right = (value & 0x0000ff00) >> 8;
357 	int retval;
358 
359 	if (left > 100)
360 		left = 100;
361 	if (right > 100)
362 		right = 100;
363 
364 	if ((dev < 0) || (dev > 31))
365 		return -EINVAL;
366 
367 	if (!(devc->supported_devices & (1 << dev)))	/*
368 							 * Not supported
369 							 */
370 		return -EINVAL;
371 
372 	/* Differentiate depending on the chipsets */
373 	switch (devc->model) {
374 	case MDL_SMW:
375 		retval = smw_mixer_set(devc, dev, left, right);
376 		break;
377 	case MDL_ESS:
378 		retval = ess_mixer_set(devc, dev, left, right);
379 		break;
380 	default:
381 		retval = sb_common_mixer_set(devc, dev, left, right);
382 	}
383 	if (retval >= 0) devc->levels[dev] = retval;
384 
385 	return retval;
386 }
387 
388 /*
389  * set_recsrc doesn't apply to ES188x
390  */
set_recsrc(sb_devc * devc,int src)391 static void set_recsrc(sb_devc * devc, int src)
392 {
393 	sb_setmixer(devc, RECORD_SRC, (sb_getmixer(devc, RECORD_SRC) & ~7) | (src & 0x7));
394 }
395 
set_recmask(sb_devc * devc,int mask)396 static int set_recmask(sb_devc * devc, int mask)
397 {
398 	int devmask, i;
399 	unsigned char  regimageL, regimageR;
400 
401 	devmask = mask & devc->supported_rec_devices;
402 
403 	switch (devc->model)
404 	{
405 		case MDL_SBPRO:
406 		case MDL_ESS:
407 		case MDL_JAZZ:
408 		case MDL_SMW:
409 			if (devc->model == MDL_ESS && ess_set_recmask (devc, &devmask)) {
410 				break;
411 			};
412 			if (devmask != SOUND_MASK_MIC &&
413 				devmask != SOUND_MASK_LINE &&
414 				devmask != SOUND_MASK_CD)
415 			{
416 				/*
417 				 * More than one device selected. Drop the
418 				 * previous selection
419 				 */
420 				devmask &= ~devc->recmask;
421 			}
422 			if (devmask != SOUND_MASK_MIC &&
423 				devmask != SOUND_MASK_LINE &&
424 				devmask != SOUND_MASK_CD)
425 			{
426 				/*
427 				 * More than one device selected. Default to
428 				 * mic
429 				 */
430 				devmask = SOUND_MASK_MIC;
431 			}
432 			if (devmask ^ devc->recmask)	/*
433 							 *	Input source changed
434 							 */
435 			{
436 				switch (devmask)
437 				{
438 					case SOUND_MASK_MIC:
439 						set_recsrc(devc, SRC__MIC);
440 						break;
441 
442 					case SOUND_MASK_LINE:
443 						set_recsrc(devc, SRC__LINE);
444 						break;
445 
446 					case SOUND_MASK_CD:
447 						set_recsrc(devc, SRC__CD);
448 						break;
449 
450 					default:
451 						set_recsrc(devc, SRC__MIC);
452 				}
453 			}
454 			break;
455 
456 		case MDL_SB16:
457 			if (!devmask)
458 				devmask = SOUND_MASK_MIC;
459 
460 			if (devc->submodel == SUBMDL_ALS007)
461 			{
462 				switch (devmask)
463 				{
464 					case SOUND_MASK_LINE:
465 						sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_LINE);
466 						break;
467 					case SOUND_MASK_CD:
468 						sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_CD);
469 						break;
470 					case SOUND_MASK_SYNTH:
471 						sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_SYNTH);
472 						break;
473 					default:           /* Also takes care of SOUND_MASK_MIC case */
474 						sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_MIC);
475 						break;
476 				}
477 			}
478 			else
479 			{
480 				regimageL = regimageR = 0;
481 				for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
482 				{
483 					if ((1 << i) & devmask)
484 					{
485 						regimageL |= sb16_recmasks_L[i];
486 						regimageR |= sb16_recmasks_R[i];
487 					}
488 					sb_setmixer (devc, SB16_IMASK_L, regimageL);
489 					sb_setmixer (devc, SB16_IMASK_R, regimageR);
490 				}
491 			}
492 			break;
493 	}
494 	devc->recmask = devmask;
495 	return devc->recmask;
496 }
497 
set_outmask(sb_devc * devc,int mask)498 static int set_outmask(sb_devc * devc, int mask)
499 {
500 	int devmask, i;
501 	unsigned char  regimage;
502 
503 	devmask = mask & devc->supported_out_devices;
504 
505 	switch (devc->model)
506 	{
507 		case MDL_SB16:
508 			if (devc->submodel == SUBMDL_ALS007)
509 				break;
510 			else
511 			{
512 				regimage = 0;
513 				for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
514 				{
515 					if ((1 << i) & devmask)
516 					{
517 						regimage |= (sb16_recmasks_L[i] | sb16_recmasks_R[i]);
518 					}
519 					sb_setmixer (devc, SB16_OMASK, regimage);
520 				}
521 			}
522 			break;
523 		default:
524 			break;
525 	}
526 
527 	devc->outmask = devmask;
528 	return devc->outmask;
529 }
530 
sb_mixer_ioctl(int dev,unsigned int cmd,void __user * arg)531 static int sb_mixer_ioctl(int dev, unsigned int cmd, void __user *arg)
532 {
533 	sb_devc *devc = mixer_devs[dev]->devc;
534 	int val, ret;
535 	int __user *p = arg;
536 
537 	/*
538 	 * Use ioctl(fd, SOUND_MIXER_AGC, &mode) to turn AGC off (0) or on (1).
539 	 * Use ioctl(fd, SOUND_MIXER_3DSE, &mode) to turn 3DSE off (0) or on (1)
540 	 *					      or mode==2 put 3DSE state to mode.
541 	 */
542 	if (devc->model == MDL_SB16) {
543 		if (cmd == SOUND_MIXER_AGC)
544 		{
545 			if (get_user(val, p))
546 				return -EFAULT;
547 			sb_setmixer(devc, 0x43, (~val) & 0x01);
548 			return 0;
549 		}
550 		if (cmd == SOUND_MIXER_3DSE)
551 		{
552 			/* I put here 15, but I don't know the exact version.
553 			   At least my 4.13 havn't 3DSE, 4.16 has it. */
554 			if (devc->minor < 15)
555 				return -EINVAL;
556 			if (get_user(val, p))
557 				return -EFAULT;
558 			if (val == 0 || val == 1)
559 				sb_chgmixer(devc, AWE_3DSE, 0x01, val);
560 			else if (val == 2)
561 			{
562 				ret = sb_getmixer(devc, AWE_3DSE)&0x01;
563 				return put_user(ret, p);
564 			}
565 			else
566 				return -EINVAL;
567 			return 0;
568 		}
569 	}
570 	if (((cmd >> 8) & 0xff) == 'M')
571 	{
572 		if (_SIOC_DIR(cmd) & _SIOC_WRITE)
573 		{
574 			if (get_user(val, p))
575 				return -EFAULT;
576 			switch (cmd & 0xff)
577 			{
578 				case SOUND_MIXER_RECSRC:
579 					ret = set_recmask(devc, val);
580 					break;
581 
582 				case SOUND_MIXER_OUTSRC:
583 					ret = set_outmask(devc, val);
584 					break;
585 
586 				default:
587 					ret = sb_mixer_set(devc, cmd & 0xff, val);
588 			}
589 		}
590 		else switch (cmd & 0xff)
591 		{
592 			case SOUND_MIXER_RECSRC:
593 				ret = devc->recmask;
594 				break;
595 
596 			case SOUND_MIXER_OUTSRC:
597 				ret = devc->outmask;
598 				break;
599 
600 			case SOUND_MIXER_DEVMASK:
601 				ret = devc->supported_devices;
602 				break;
603 
604 			case SOUND_MIXER_STEREODEVS:
605 				ret = devc->supported_devices;
606 				/* The ESS seems to have stereo mic controls */
607 				if (devc->model == MDL_ESS)
608 					ret &= ~(SOUND_MASK_SPEAKER|SOUND_MASK_IMIX);
609 				else if (devc->model != MDL_JAZZ && devc->model != MDL_SMW)
610 					ret &= ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IMIX);
611 				break;
612 
613 			case SOUND_MIXER_RECMASK:
614 				ret = devc->supported_rec_devices;
615 				break;
616 
617 			case SOUND_MIXER_OUTMASK:
618 				ret = devc->supported_out_devices;
619 				break;
620 
621 			case SOUND_MIXER_CAPS:
622 				ret = devc->mixer_caps;
623 				break;
624 
625 			default:
626 				ret = sb_mixer_get(devc, cmd & 0xff);
627 				break;
628 		}
629 		return put_user(ret, p);
630 	} else
631 		return -EINVAL;
632 }
633 
634 static struct mixer_operations sb_mixer_operations =
635 {
636 	.owner	= THIS_MODULE,
637 	.id	= "SB",
638 	.name	= "Sound Blaster",
639 	.ioctl	= sb_mixer_ioctl
640 };
641 
642 static struct mixer_operations als007_mixer_operations =
643 {
644 	.owner	= THIS_MODULE,
645 	.id	= "ALS007",
646 	.name	= "Avance ALS-007",
647 	.ioctl	= sb_mixer_ioctl
648 };
649 
sb_mixer_reset(sb_devc * devc)650 static void sb_mixer_reset(sb_devc * devc)
651 {
652 	char name[32];
653 	int i;
654 
655 	sprintf(name, "SB_%d", devc->sbmixnum);
656 
657 	if (devc->sbmo.sm_games)
658 		devc->levels = load_mixer_volumes(name, smg_default_levels, 1);
659 	else
660 		devc->levels = load_mixer_volumes(name, sb_default_levels, 1);
661 
662 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
663 		sb_mixer_set(devc, i, devc->levels[i]);
664 
665 	if (devc->model != MDL_ESS || !ess_mixer_reset (devc)) {
666 		set_recmask(devc, SOUND_MASK_MIC);
667 	};
668 }
669 
sb_mixer_init(sb_devc * devc,struct module * owner)670 int sb_mixer_init(sb_devc * devc, struct module *owner)
671 {
672 	int mixer_type = 0;
673 	int m;
674 
675 	devc->sbmixnum = sbmixnum++;
676 	devc->levels = NULL;
677 
678 	sb_setmixer(devc, 0x00, 0);	/* Reset mixer */
679 
680 	if (!(mixer_type = detect_mixer(devc)))
681 		return 0;	/* No mixer. Why? */
682 
683 	switch (devc->model)
684 	{
685 		case MDL_ESSPCI:
686 		case MDL_YMPCI:
687 		case MDL_SBPRO:
688 		case MDL_AZTECH:
689 		case MDL_JAZZ:
690 			devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
691 			devc->supported_devices = SBPRO_MIXER_DEVICES;
692 			devc->supported_rec_devices = SBPRO_RECORDING_DEVICES;
693 			devc->iomap = &sbpro_mix;
694 			devc->iomap_sz = ARRAY_SIZE(sbpro_mix);
695 			break;
696 
697 		case MDL_ESS:
698 			ess_mixer_init (devc);
699 			break;
700 
701 		case MDL_SMW:
702 			devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
703 			devc->supported_devices = 0;
704 			devc->supported_rec_devices = 0;
705 			devc->iomap = &sbpro_mix;
706 			devc->iomap_sz = ARRAY_SIZE(sbpro_mix);
707 			smw_mixer_init(devc);
708 			break;
709 
710 		case MDL_SB16:
711 			devc->mixer_caps = 0;
712 			devc->supported_rec_devices = SB16_RECORDING_DEVICES;
713 			devc->supported_out_devices = SB16_OUTFILTER_DEVICES;
714 			if (devc->submodel != SUBMDL_ALS007)
715 			{
716 				devc->supported_devices = SB16_MIXER_DEVICES;
717 				devc->iomap = &sb16_mix;
718 				devc->iomap_sz = ARRAY_SIZE(sb16_mix);
719 			}
720 			else
721 			{
722 				devc->supported_devices = ALS007_MIXER_DEVICES;
723 				devc->iomap = &als007_mix;
724 				devc->iomap_sz = ARRAY_SIZE(als007_mix);
725 			}
726 			break;
727 
728 		default:
729 			printk(KERN_WARNING "sb_mixer: Unsupported mixer type %d\n", devc->model);
730 			return 0;
731 	}
732 
733 	m = sound_alloc_mixerdev();
734 	if (m == -1)
735 		return 0;
736 
737 	mixer_devs[m] = kmalloc(sizeof(struct mixer_operations), GFP_KERNEL);
738 	if (mixer_devs[m] == NULL)
739 	{
740 		printk(KERN_ERR "sb_mixer: Can't allocate memory\n");
741 		sound_unload_mixerdev(m);
742 		return 0;
743 	}
744 
745 	if (devc->submodel != SUBMDL_ALS007)
746 		memcpy ((char *) mixer_devs[m], (char *) &sb_mixer_operations, sizeof (struct mixer_operations));
747 	else
748 		memcpy ((char *) mixer_devs[m], (char *) &als007_mixer_operations, sizeof (struct mixer_operations));
749 
750 	mixer_devs[m]->devc = devc;
751 
752 	if (owner)
753 			 mixer_devs[m]->owner = owner;
754 
755 	devc->my_mixerdev = m;
756 	sb_mixer_reset(devc);
757 	return 1;
758 }
759 
sb_mixer_unload(sb_devc * devc)760 void sb_mixer_unload(sb_devc *devc)
761 {
762 	if (devc->my_mixerdev == -1)
763 		return;
764 
765 	kfree(mixer_devs[devc->my_mixerdev]);
766 	sound_unload_mixerdev(devc->my_mixerdev);
767 	sbmixnum--;
768 }
769