xref: /linux/sound/isa/sb/sb_mixer.c (revision a9e6060bb2a6cae6d43a98ec0794844ad01273d3)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
4  *  Routines for Sound Blaster mixer control
5  */
6 
7 #include <linux/io.h>
8 #include <linux/delay.h>
9 #include <linux/string.h>
10 #include <linux/time.h>
11 #include <sound/core.h>
12 #include <sound/sb.h>
13 #include <sound/control.h>
14 
15 #undef IO_DEBUG
16 
snd_sbmixer_write(struct snd_sb * chip,unsigned char reg,unsigned char data)17 void snd_sbmixer_write(struct snd_sb *chip, unsigned char reg, unsigned char data)
18 {
19 	outb(reg, SBP(chip, MIXER_ADDR));
20 	udelay(10);
21 	outb(data, SBP(chip, MIXER_DATA));
22 	udelay(10);
23 #ifdef IO_DEBUG
24 	dev_dbg(chip->card->dev, "mixer_write 0x%x 0x%x\n", reg, data);
25 #endif
26 }
27 
snd_sbmixer_read(struct snd_sb * chip,unsigned char reg)28 unsigned char snd_sbmixer_read(struct snd_sb *chip, unsigned char reg)
29 {
30 	unsigned char result;
31 
32 	outb(reg, SBP(chip, MIXER_ADDR));
33 	udelay(10);
34 	result = inb(SBP(chip, MIXER_DATA));
35 	udelay(10);
36 #ifdef IO_DEBUG
37 	dev_dbg(chip->card->dev, "mixer_read 0x%x 0x%x\n", reg, result);
38 #endif
39 	return result;
40 }
41 
42 /*
43  * Single channel mixer element
44  */
45 
snd_sbmixer_info_single(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)46 static int snd_sbmixer_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
47 {
48 	int mask = (kcontrol->private_value >> 24) & 0xff;
49 
50 	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
51 	uinfo->count = 1;
52 	uinfo->value.integer.min = 0;
53 	uinfo->value.integer.max = mask;
54 	return 0;
55 }
56 
snd_sbmixer_get_single(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)57 static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
58 {
59 	struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
60 	unsigned long flags;
61 	int reg = kcontrol->private_value & 0xff;
62 	int shift = (kcontrol->private_value >> 16) & 0xff;
63 	int mask = (kcontrol->private_value >> 24) & 0xff;
64 	unsigned char val;
65 
66 	spin_lock_irqsave(&sb->mixer_lock, flags);
67 	val = (snd_sbmixer_read(sb, reg) >> shift) & mask;
68 	spin_unlock_irqrestore(&sb->mixer_lock, flags);
69 	ucontrol->value.integer.value[0] = val;
70 	return 0;
71 }
72 
snd_sbmixer_put_single(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)73 static int snd_sbmixer_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
74 {
75 	struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
76 	unsigned long flags;
77 	int reg = kcontrol->private_value & 0xff;
78 	int shift = (kcontrol->private_value >> 16) & 0x07;
79 	int mask = (kcontrol->private_value >> 24) & 0xff;
80 	int change;
81 	unsigned char val, oval;
82 
83 	val = (ucontrol->value.integer.value[0] & mask) << shift;
84 	spin_lock_irqsave(&sb->mixer_lock, flags);
85 	oval = snd_sbmixer_read(sb, reg);
86 	val = (oval & ~(mask << shift)) | val;
87 	change = val != oval;
88 	if (change)
89 		snd_sbmixer_write(sb, reg, val);
90 	spin_unlock_irqrestore(&sb->mixer_lock, flags);
91 	return change;
92 }
93 
94 /*
95  * Double channel mixer element
96  */
97 
snd_sbmixer_info_double(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)98 static int snd_sbmixer_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
99 {
100 	int mask = (kcontrol->private_value >> 24) & 0xff;
101 
102 	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
103 	uinfo->count = 2;
104 	uinfo->value.integer.min = 0;
105 	uinfo->value.integer.max = mask;
106 	return 0;
107 }
108 
snd_sbmixer_get_double(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)109 static int snd_sbmixer_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
110 {
111 	struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
112 	unsigned long flags;
113 	int left_reg = kcontrol->private_value & 0xff;
114 	int right_reg = (kcontrol->private_value >> 8) & 0xff;
115 	int left_shift = (kcontrol->private_value >> 16) & 0x07;
116 	int right_shift = (kcontrol->private_value >> 19) & 0x07;
117 	int mask = (kcontrol->private_value >> 24) & 0xff;
118 	unsigned char left, right;
119 
120 	spin_lock_irqsave(&sb->mixer_lock, flags);
121 	left = (snd_sbmixer_read(sb, left_reg) >> left_shift) & mask;
122 	right = (snd_sbmixer_read(sb, right_reg) >> right_shift) & mask;
123 	spin_unlock_irqrestore(&sb->mixer_lock, flags);
124 	ucontrol->value.integer.value[0] = left;
125 	ucontrol->value.integer.value[1] = right;
126 	return 0;
127 }
128 
snd_sbmixer_put_double(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)129 static int snd_sbmixer_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
130 {
131 	struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
132 	unsigned long flags;
133 	int left_reg = kcontrol->private_value & 0xff;
134 	int right_reg = (kcontrol->private_value >> 8) & 0xff;
135 	int left_shift = (kcontrol->private_value >> 16) & 0x07;
136 	int right_shift = (kcontrol->private_value >> 19) & 0x07;
137 	int mask = (kcontrol->private_value >> 24) & 0xff;
138 	int change;
139 	unsigned char left, right, oleft, oright;
140 
141 	left = (ucontrol->value.integer.value[0] & mask) << left_shift;
142 	right = (ucontrol->value.integer.value[1] & mask) << right_shift;
143 	spin_lock_irqsave(&sb->mixer_lock, flags);
144 	if (left_reg == right_reg) {
145 		oleft = snd_sbmixer_read(sb, left_reg);
146 		left = (oleft & ~((mask << left_shift) | (mask << right_shift))) | left | right;
147 		change = left != oleft;
148 		if (change)
149 			snd_sbmixer_write(sb, left_reg, left);
150 	} else {
151 		oleft = snd_sbmixer_read(sb, left_reg);
152 		oright = snd_sbmixer_read(sb, right_reg);
153 		left = (oleft & ~(mask << left_shift)) | left;
154 		right = (oright & ~(mask << right_shift)) | right;
155 		change = left != oleft || right != oright;
156 		if (change) {
157 			snd_sbmixer_write(sb, left_reg, left);
158 			snd_sbmixer_write(sb, right_reg, right);
159 		}
160 	}
161 	spin_unlock_irqrestore(&sb->mixer_lock, flags);
162 	return change;
163 }
164 
165 /*
166  * DT-019x / ALS-007 capture/input switch
167  */
168 
snd_dt019x_input_sw_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)169 static int snd_dt019x_input_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
170 {
171 	static const char * const texts[5] = {
172 		"CD", "Mic", "Line", "Synth", "Master"
173 	};
174 
175 	return snd_ctl_enum_info(uinfo, 1, 5, texts);
176 }
177 
snd_dt019x_input_sw_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)178 static int snd_dt019x_input_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
179 {
180 	struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
181 	unsigned long flags;
182 	unsigned char oval;
183 
184 	spin_lock_irqsave(&sb->mixer_lock, flags);
185 	oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW);
186 	spin_unlock_irqrestore(&sb->mixer_lock, flags);
187 	switch (oval & 0x07) {
188 	case SB_DT019X_CAP_CD:
189 		ucontrol->value.enumerated.item[0] = 0;
190 		break;
191 	case SB_DT019X_CAP_MIC:
192 		ucontrol->value.enumerated.item[0] = 1;
193 		break;
194 	case SB_DT019X_CAP_LINE:
195 		ucontrol->value.enumerated.item[0] = 2;
196 		break;
197 	case SB_DT019X_CAP_MAIN:
198 		ucontrol->value.enumerated.item[0] = 4;
199 		break;
200 	/* To record the synth on these cards you must record the main.   */
201 	/* Thus SB_DT019X_CAP_SYNTH == SB_DT019X_CAP_MAIN and would cause */
202 	/* duplicate case labels if left uncommented. */
203 	/* case SB_DT019X_CAP_SYNTH:
204 	 *	ucontrol->value.enumerated.item[0] = 3;
205 	 *	break;
206 	 */
207 	default:
208 		ucontrol->value.enumerated.item[0] = 4;
209 		break;
210 	}
211 	return 0;
212 }
213 
snd_dt019x_input_sw_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)214 static int snd_dt019x_input_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
215 {
216 	struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
217 	unsigned long flags;
218 	int change;
219 	unsigned char nval, oval;
220 
221 	if (ucontrol->value.enumerated.item[0] > 4)
222 		return -EINVAL;
223 	switch (ucontrol->value.enumerated.item[0]) {
224 	case 0:
225 		nval = SB_DT019X_CAP_CD;
226 		break;
227 	case 1:
228 		nval = SB_DT019X_CAP_MIC;
229 		break;
230 	case 2:
231 		nval = SB_DT019X_CAP_LINE;
232 		break;
233 	case 3:
234 		nval = SB_DT019X_CAP_SYNTH;
235 		break;
236 	case 4:
237 		nval = SB_DT019X_CAP_MAIN;
238 		break;
239 	default:
240 		nval = SB_DT019X_CAP_MAIN;
241 	}
242 	spin_lock_irqsave(&sb->mixer_lock, flags);
243 	oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW);
244 	change = nval != oval;
245 	if (change)
246 		snd_sbmixer_write(sb, SB_DT019X_CAPTURE_SW, nval);
247 	spin_unlock_irqrestore(&sb->mixer_lock, flags);
248 	return change;
249 }
250 
251 /*
252  * ALS4000 mono recording control switch
253  */
254 
snd_als4k_mono_capture_route_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)255 static int snd_als4k_mono_capture_route_info(struct snd_kcontrol *kcontrol,
256 					     struct snd_ctl_elem_info *uinfo)
257 {
258 	static const char * const texts[3] = {
259 		"L chan only", "R chan only", "L ch/2 + R ch/2"
260 	};
261 
262 	return snd_ctl_enum_info(uinfo, 1, 3, texts);
263 }
264 
snd_als4k_mono_capture_route_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)265 static int snd_als4k_mono_capture_route_get(struct snd_kcontrol *kcontrol,
266 				struct snd_ctl_elem_value *ucontrol)
267 {
268 	struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
269 	unsigned long flags;
270 	unsigned char oval;
271 
272 	spin_lock_irqsave(&sb->mixer_lock, flags);
273 	oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL);
274 	spin_unlock_irqrestore(&sb->mixer_lock, flags);
275 	oval >>= 6;
276 	if (oval > 2)
277 		oval = 2;
278 
279 	ucontrol->value.enumerated.item[0] = oval;
280 	return 0;
281 }
282 
snd_als4k_mono_capture_route_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)283 static int snd_als4k_mono_capture_route_put(struct snd_kcontrol *kcontrol,
284 				struct snd_ctl_elem_value *ucontrol)
285 {
286 	struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
287 	unsigned long flags;
288 	int change;
289 	unsigned char nval, oval;
290 
291 	if (ucontrol->value.enumerated.item[0] > 2)
292 		return -EINVAL;
293 	spin_lock_irqsave(&sb->mixer_lock, flags);
294 	oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL);
295 
296 	nval = (oval & ~(3 << 6))
297 	     | (ucontrol->value.enumerated.item[0] << 6);
298 	change = nval != oval;
299 	if (change)
300 		snd_sbmixer_write(sb, SB_ALS4000_MONO_IO_CTRL, nval);
301 	spin_unlock_irqrestore(&sb->mixer_lock, flags);
302 	return change;
303 }
304 
305 /*
306  * SBPRO input multiplexer
307  */
308 
snd_sb8mixer_info_mux(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)309 static int snd_sb8mixer_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
310 {
311 	static const char * const texts[3] = {
312 		"Mic", "CD", "Line"
313 	};
314 
315 	return snd_ctl_enum_info(uinfo, 1, 3, texts);
316 }
317 
318 
snd_sb8mixer_get_mux(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)319 static int snd_sb8mixer_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
320 {
321 	struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
322 	unsigned long flags;
323 	unsigned char oval;
324 
325 	spin_lock_irqsave(&sb->mixer_lock, flags);
326 	oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE);
327 	spin_unlock_irqrestore(&sb->mixer_lock, flags);
328 	switch ((oval >> 0x01) & 0x03) {
329 	case SB_DSP_MIXS_CD:
330 		ucontrol->value.enumerated.item[0] = 1;
331 		break;
332 	case SB_DSP_MIXS_LINE:
333 		ucontrol->value.enumerated.item[0] = 2;
334 		break;
335 	default:
336 		ucontrol->value.enumerated.item[0] = 0;
337 		break;
338 	}
339 	return 0;
340 }
341 
snd_sb8mixer_put_mux(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)342 static int snd_sb8mixer_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
343 {
344 	struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
345 	unsigned long flags;
346 	int change;
347 	unsigned char nval, oval;
348 
349 	if (ucontrol->value.enumerated.item[0] > 2)
350 		return -EINVAL;
351 	switch (ucontrol->value.enumerated.item[0]) {
352 	case 1:
353 		nval = SB_DSP_MIXS_CD;
354 		break;
355 	case 2:
356 		nval = SB_DSP_MIXS_LINE;
357 		break;
358 	default:
359 		nval = SB_DSP_MIXS_MIC;
360 	}
361 	nval <<= 1;
362 	spin_lock_irqsave(&sb->mixer_lock, flags);
363 	oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE);
364 	nval |= oval & ~0x06;
365 	change = nval != oval;
366 	if (change)
367 		snd_sbmixer_write(sb, SB_DSP_CAPTURE_SOURCE, nval);
368 	spin_unlock_irqrestore(&sb->mixer_lock, flags);
369 	return change;
370 }
371 
372 /*
373  * SB16 input switch
374  */
375 
snd_sb16mixer_info_input_sw(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)376 static int snd_sb16mixer_info_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
377 {
378 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
379 	uinfo->count = 4;
380 	uinfo->value.integer.min = 0;
381 	uinfo->value.integer.max = 1;
382 	return 0;
383 }
384 
snd_sb16mixer_get_input_sw(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)385 static int snd_sb16mixer_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
386 {
387 	struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
388 	unsigned long flags;
389 	int reg1 = kcontrol->private_value & 0xff;
390 	int reg2 = (kcontrol->private_value >> 8) & 0xff;
391 	int left_shift = (kcontrol->private_value >> 16) & 0x0f;
392 	int right_shift = (kcontrol->private_value >> 24) & 0x0f;
393 	unsigned char val1, val2;
394 
395 	spin_lock_irqsave(&sb->mixer_lock, flags);
396 	val1 = snd_sbmixer_read(sb, reg1);
397 	val2 = snd_sbmixer_read(sb, reg2);
398 	spin_unlock_irqrestore(&sb->mixer_lock, flags);
399 	ucontrol->value.integer.value[0] = (val1 >> left_shift) & 0x01;
400 	ucontrol->value.integer.value[1] = (val2 >> left_shift) & 0x01;
401 	ucontrol->value.integer.value[2] = (val1 >> right_shift) & 0x01;
402 	ucontrol->value.integer.value[3] = (val2 >> right_shift) & 0x01;
403 	return 0;
404 }
405 
snd_sb16mixer_put_input_sw(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)406 static int snd_sb16mixer_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
407 {
408 	struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
409 	unsigned long flags;
410 	int reg1 = kcontrol->private_value & 0xff;
411 	int reg2 = (kcontrol->private_value >> 8) & 0xff;
412 	int left_shift = (kcontrol->private_value >> 16) & 0x0f;
413 	int right_shift = (kcontrol->private_value >> 24) & 0x0f;
414 	int change;
415 	unsigned char val1, val2, oval1, oval2;
416 
417 	spin_lock_irqsave(&sb->mixer_lock, flags);
418 	oval1 = snd_sbmixer_read(sb, reg1);
419 	oval2 = snd_sbmixer_read(sb, reg2);
420 	val1 = oval1 & ~((1 << left_shift) | (1 << right_shift));
421 	val2 = oval2 & ~((1 << left_shift) | (1 << right_shift));
422 	val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift;
423 	val2 |= (ucontrol->value.integer.value[1] & 1) << left_shift;
424 	val1 |= (ucontrol->value.integer.value[2] & 1) << right_shift;
425 	val2 |= (ucontrol->value.integer.value[3] & 1) << right_shift;
426 	change = val1 != oval1 || val2 != oval2;
427 	if (change) {
428 		snd_sbmixer_write(sb, reg1, val1);
429 		snd_sbmixer_write(sb, reg2, val2);
430 	}
431 	spin_unlock_irqrestore(&sb->mixer_lock, flags);
432 	return change;
433 }
434 
435 
436 /*
437  */
438 /*
439  */
snd_sbmixer_add_ctl(struct snd_sb * chip,const char * name,int index,int type,unsigned long value)440 int snd_sbmixer_add_ctl(struct snd_sb *chip, const char *name, int index, int type, unsigned long value)
441 {
442 	static const struct snd_kcontrol_new newctls[] = {
443 		[SB_MIX_SINGLE] = {
444 			.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
445 			.info = snd_sbmixer_info_single,
446 			.get = snd_sbmixer_get_single,
447 			.put = snd_sbmixer_put_single,
448 		},
449 		[SB_MIX_DOUBLE] = {
450 			.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
451 			.info = snd_sbmixer_info_double,
452 			.get = snd_sbmixer_get_double,
453 			.put = snd_sbmixer_put_double,
454 		},
455 		[SB_MIX_INPUT_SW] = {
456 			.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
457 			.info = snd_sb16mixer_info_input_sw,
458 			.get = snd_sb16mixer_get_input_sw,
459 			.put = snd_sb16mixer_put_input_sw,
460 		},
461 		[SB_MIX_CAPTURE_PRO] = {
462 			.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
463 			.info = snd_sb8mixer_info_mux,
464 			.get = snd_sb8mixer_get_mux,
465 			.put = snd_sb8mixer_put_mux,
466 		},
467 		[SB_MIX_CAPTURE_DT019X] = {
468 			.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
469 			.info = snd_dt019x_input_sw_info,
470 			.get = snd_dt019x_input_sw_get,
471 			.put = snd_dt019x_input_sw_put,
472 		},
473 		[SB_MIX_MONO_CAPTURE_ALS4K] = {
474 			.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
475 			.info = snd_als4k_mono_capture_route_info,
476 			.get = snd_als4k_mono_capture_route_get,
477 			.put = snd_als4k_mono_capture_route_put,
478 		},
479 	};
480 	struct snd_kcontrol *ctl;
481 	int err;
482 
483 	ctl = snd_ctl_new1(&newctls[type], chip);
484 	if (! ctl)
485 		return -ENOMEM;
486 	strscpy(ctl->id.name, name, sizeof(ctl->id.name));
487 	ctl->id.index = index;
488 	ctl->private_value = value;
489 	err = snd_ctl_add(chip->card, ctl);
490 	if (err < 0)
491 		return err;
492 	return 0;
493 }
494 
495 /*
496  * SB 2.0 specific mixer elements
497  */
498 
499 static const struct sbmix_elem snd_sb20_controls[] = {
500 	SB_SINGLE("Master Playback Volume", SB_DSP20_MASTER_DEV, 1, 7),
501 	SB_SINGLE("PCM Playback Volume", SB_DSP20_PCM_DEV, 1, 3),
502 	SB_SINGLE("Synth Playback Volume", SB_DSP20_FM_DEV, 1, 7),
503 	SB_SINGLE("CD Playback Volume", SB_DSP20_CD_DEV, 1, 7)
504 };
505 
506 static const unsigned char snd_sb20_init_values[][2] = {
507 	{ SB_DSP20_MASTER_DEV, 0 },
508 	{ SB_DSP20_FM_DEV, 0 },
509 };
510 
511 /*
512  * SB Pro specific mixer elements
513  */
514 static const struct sbmix_elem snd_sbpro_controls[] = {
515 	SB_DOUBLE("Master Playback Volume",
516 		  SB_DSP_MASTER_DEV, SB_DSP_MASTER_DEV, 5, 1, 7),
517 	SB_DOUBLE("PCM Playback Volume",
518 		  SB_DSP_PCM_DEV, SB_DSP_PCM_DEV, 5, 1, 7),
519 	SB_SINGLE("PCM Playback Filter", SB_DSP_PLAYBACK_FILT, 5, 1),
520 	SB_DOUBLE("Synth Playback Volume",
521 		  SB_DSP_FM_DEV, SB_DSP_FM_DEV, 5, 1, 7),
522 	SB_DOUBLE("CD Playback Volume", SB_DSP_CD_DEV, SB_DSP_CD_DEV, 5, 1, 7),
523 	SB_DOUBLE("Line Playback Volume",
524 		  SB_DSP_LINE_DEV, SB_DSP_LINE_DEV, 5, 1, 7),
525 	SB_SINGLE("Mic Playback Volume", SB_DSP_MIC_DEV, 1, 3),
526 	{
527 		.name = "Capture Source",
528 		.type = SB_MIX_CAPTURE_PRO
529 	},
530 	SB_SINGLE("Capture Filter", SB_DSP_CAPTURE_FILT, 5, 1),
531 	SB_SINGLE("Capture Low-Pass Filter", SB_DSP_CAPTURE_FILT, 3, 1)
532 };
533 
534 static const unsigned char snd_sbpro_init_values[][2] = {
535 	{ SB_DSP_MASTER_DEV, 0 },
536 	{ SB_DSP_PCM_DEV, 0 },
537 	{ SB_DSP_FM_DEV, 0 },
538 };
539 
540 /*
541  * SB16 specific mixer elements
542  */
543 static const struct sbmix_elem snd_sb16_controls[] = {
544 	SB_DOUBLE("Master Playback Volume",
545 		  SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31),
546 	SB_DOUBLE("PCM Playback Volume",
547 		  SB_DSP4_PCM_DEV, (SB_DSP4_PCM_DEV + 1), 3, 3, 31),
548 	SB16_INPUT_SW("Synth Capture Route",
549 		      SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 6, 5),
550 	SB_DOUBLE("Synth Playback Volume",
551 		  SB_DSP4_SYNTH_DEV, (SB_DSP4_SYNTH_DEV + 1), 3, 3, 31),
552 	SB16_INPUT_SW("CD Capture Route",
553 		      SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 2, 1),
554 	SB_DOUBLE("CD Playback Switch",
555 		  SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1),
556 	SB_DOUBLE("CD Playback Volume",
557 		  SB_DSP4_CD_DEV, (SB_DSP4_CD_DEV + 1), 3, 3, 31),
558 	SB16_INPUT_SW("Mic Capture Route",
559 		      SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 0, 0),
560 	SB_SINGLE("Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1),
561 	SB_SINGLE("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31),
562 	SB_SINGLE("Beep Volume", SB_DSP4_SPEAKER_DEV, 6, 3),
563 	SB_DOUBLE("Capture Volume",
564 		  SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3),
565 	SB_DOUBLE("Playback Volume",
566 		  SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3),
567 	SB16_INPUT_SW("Line Capture Route",
568 		      SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 4, 3),
569 	SB_DOUBLE("Line Playback Switch",
570 		  SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1),
571 	SB_DOUBLE("Line Playback Volume",
572 		  SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31),
573 	SB_SINGLE("Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1),
574 	SB_SINGLE("3D Enhancement Switch", SB_DSP4_3DSE, 0, 1),
575 	SB_DOUBLE("Tone Control - Bass",
576 		  SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15),
577 	SB_DOUBLE("Tone Control - Treble",
578 		  SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15)
579 };
580 
581 static const unsigned char snd_sb16_init_values[][2] = {
582 	{ SB_DSP4_MASTER_DEV + 0, 0 },
583 	{ SB_DSP4_MASTER_DEV + 1, 0 },
584 	{ SB_DSP4_PCM_DEV + 0, 0 },
585 	{ SB_DSP4_PCM_DEV + 1, 0 },
586 	{ SB_DSP4_SYNTH_DEV + 0, 0 },
587 	{ SB_DSP4_SYNTH_DEV + 1, 0 },
588 	{ SB_DSP4_INPUT_LEFT, 0 },
589 	{ SB_DSP4_INPUT_RIGHT, 0 },
590 	{ SB_DSP4_OUTPUT_SW, 0 },
591 	{ SB_DSP4_SPEAKER_DEV, 0 },
592 };
593 
594 /*
595  * DT019x specific mixer elements
596  */
597 static const struct sbmix_elem snd_dt019x_controls[] = {
598 	/* ALS4000 below has some parts which we might be lacking,
599 	 * e.g. snd_als4000_ctl_mono_playback_switch - check it! */
600 	SB_DOUBLE("Master Playback Volume",
601 		  SB_DT019X_MASTER_DEV, SB_DT019X_MASTER_DEV, 4, 0, 15),
602 	SB_DOUBLE("PCM Playback Switch",
603 		  SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 2, 1, 1),
604 	SB_DOUBLE("PCM Playback Volume",
605 		  SB_DT019X_PCM_DEV, SB_DT019X_PCM_DEV, 4, 0, 15),
606 	SB_DOUBLE("Synth Playback Switch",
607 		  SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 4, 3, 1),
608 	SB_DOUBLE("Synth Playback Volume",
609 		  SB_DT019X_SYNTH_DEV, SB_DT019X_SYNTH_DEV, 4, 0, 15),
610 	SB_DOUBLE("CD Playback Switch",
611 		  SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1),
612 	SB_DOUBLE("CD Playback Volume",
613 		  SB_DT019X_CD_DEV, SB_DT019X_CD_DEV, 4, 0, 15),
614 	SB_SINGLE("Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1),
615 	SB_SINGLE("Mic Playback Volume", SB_DT019X_MIC_DEV, 4, 7),
616 	SB_SINGLE("Beep Volume", SB_DT019X_SPKR_DEV, 0,  7),
617 	SB_DOUBLE("Line Playback Switch",
618 		  SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1),
619 	SB_DOUBLE("Line Playback Volume",
620 		  SB_DT019X_LINE_DEV, SB_DT019X_LINE_DEV, 4, 0, 15),
621 	{
622 		.name = "Capture Source",
623 		.type = SB_MIX_CAPTURE_DT019X
624 	}
625 };
626 
627 static const unsigned char snd_dt019x_init_values[][2] = {
628         { SB_DT019X_MASTER_DEV, 0 },
629         { SB_DT019X_PCM_DEV, 0 },
630         { SB_DT019X_SYNTH_DEV, 0 },
631         { SB_DT019X_CD_DEV, 0 },
632         { SB_DT019X_MIC_DEV, 0 },	/* Includes PC-speaker in high nibble */
633         { SB_DT019X_LINE_DEV, 0 },
634         { SB_DSP4_OUTPUT_SW, 0 },
635         { SB_DT019X_OUTPUT_SW2, 0 },
636         { SB_DT019X_CAPTURE_SW, 0x06 },
637 };
638 
639 /*
640  * ALS4000 specific mixer elements
641  */
642 static const struct sbmix_elem snd_als4000_controls[] = {
643 	SB_DOUBLE("PCM Playback Switch",
644 		  SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 2, 1, 1),
645 	SB_DOUBLE("Synth Playback Switch",
646 		  SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 4, 3, 1),
647 	SB_SINGLE("Mic Boost (+20dB)", SB_ALS4000_MIC_IN_GAIN, 0, 0x03),
648 	SB_SINGLE("Master Mono Playback Switch", SB_ALS4000_MONO_IO_CTRL, 5, 1),
649 	{
650 		.name = "Master Mono Capture Route",
651 		.type = SB_MIX_MONO_CAPTURE_ALS4K
652 	},
653 	SB_SINGLE("Mono Playback Switch", SB_DT019X_OUTPUT_SW2, 0, 1),
654 	SB_SINGLE("Analog Loopback Switch", SB_ALS4000_MIC_IN_GAIN, 7, 0x01),
655 	SB_SINGLE("3D Control - Switch", SB_ALS4000_3D_SND_FX, 6, 0x01),
656 	SB_SINGLE("Digital Loopback Switch",
657 		  SB_ALS4000_CR3_CONFIGURATION, 7, 0x01),
658 	/* FIXME: functionality of 3D controls might be swapped, I didn't find
659 	 * a description of how to identify what is supposed to be what */
660 	SB_SINGLE("3D Control - Level", SB_ALS4000_3D_SND_FX, 0, 0x07),
661 	/* FIXME: maybe there's actually some standard 3D ctrl name for it?? */
662 	SB_SINGLE("3D Control - Freq", SB_ALS4000_3D_SND_FX, 4, 0x03),
663 	/* FIXME: ALS4000a.pdf mentions BBD (Bucket Brigade Device) time delay,
664 	 * but what ALSA 3D attribute is that actually? "Center", "Depth",
665 	 * "Wide" or "Space" or even "Level"? Assuming "Wide" for now... */
666 	SB_SINGLE("3D Control - Wide", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f),
667 	SB_SINGLE("3D PowerOff Switch", SB_ALS4000_3D_TIME_DELAY, 4, 0x01),
668 	SB_SINGLE("Master Playback 8kHz / 20kHz LPF Switch",
669 		  SB_ALS4000_FMDAC, 5, 0x01),
670 #ifdef NOT_AVAILABLE
671 	SB_SINGLE("FMDAC Switch (Option ?)", SB_ALS4000_FMDAC, 0, 0x01),
672 	SB_SINGLE("QSound Mode", SB_ALS4000_QSOUND, 1, 0x1f),
673 #endif
674 };
675 
676 static const unsigned char snd_als4000_init_values[][2] = {
677 	{ SB_DSP4_MASTER_DEV + 0, 0 },
678 	{ SB_DSP4_MASTER_DEV + 1, 0 },
679 	{ SB_DSP4_PCM_DEV + 0, 0 },
680 	{ SB_DSP4_PCM_DEV + 1, 0 },
681 	{ SB_DSP4_SYNTH_DEV + 0, 0 },
682 	{ SB_DSP4_SYNTH_DEV + 1, 0 },
683 	{ SB_DSP4_SPEAKER_DEV, 0 },
684 	{ SB_DSP4_OUTPUT_SW, 0 },
685 	{ SB_DSP4_INPUT_LEFT, 0 },
686 	{ SB_DSP4_INPUT_RIGHT, 0 },
687 	{ SB_DT019X_OUTPUT_SW2, 0 },
688 	{ SB_ALS4000_MIC_IN_GAIN, 0 },
689 };
690 
691 /*
692  */
snd_sbmixer_init(struct snd_sb * chip,const struct sbmix_elem * controls,int controls_count,const unsigned char map[][2],int map_count,char * name)693 static int snd_sbmixer_init(struct snd_sb *chip,
694 			    const struct sbmix_elem *controls,
695 			    int controls_count,
696 			    const unsigned char map[][2],
697 			    int map_count,
698 			    char *name)
699 {
700 	unsigned long flags;
701 	struct snd_card *card = chip->card;
702 	int idx, err;
703 
704 	/* mixer reset */
705 	spin_lock_irqsave(&chip->mixer_lock, flags);
706 	snd_sbmixer_write(chip, 0x00, 0x00);
707 	spin_unlock_irqrestore(&chip->mixer_lock, flags);
708 
709 	/* mute and zero volume channels */
710 	for (idx = 0; idx < map_count; idx++) {
711 		spin_lock_irqsave(&chip->mixer_lock, flags);
712 		snd_sbmixer_write(chip, map[idx][0], map[idx][1]);
713 		spin_unlock_irqrestore(&chip->mixer_lock, flags);
714 	}
715 
716 	for (idx = 0; idx < controls_count; idx++) {
717 		err = snd_sbmixer_add_ctl_elem(chip, &controls[idx]);
718 		if (err < 0)
719 			return err;
720 	}
721 	snd_component_add(card, name);
722 	strscpy(card->mixername, name);
723 	return 0;
724 }
725 
snd_sbmixer_new(struct snd_sb * chip)726 int snd_sbmixer_new(struct snd_sb *chip)
727 {
728 	struct snd_card *card;
729 	int err;
730 
731 	if (snd_BUG_ON(!chip || !chip->card))
732 		return -EINVAL;
733 
734 	card = chip->card;
735 
736 	switch (chip->hardware) {
737 	case SB_HW_10:
738 		return 0; /* no mixer chip on SB1.x */
739 	case SB_HW_20:
740 	case SB_HW_201:
741 		err = snd_sbmixer_init(chip,
742 				       snd_sb20_controls,
743 				       ARRAY_SIZE(snd_sb20_controls),
744 				       snd_sb20_init_values,
745 				       ARRAY_SIZE(snd_sb20_init_values),
746 				       "CTL1335");
747 		if (err < 0)
748 			return err;
749 		break;
750 	case SB_HW_PRO:
751 	case SB_HW_JAZZ16:
752 		err = snd_sbmixer_init(chip,
753 				       snd_sbpro_controls,
754 				       ARRAY_SIZE(snd_sbpro_controls),
755 				       snd_sbpro_init_values,
756 				       ARRAY_SIZE(snd_sbpro_init_values),
757 				       "CTL1345");
758 		if (err < 0)
759 			return err;
760 		break;
761 	case SB_HW_16:
762 	case SB_HW_ALS100:
763 	case SB_HW_CS5530:
764 		err = snd_sbmixer_init(chip,
765 				       snd_sb16_controls,
766 				       ARRAY_SIZE(snd_sb16_controls),
767 				       snd_sb16_init_values,
768 				       ARRAY_SIZE(snd_sb16_init_values),
769 				       "CTL1745");
770 		if (err < 0)
771 			return err;
772 		break;
773 	case SB_HW_ALS4000:
774 		/* use only the first 16 controls from SB16 */
775 		err = snd_sbmixer_init(chip,
776 					snd_sb16_controls,
777 					16,
778 					snd_sb16_init_values,
779 					ARRAY_SIZE(snd_sb16_init_values),
780 					"ALS4000");
781 		if (err < 0)
782 			return err;
783 		err = snd_sbmixer_init(chip,
784 				       snd_als4000_controls,
785 				       ARRAY_SIZE(snd_als4000_controls),
786 				       snd_als4000_init_values,
787 				       ARRAY_SIZE(snd_als4000_init_values),
788 				       "ALS4000");
789 		if (err < 0)
790 			return err;
791 		break;
792 	case SB_HW_DT019X:
793 		err = snd_sbmixer_init(chip,
794 				       snd_dt019x_controls,
795 				       ARRAY_SIZE(snd_dt019x_controls),
796 				       snd_dt019x_init_values,
797 				       ARRAY_SIZE(snd_dt019x_init_values),
798 				       "DT019X");
799 		if (err < 0)
800 			return err;
801 		break;
802 	default:
803 		strscpy(card->mixername, "???");
804 	}
805 	return 0;
806 }
807 
808 #ifdef CONFIG_PM
809 static const unsigned char sb20_saved_regs[] = {
810 	SB_DSP20_MASTER_DEV,
811 	SB_DSP20_PCM_DEV,
812 	SB_DSP20_FM_DEV,
813 	SB_DSP20_CD_DEV,
814 };
815 
816 static const unsigned char sbpro_saved_regs[] = {
817 	SB_DSP_MASTER_DEV,
818 	SB_DSP_PCM_DEV,
819 	SB_DSP_PLAYBACK_FILT,
820 	SB_DSP_FM_DEV,
821 	SB_DSP_CD_DEV,
822 	SB_DSP_LINE_DEV,
823 	SB_DSP_MIC_DEV,
824 	SB_DSP_CAPTURE_SOURCE,
825 	SB_DSP_CAPTURE_FILT,
826 };
827 
828 static const unsigned char sb16_saved_regs[] = {
829 	SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1,
830 	SB_DSP4_3DSE,
831 	SB_DSP4_BASS_DEV, SB_DSP4_BASS_DEV + 1,
832 	SB_DSP4_TREBLE_DEV, SB_DSP4_TREBLE_DEV + 1,
833 	SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1,
834 	SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT,
835 	SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1,
836 	SB_DSP4_OUTPUT_SW,
837 	SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1,
838 	SB_DSP4_LINE_DEV, SB_DSP4_LINE_DEV + 1,
839 	SB_DSP4_MIC_DEV,
840 	SB_DSP4_SPEAKER_DEV,
841 	SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1,
842 	SB_DSP4_OGAIN_DEV, SB_DSP4_OGAIN_DEV + 1,
843 	SB_DSP4_MIC_AGC
844 };
845 
846 static const unsigned char dt019x_saved_regs[] = {
847 	SB_DT019X_MASTER_DEV,
848 	SB_DT019X_PCM_DEV,
849 	SB_DT019X_SYNTH_DEV,
850 	SB_DT019X_CD_DEV,
851 	SB_DT019X_MIC_DEV,
852 	SB_DT019X_SPKR_DEV,
853 	SB_DT019X_LINE_DEV,
854 	SB_DSP4_OUTPUT_SW,
855 	SB_DT019X_OUTPUT_SW2,
856 	SB_DT019X_CAPTURE_SW,
857 };
858 
859 static const unsigned char als4000_saved_regs[] = {
860 	/* please verify in dsheet whether regs to be added
861 	   are actually real H/W or just dummy */
862 	SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1,
863 	SB_DSP4_OUTPUT_SW,
864 	SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1,
865 	SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT,
866 	SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1,
867 	SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1,
868 	SB_DSP4_MIC_DEV,
869 	SB_DSP4_SPEAKER_DEV,
870 	SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1,
871 	SB_DSP4_OGAIN_DEV, SB_DSP4_OGAIN_DEV + 1,
872 	SB_DT019X_OUTPUT_SW2,
873 	SB_ALS4000_MONO_IO_CTRL,
874 	SB_ALS4000_MIC_IN_GAIN,
875 	SB_ALS4000_FMDAC,
876 	SB_ALS4000_3D_SND_FX,
877 	SB_ALS4000_3D_TIME_DELAY,
878 	SB_ALS4000_CR3_CONFIGURATION,
879 };
880 
save_mixer(struct snd_sb * chip,const unsigned char * regs,int num_regs)881 static void save_mixer(struct snd_sb *chip, const unsigned char *regs, int num_regs)
882 {
883 	unsigned char *val = chip->saved_regs;
884 	if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs)))
885 		return;
886 	for (; num_regs; num_regs--)
887 		*val++ = snd_sbmixer_read(chip, *regs++);
888 }
889 
restore_mixer(struct snd_sb * chip,const unsigned char * regs,int num_regs)890 static void restore_mixer(struct snd_sb *chip, const unsigned char *regs, int num_regs)
891 {
892 	unsigned char *val = chip->saved_regs;
893 	if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs)))
894 		return;
895 	for (; num_regs; num_regs--)
896 		snd_sbmixer_write(chip, *regs++, *val++);
897 }
898 
snd_sbmixer_suspend(struct snd_sb * chip)899 void snd_sbmixer_suspend(struct snd_sb *chip)
900 {
901 	switch (chip->hardware) {
902 	case SB_HW_20:
903 	case SB_HW_201:
904 		save_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs));
905 		break;
906 	case SB_HW_PRO:
907 	case SB_HW_JAZZ16:
908 		save_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs));
909 		break;
910 	case SB_HW_16:
911 	case SB_HW_ALS100:
912 	case SB_HW_CS5530:
913 		save_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs));
914 		break;
915 	case SB_HW_ALS4000:
916 		save_mixer(chip, als4000_saved_regs, ARRAY_SIZE(als4000_saved_regs));
917 		break;
918 	case SB_HW_DT019X:
919 		save_mixer(chip, dt019x_saved_regs, ARRAY_SIZE(dt019x_saved_regs));
920 		break;
921 	default:
922 		break;
923 	}
924 }
925 
snd_sbmixer_resume(struct snd_sb * chip)926 void snd_sbmixer_resume(struct snd_sb *chip)
927 {
928 	switch (chip->hardware) {
929 	case SB_HW_20:
930 	case SB_HW_201:
931 		restore_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs));
932 		break;
933 	case SB_HW_PRO:
934 	case SB_HW_JAZZ16:
935 		restore_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs));
936 		break;
937 	case SB_HW_16:
938 	case SB_HW_ALS100:
939 	case SB_HW_CS5530:
940 		restore_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs));
941 		break;
942 	case SB_HW_ALS4000:
943 		restore_mixer(chip, als4000_saved_regs, ARRAY_SIZE(als4000_saved_regs));
944 		break;
945 	case SB_HW_DT019X:
946 		restore_mixer(chip, dt019x_saved_regs, ARRAY_SIZE(dt019x_saved_regs));
947 		break;
948 	default:
949 		break;
950 	}
951 }
952 #endif
953