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