OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [sound/] [isa/] [sb/] [sb_mixer.c] - Blame information for rev 3

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.