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