Import 2.1.122pre3
[davej-history.git] / drivers / sound / sb_mixer.c
blob693433b1bd3a3ab162d1e032c357277833165cd4
2 /*
3 * sound/sb_mixer.c
5 * The low level mixer driver for the Sound Blaster compatible cards.
6 */
7 /*
8 * Copyright (C) by Hannu Savolainen 1993-1997
10 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
11 * Version 2 (June 1991). See the "COPYING" file distributed with this software
12 * for more info.
15 * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
18 #include <linux/config.h>
19 #include "sound_config.h"
21 #ifdef CONFIG_SBDSP
22 #define __SB_MIXER_C__
24 #include "sb.h"
25 #include "sb_mixer.h"
27 static int sbmixnum = 1;
29 static void sb_mixer_reset(sb_devc * devc);
31 void sb_mixer_set_stereo(sb_devc * devc, int mode)
33 sb_setmixer(devc, OUT_FILTER, ((sb_getmixer(devc, OUT_FILTER) & ~STEREO_DAC)
34 | (mode ? STEREO_DAC : MONO_DAC)));
37 static int detect_mixer(sb_devc * devc)
39 /* Just trust the mixer is there */
40 return 1;
43 static void change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval)
45 unsigned char mask;
46 int shift;
48 mask = (1 << (*devc->iomap)[dev][chn].nbits) - 1;
49 newval = (int) ((newval * mask) + 50) / 100; /* Scale */
51 shift = (*devc->iomap)[dev][chn].bitoffs - (*devc->iomap)[dev][LEFT_CHN].nbits + 1;
53 *regval &= ~(mask << shift); /* Mask out previous value */
54 *regval |= (newval & mask) << shift; /* Set the new value */
57 static int sb_mixer_get(sb_devc * devc, int dev)
59 if (!((1 << dev) & devc->supported_devices))
60 return -EINVAL;
61 return devc->levels[dev];
64 void smw_mixer_init(sb_devc * devc)
66 int i;
68 sb_setmixer(devc, 0x00, 0x18); /* Mute unused (Telephone) line */
69 sb_setmixer(devc, 0x10, 0x38); /* Config register 2 */
71 devc->supported_devices = 0;
72 for (i = 0; i < sizeof(smw_mix_regs); i++)
73 if (smw_mix_regs[i] != 0)
74 devc->supported_devices |= (1 << i);
76 devc->supported_rec_devices = devc->supported_devices &
77 ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_PCM | SOUND_MASK_VOLUME);
78 sb_mixer_reset(devc);
81 static int smw_mixer_set(sb_devc * devc, int dev, int value)
83 int left = value & 0x000000ff;
84 int right = (value & 0x0000ff00) >> 8;
85 int reg, val;
87 if (left > 100)
88 left = 100;
89 if (right > 100)
90 right = 100;
92 if (dev > 31)
93 return -EINVAL;
95 if (!(devc->supported_devices & (1 << dev))) /* Not supported */
96 return -EINVAL;
98 switch (dev)
100 case SOUND_MIXER_VOLUME:
101 sb_setmixer(devc, 0x0b, 96 - (96 * left / 100)); /* 96=mute, 0=max */
102 sb_setmixer(devc, 0x0c, 96 - (96 * right / 100));
103 break;
105 case SOUND_MIXER_BASS:
106 case SOUND_MIXER_TREBLE:
107 devc->levels[dev] = left | (right << 8);
108 /* Set left bass and treble values */
109 val = ((devc->levels[SOUND_MIXER_TREBLE] & 0xff) * 16 / (unsigned) 100) << 4;
110 val |= ((devc->levels[SOUND_MIXER_BASS] & 0xff) * 16 / (unsigned) 100) & 0x0f;
111 sb_setmixer(devc, 0x0d, val);
113 /* Set right bass and treble values */
114 val = (((devc->levels[SOUND_MIXER_TREBLE] >> 8) & 0xff) * 16 / (unsigned) 100) << 4;
115 val |= (((devc->levels[SOUND_MIXER_BASS] >> 8) & 0xff) * 16 / (unsigned) 100) & 0x0f;
116 sb_setmixer(devc, 0x0e, val);
118 break;
120 default:
121 reg = smw_mix_regs[dev];
122 if (reg == 0)
123 return -EINVAL;
124 sb_setmixer(devc, reg, (24 - (24 * left / 100)) | 0x20); /* 24=mute, 0=max */
125 sb_setmixer(devc, reg + 1, (24 - (24 * right / 100)) | 0x40);
128 devc->levels[dev] = left | (right << 8);
129 return left | (right << 8);
132 static int sb_mixer_set(sb_devc * devc, int dev, int value)
134 int left = value & 0x000000ff;
135 int right = (value & 0x0000ff00) >> 8;
137 int regoffs;
138 unsigned char val;
140 if (devc->model == MDL_SMW)
141 return smw_mixer_set(devc, dev, value);
143 if (left > 100)
144 left = 100;
145 if (right > 100)
146 right = 100;
148 if (dev > 31)
149 return -EINVAL;
151 if (!(devc->supported_devices & (1 << dev))) /*
152 * Not supported
154 return -EINVAL;
156 regoffs = (*devc->iomap)[dev][LEFT_CHN].regno;
158 if (regoffs == 0)
159 return -EINVAL;
161 val = sb_getmixer(devc, regoffs);
162 change_bits(devc, &val, dev, LEFT_CHN, left);
164 devc->levels[dev] = left | (left << 8);
166 if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs) /*
167 * Change register
170 sb_setmixer(devc, regoffs, val); /*
171 * Save the old one
173 regoffs = (*devc->iomap)[dev][RIGHT_CHN].regno;
175 if (regoffs == 0)
176 return left | (left << 8); /*
177 * Just left channel present
180 val = sb_getmixer(devc, regoffs); /*
181 * Read the new one
184 change_bits(devc, &val, dev, RIGHT_CHN, right);
186 sb_setmixer(devc, regoffs, val);
188 devc->levels[dev] = left | (right << 8);
189 return left | (right << 8);
192 static void set_recsrc(sb_devc * devc, int src)
194 sb_setmixer(devc, RECORD_SRC, (sb_getmixer(devc, RECORD_SRC) & ~7) | (src & 0x7));
197 static int set_recmask(sb_devc * devc, int mask)
199 int devmask, i;
200 unsigned char regimageL, regimageR;
202 devmask = mask & devc->supported_rec_devices;
204 switch (devc->model)
206 case MDL_SBPRO:
207 case MDL_ESS:
208 case MDL_JAZZ:
209 case MDL_SMW:
211 if (devmask != SOUND_MASK_MIC &&
212 devmask != SOUND_MASK_LINE &&
213 devmask != SOUND_MASK_CD)
216 * More than one device selected. Drop the
217 * previous selection
219 devmask &= ~devc->recmask;
221 if (devmask != SOUND_MASK_MIC &&
222 devmask != SOUND_MASK_LINE &&
223 devmask != SOUND_MASK_CD)
226 * More than one device selected. Default to
227 * mic
229 devmask = SOUND_MASK_MIC;
231 if (devmask ^ devc->recmask) /*
232 * Input source changed
235 switch (devmask)
237 case SOUND_MASK_MIC:
238 set_recsrc(devc, SRC__MIC);
239 break;
241 case SOUND_MASK_LINE:
242 set_recsrc(devc, SRC__LINE);
243 break;
245 case SOUND_MASK_CD:
246 set_recsrc(devc, SRC__CD);
247 break;
249 default:
250 set_recsrc(devc, SRC__MIC);
253 break;
255 case MDL_SB16:
256 if (!devmask)
257 devmask = SOUND_MASK_MIC;
259 if (devc->submodel == SUBMDL_ALS007)
261 switch (devmask)
263 case SOUND_MASK_LINE:
264 sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_LINE);
265 break;
266 case SOUND_MASK_CD:
267 sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_CD);
268 break;
269 case SOUND_MASK_SYNTH:
270 sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_SYNTH);
271 break;
272 default: /* Also takes care of SOUND_MASK_MIC case */
273 sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_MIC);
274 break;
277 else
279 regimageL = regimageR = 0;
280 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
282 if ((1 << i) & devmask)
284 regimageL |= sb16_recmasks_L[i];
285 regimageR |= sb16_recmasks_R[i];
287 sb_setmixer (devc, SB16_IMASK_L, regimageL);
288 sb_setmixer (devc, SB16_IMASK_R, regimageR);
291 break;
293 devc->recmask = devmask;
294 return devc->recmask;
297 static int sb_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
299 sb_devc *devc = mixer_devs[dev]->devc;
300 int val, ret;
303 * Use ioctl(fd, SOUND_MIXER_PRIVATE1, &mode) to turn AGC off (0) or on (1).
305 if (cmd == SOUND_MIXER_PRIVATE1 && devc->model == MDL_SB16)
307 if (get_user(val, (int *)arg))
308 return -EFAULT;
309 sb_setmixer(devc, 0x43, (~val) & 0x01);
310 return 0;
312 if (((cmd >> 8) & 0xff) == 'M')
314 if (_SIOC_DIR(cmd) & _SIOC_WRITE)
316 if (get_user(val, (int *)arg))
317 return -EFAULT;
318 switch (cmd & 0xff)
320 case SOUND_MIXER_RECSRC:
321 ret = set_recmask(devc, val);
322 break;
324 default:
325 ret = sb_mixer_set(devc, cmd & 0xff, val);
328 else switch (cmd & 0xff)
330 case SOUND_MIXER_RECSRC:
331 ret = devc->recmask;
332 break;
334 case SOUND_MIXER_DEVMASK:
335 ret = devc->supported_devices;
336 break;
338 case SOUND_MIXER_STEREODEVS:
339 ret = devc->supported_devices;
340 /* The ESS seems to have stereo mic controls */
341 if (devc->model == MDL_ESS)
342 ret &= ~(SOUND_MASK_SPEAKER|SOUND_MASK_IMIX);
343 else if (devc->model != MDL_JAZZ && devc->model != MDL_SMW)
344 ret &= ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IMIX);
345 break;
347 case SOUND_MIXER_RECMASK:
348 ret = devc->supported_rec_devices;
349 break;
351 case SOUND_MIXER_CAPS:
352 ret = devc->mixer_caps;
353 break;
355 default:
356 ret = sb_mixer_get(devc, cmd & 0xff);
357 break;
359 return put_user(ret, (int *)arg);
360 } else
361 return -EINVAL;
364 static struct mixer_operations sb_mixer_operations =
366 "SB",
367 "Sound Blaster",
368 sb_mixer_ioctl
371 static struct mixer_operations als007_mixer_operations =
373 "ALS007",
374 "Avance ALS-007",
375 sb_mixer_ioctl
378 static void sb_mixer_reset(sb_devc * devc)
380 char name[32];
381 int i;
382 extern int sm_games;
384 sprintf(name, "SB_%d", devc->sbmixnum);
386 if (sm_games)
387 devc->levels = load_mixer_volumes(name, smg_default_levels, 1);
388 else
389 devc->levels = load_mixer_volumes(name, sb_default_levels, 1);
391 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
392 sb_mixer_set(devc, i, devc->levels[i]);
393 set_recmask(devc, SOUND_MASK_MIC);
396 int sb_mixer_init(sb_devc * devc)
398 int mixer_type = 0;
399 int m;
401 devc->sbmixnum = sbmixnum++;
402 devc->levels = NULL;
404 sb_setmixer(devc, 0x00, 0); /* Reset mixer */
406 if (!(mixer_type = detect_mixer(devc)))
407 return 0; /* No mixer. Why? */
409 switch (devc->model)
411 case MDL_SBPRO:
412 case MDL_AZTECH:
413 case MDL_JAZZ:
414 devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
415 devc->supported_devices = SBPRO_MIXER_DEVICES;
416 devc->supported_rec_devices = SBPRO_RECORDING_DEVICES;
417 devc->iomap = &sbpro_mix;
418 break;
420 case MDL_ESS:
421 devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
422 devc->supported_devices = ES688_MIXER_DEVICES;
423 devc->supported_rec_devices = ES688_RECORDING_DEVICES;
424 devc->iomap = &es688_mix;
425 break;
427 case MDL_SMW:
428 devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
429 devc->supported_devices = 0;
430 devc->supported_rec_devices = 0;
431 devc->iomap = &sbpro_mix;
432 smw_mixer_init(devc);
433 break;
435 case MDL_SB16:
436 devc->mixer_caps = 0;
437 devc->supported_rec_devices = SB16_RECORDING_DEVICES;
438 if (devc->submodel != SUBMDL_ALS007)
440 devc->supported_devices = SB16_MIXER_DEVICES;
441 devc->iomap = &sb16_mix;
443 else
445 devc->supported_devices = ALS007_MIXER_DEVICES;
446 devc->iomap = &als007_mix;
448 break;
450 default:
451 printk(KERN_WARNING "sb_mixer: Unsupported mixer type %d\n", devc->model);
452 return 0;
455 m = sound_alloc_mixerdev();
456 if (m == -1)
457 return 0;
459 mixer_devs[m] = (struct mixer_operations *)kmalloc(sizeof(struct mixer_operations), GFP_KERNEL);
460 if (mixer_devs[m] == NULL)
462 printk(KERN_ERR "sb_mixer: Can't allocate memory\n");
463 sound_unload_mixerdev(m);
464 return 0;
467 if (devc->submodel != SUBMDL_ALS007)
468 memcpy ((char *) mixer_devs[m], (char *) &sb_mixer_operations, sizeof (struct mixer_operations));
469 else
470 memcpy ((char *) mixer_devs[m], (char *) &als007_mixer_operations, sizeof (struct mixer_operations));
472 mixer_devs[m]->devc = devc;
473 devc->my_mixerdev = m;
474 sb_mixer_reset(devc);
475 return 1;
478 #endif