0001
0002
0003
0004
0005
0006
0007 #include <linux/io.h>
0008 #include <linux/delay.h>
0009 #include <linux/time.h>
0010 #include <sound/core.h>
0011 #include <sound/sb.h>
0012 #include <sound/control.h>
0013
0014 #undef IO_DEBUG
0015
0016 void snd_sbmixer_write(struct snd_sb *chip, unsigned char reg, unsigned char data)
0017 {
0018 outb(reg, SBP(chip, MIXER_ADDR));
0019 udelay(10);
0020 outb(data, SBP(chip, MIXER_DATA));
0021 udelay(10);
0022 #ifdef IO_DEBUG
0023 snd_printk(KERN_DEBUG "mixer_write 0x%x 0x%x\n", reg, data);
0024 #endif
0025 }
0026
0027 unsigned char snd_sbmixer_read(struct snd_sb *chip, unsigned char reg)
0028 {
0029 unsigned char result;
0030
0031 outb(reg, SBP(chip, MIXER_ADDR));
0032 udelay(10);
0033 result = inb(SBP(chip, MIXER_DATA));
0034 udelay(10);
0035 #ifdef IO_DEBUG
0036 snd_printk(KERN_DEBUG "mixer_read 0x%x 0x%x\n", reg, result);
0037 #endif
0038 return result;
0039 }
0040
0041
0042
0043
0044
0045 static int snd_sbmixer_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0046 {
0047 int mask = (kcontrol->private_value >> 24) & 0xff;
0048
0049 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
0050 uinfo->count = 1;
0051 uinfo->value.integer.min = 0;
0052 uinfo->value.integer.max = mask;
0053 return 0;
0054 }
0055
0056 static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0057 {
0058 struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
0059 unsigned long flags;
0060 int reg = kcontrol->private_value & 0xff;
0061 int shift = (kcontrol->private_value >> 16) & 0xff;
0062 int mask = (kcontrol->private_value >> 24) & 0xff;
0063 unsigned char val;
0064
0065 spin_lock_irqsave(&sb->mixer_lock, flags);
0066 val = (snd_sbmixer_read(sb, reg) >> shift) & mask;
0067 spin_unlock_irqrestore(&sb->mixer_lock, flags);
0068 ucontrol->value.integer.value[0] = val;
0069 return 0;
0070 }
0071
0072 static int snd_sbmixer_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0073 {
0074 struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
0075 unsigned long flags;
0076 int reg = kcontrol->private_value & 0xff;
0077 int shift = (kcontrol->private_value >> 16) & 0x07;
0078 int mask = (kcontrol->private_value >> 24) & 0xff;
0079 int change;
0080 unsigned char val, oval;
0081
0082 val = (ucontrol->value.integer.value[0] & mask) << shift;
0083 spin_lock_irqsave(&sb->mixer_lock, flags);
0084 oval = snd_sbmixer_read(sb, reg);
0085 val = (oval & ~(mask << shift)) | val;
0086 change = val != oval;
0087 if (change)
0088 snd_sbmixer_write(sb, reg, val);
0089 spin_unlock_irqrestore(&sb->mixer_lock, flags);
0090 return change;
0091 }
0092
0093
0094
0095
0096
0097 static int snd_sbmixer_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0098 {
0099 int mask = (kcontrol->private_value >> 24) & 0xff;
0100
0101 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
0102 uinfo->count = 2;
0103 uinfo->value.integer.min = 0;
0104 uinfo->value.integer.max = mask;
0105 return 0;
0106 }
0107
0108 static int snd_sbmixer_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0109 {
0110 struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
0111 unsigned long flags;
0112 int left_reg = kcontrol->private_value & 0xff;
0113 int right_reg = (kcontrol->private_value >> 8) & 0xff;
0114 int left_shift = (kcontrol->private_value >> 16) & 0x07;
0115 int right_shift = (kcontrol->private_value >> 19) & 0x07;
0116 int mask = (kcontrol->private_value >> 24) & 0xff;
0117 unsigned char left, right;
0118
0119 spin_lock_irqsave(&sb->mixer_lock, flags);
0120 left = (snd_sbmixer_read(sb, left_reg) >> left_shift) & mask;
0121 right = (snd_sbmixer_read(sb, right_reg) >> right_shift) & mask;
0122 spin_unlock_irqrestore(&sb->mixer_lock, flags);
0123 ucontrol->value.integer.value[0] = left;
0124 ucontrol->value.integer.value[1] = right;
0125 return 0;
0126 }
0127
0128 static int snd_sbmixer_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0129 {
0130 struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
0131 unsigned long flags;
0132 int left_reg = kcontrol->private_value & 0xff;
0133 int right_reg = (kcontrol->private_value >> 8) & 0xff;
0134 int left_shift = (kcontrol->private_value >> 16) & 0x07;
0135 int right_shift = (kcontrol->private_value >> 19) & 0x07;
0136 int mask = (kcontrol->private_value >> 24) & 0xff;
0137 int change;
0138 unsigned char left, right, oleft, oright;
0139
0140 left = (ucontrol->value.integer.value[0] & mask) << left_shift;
0141 right = (ucontrol->value.integer.value[1] & mask) << right_shift;
0142 spin_lock_irqsave(&sb->mixer_lock, flags);
0143 if (left_reg == right_reg) {
0144 oleft = snd_sbmixer_read(sb, left_reg);
0145 left = (oleft & ~((mask << left_shift) | (mask << right_shift))) | left | right;
0146 change = left != oleft;
0147 if (change)
0148 snd_sbmixer_write(sb, left_reg, left);
0149 } else {
0150 oleft = snd_sbmixer_read(sb, left_reg);
0151 oright = snd_sbmixer_read(sb, right_reg);
0152 left = (oleft & ~(mask << left_shift)) | left;
0153 right = (oright & ~(mask << right_shift)) | right;
0154 change = left != oleft || right != oright;
0155 if (change) {
0156 snd_sbmixer_write(sb, left_reg, left);
0157 snd_sbmixer_write(sb, right_reg, right);
0158 }
0159 }
0160 spin_unlock_irqrestore(&sb->mixer_lock, flags);
0161 return change;
0162 }
0163
0164
0165
0166
0167
0168 static int snd_dt019x_input_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0169 {
0170 static const char * const texts[5] = {
0171 "CD", "Mic", "Line", "Synth", "Master"
0172 };
0173
0174 return snd_ctl_enum_info(uinfo, 1, 5, texts);
0175 }
0176
0177 static int snd_dt019x_input_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0178 {
0179 struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
0180 unsigned long flags;
0181 unsigned char oval;
0182
0183 spin_lock_irqsave(&sb->mixer_lock, flags);
0184 oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW);
0185 spin_unlock_irqrestore(&sb->mixer_lock, flags);
0186 switch (oval & 0x07) {
0187 case SB_DT019X_CAP_CD:
0188 ucontrol->value.enumerated.item[0] = 0;
0189 break;
0190 case SB_DT019X_CAP_MIC:
0191 ucontrol->value.enumerated.item[0] = 1;
0192 break;
0193 case SB_DT019X_CAP_LINE:
0194 ucontrol->value.enumerated.item[0] = 2;
0195 break;
0196 case SB_DT019X_CAP_MAIN:
0197 ucontrol->value.enumerated.item[0] = 4;
0198 break;
0199
0200
0201
0202
0203
0204
0205
0206 default:
0207 ucontrol->value.enumerated.item[0] = 4;
0208 break;
0209 }
0210 return 0;
0211 }
0212
0213 static int snd_dt019x_input_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0214 {
0215 struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
0216 unsigned long flags;
0217 int change;
0218 unsigned char nval, oval;
0219
0220 if (ucontrol->value.enumerated.item[0] > 4)
0221 return -EINVAL;
0222 switch (ucontrol->value.enumerated.item[0]) {
0223 case 0:
0224 nval = SB_DT019X_CAP_CD;
0225 break;
0226 case 1:
0227 nval = SB_DT019X_CAP_MIC;
0228 break;
0229 case 2:
0230 nval = SB_DT019X_CAP_LINE;
0231 break;
0232 case 3:
0233 nval = SB_DT019X_CAP_SYNTH;
0234 break;
0235 case 4:
0236 nval = SB_DT019X_CAP_MAIN;
0237 break;
0238 default:
0239 nval = SB_DT019X_CAP_MAIN;
0240 }
0241 spin_lock_irqsave(&sb->mixer_lock, flags);
0242 oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW);
0243 change = nval != oval;
0244 if (change)
0245 snd_sbmixer_write(sb, SB_DT019X_CAPTURE_SW, nval);
0246 spin_unlock_irqrestore(&sb->mixer_lock, flags);
0247 return change;
0248 }
0249
0250
0251
0252
0253
0254 static int snd_als4k_mono_capture_route_info(struct snd_kcontrol *kcontrol,
0255 struct snd_ctl_elem_info *uinfo)
0256 {
0257 static const char * const texts[3] = {
0258 "L chan only", "R chan only", "L ch/2 + R ch/2"
0259 };
0260
0261 return snd_ctl_enum_info(uinfo, 1, 3, texts);
0262 }
0263
0264 static int snd_als4k_mono_capture_route_get(struct snd_kcontrol *kcontrol,
0265 struct snd_ctl_elem_value *ucontrol)
0266 {
0267 struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
0268 unsigned long flags;
0269 unsigned char oval;
0270
0271 spin_lock_irqsave(&sb->mixer_lock, flags);
0272 oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL);
0273 spin_unlock_irqrestore(&sb->mixer_lock, flags);
0274 oval >>= 6;
0275 if (oval > 2)
0276 oval = 2;
0277
0278 ucontrol->value.enumerated.item[0] = oval;
0279 return 0;
0280 }
0281
0282 static int snd_als4k_mono_capture_route_put(struct snd_kcontrol *kcontrol,
0283 struct snd_ctl_elem_value *ucontrol)
0284 {
0285 struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
0286 unsigned long flags;
0287 int change;
0288 unsigned char nval, oval;
0289
0290 if (ucontrol->value.enumerated.item[0] > 2)
0291 return -EINVAL;
0292 spin_lock_irqsave(&sb->mixer_lock, flags);
0293 oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL);
0294
0295 nval = (oval & ~(3 << 6))
0296 | (ucontrol->value.enumerated.item[0] << 6);
0297 change = nval != oval;
0298 if (change)
0299 snd_sbmixer_write(sb, SB_ALS4000_MONO_IO_CTRL, nval);
0300 spin_unlock_irqrestore(&sb->mixer_lock, flags);
0301 return change;
0302 }
0303
0304
0305
0306
0307
0308 static int snd_sb8mixer_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0309 {
0310 static const char * const texts[3] = {
0311 "Mic", "CD", "Line"
0312 };
0313
0314 return snd_ctl_enum_info(uinfo, 1, 3, texts);
0315 }
0316
0317
0318 static int snd_sb8mixer_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0319 {
0320 struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
0321 unsigned long flags;
0322 unsigned char oval;
0323
0324 spin_lock_irqsave(&sb->mixer_lock, flags);
0325 oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE);
0326 spin_unlock_irqrestore(&sb->mixer_lock, flags);
0327 switch ((oval >> 0x01) & 0x03) {
0328 case SB_DSP_MIXS_CD:
0329 ucontrol->value.enumerated.item[0] = 1;
0330 break;
0331 case SB_DSP_MIXS_LINE:
0332 ucontrol->value.enumerated.item[0] = 2;
0333 break;
0334 default:
0335 ucontrol->value.enumerated.item[0] = 0;
0336 break;
0337 }
0338 return 0;
0339 }
0340
0341 static int snd_sb8mixer_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0342 {
0343 struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
0344 unsigned long flags;
0345 int change;
0346 unsigned char nval, oval;
0347
0348 if (ucontrol->value.enumerated.item[0] > 2)
0349 return -EINVAL;
0350 switch (ucontrol->value.enumerated.item[0]) {
0351 case 1:
0352 nval = SB_DSP_MIXS_CD;
0353 break;
0354 case 2:
0355 nval = SB_DSP_MIXS_LINE;
0356 break;
0357 default:
0358 nval = SB_DSP_MIXS_MIC;
0359 }
0360 nval <<= 1;
0361 spin_lock_irqsave(&sb->mixer_lock, flags);
0362 oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE);
0363 nval |= oval & ~0x06;
0364 change = nval != oval;
0365 if (change)
0366 snd_sbmixer_write(sb, SB_DSP_CAPTURE_SOURCE, nval);
0367 spin_unlock_irqrestore(&sb->mixer_lock, flags);
0368 return change;
0369 }
0370
0371
0372
0373
0374
0375 static int snd_sb16mixer_info_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0376 {
0377 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0378 uinfo->count = 4;
0379 uinfo->value.integer.min = 0;
0380 uinfo->value.integer.max = 1;
0381 return 0;
0382 }
0383
0384 static int snd_sb16mixer_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0385 {
0386 struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
0387 unsigned long flags;
0388 int reg1 = kcontrol->private_value & 0xff;
0389 int reg2 = (kcontrol->private_value >> 8) & 0xff;
0390 int left_shift = (kcontrol->private_value >> 16) & 0x0f;
0391 int right_shift = (kcontrol->private_value >> 24) & 0x0f;
0392 unsigned char val1, val2;
0393
0394 spin_lock_irqsave(&sb->mixer_lock, flags);
0395 val1 = snd_sbmixer_read(sb, reg1);
0396 val2 = snd_sbmixer_read(sb, reg2);
0397 spin_unlock_irqrestore(&sb->mixer_lock, flags);
0398 ucontrol->value.integer.value[0] = (val1 >> left_shift) & 0x01;
0399 ucontrol->value.integer.value[1] = (val2 >> left_shift) & 0x01;
0400 ucontrol->value.integer.value[2] = (val1 >> right_shift) & 0x01;
0401 ucontrol->value.integer.value[3] = (val2 >> right_shift) & 0x01;
0402 return 0;
0403 }
0404
0405 static int snd_sb16mixer_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0406 {
0407 struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
0408 unsigned long flags;
0409 int reg1 = kcontrol->private_value & 0xff;
0410 int reg2 = (kcontrol->private_value >> 8) & 0xff;
0411 int left_shift = (kcontrol->private_value >> 16) & 0x0f;
0412 int right_shift = (kcontrol->private_value >> 24) & 0x0f;
0413 int change;
0414 unsigned char val1, val2, oval1, oval2;
0415
0416 spin_lock_irqsave(&sb->mixer_lock, flags);
0417 oval1 = snd_sbmixer_read(sb, reg1);
0418 oval2 = snd_sbmixer_read(sb, reg2);
0419 val1 = oval1 & ~((1 << left_shift) | (1 << right_shift));
0420 val2 = oval2 & ~((1 << left_shift) | (1 << right_shift));
0421 val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift;
0422 val2 |= (ucontrol->value.integer.value[1] & 1) << left_shift;
0423 val1 |= (ucontrol->value.integer.value[2] & 1) << right_shift;
0424 val2 |= (ucontrol->value.integer.value[3] & 1) << right_shift;
0425 change = val1 != oval1 || val2 != oval2;
0426 if (change) {
0427 snd_sbmixer_write(sb, reg1, val1);
0428 snd_sbmixer_write(sb, reg2, val2);
0429 }
0430 spin_unlock_irqrestore(&sb->mixer_lock, flags);
0431 return change;
0432 }
0433
0434
0435
0436
0437
0438
0439 int snd_sbmixer_add_ctl(struct snd_sb *chip, const char *name, int index, int type, unsigned long value)
0440 {
0441 static const struct snd_kcontrol_new newctls[] = {
0442 [SB_MIX_SINGLE] = {
0443 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0444 .info = snd_sbmixer_info_single,
0445 .get = snd_sbmixer_get_single,
0446 .put = snd_sbmixer_put_single,
0447 },
0448 [SB_MIX_DOUBLE] = {
0449 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0450 .info = snd_sbmixer_info_double,
0451 .get = snd_sbmixer_get_double,
0452 .put = snd_sbmixer_put_double,
0453 },
0454 [SB_MIX_INPUT_SW] = {
0455 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0456 .info = snd_sb16mixer_info_input_sw,
0457 .get = snd_sb16mixer_get_input_sw,
0458 .put = snd_sb16mixer_put_input_sw,
0459 },
0460 [SB_MIX_CAPTURE_PRO] = {
0461 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0462 .info = snd_sb8mixer_info_mux,
0463 .get = snd_sb8mixer_get_mux,
0464 .put = snd_sb8mixer_put_mux,
0465 },
0466 [SB_MIX_CAPTURE_DT019X] = {
0467 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0468 .info = snd_dt019x_input_sw_info,
0469 .get = snd_dt019x_input_sw_get,
0470 .put = snd_dt019x_input_sw_put,
0471 },
0472 [SB_MIX_MONO_CAPTURE_ALS4K] = {
0473 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0474 .info = snd_als4k_mono_capture_route_info,
0475 .get = snd_als4k_mono_capture_route_get,
0476 .put = snd_als4k_mono_capture_route_put,
0477 },
0478 };
0479 struct snd_kcontrol *ctl;
0480 int err;
0481
0482 ctl = snd_ctl_new1(&newctls[type], chip);
0483 if (! ctl)
0484 return -ENOMEM;
0485 strscpy(ctl->id.name, name, sizeof(ctl->id.name));
0486 ctl->id.index = index;
0487 ctl->private_value = value;
0488 err = snd_ctl_add(chip->card, ctl);
0489 if (err < 0)
0490 return err;
0491 return 0;
0492 }
0493
0494
0495
0496
0497
0498 static const struct sbmix_elem snd_sb20_controls[] = {
0499 SB_SINGLE("Master Playback Volume", SB_DSP20_MASTER_DEV, 1, 7),
0500 SB_SINGLE("PCM Playback Volume", SB_DSP20_PCM_DEV, 1, 3),
0501 SB_SINGLE("Synth Playback Volume", SB_DSP20_FM_DEV, 1, 7),
0502 SB_SINGLE("CD Playback Volume", SB_DSP20_CD_DEV, 1, 7)
0503 };
0504
0505 static const unsigned char snd_sb20_init_values[][2] = {
0506 { SB_DSP20_MASTER_DEV, 0 },
0507 { SB_DSP20_FM_DEV, 0 },
0508 };
0509
0510
0511
0512
0513 static const struct sbmix_elem snd_sbpro_controls[] = {
0514 SB_DOUBLE("Master Playback Volume",
0515 SB_DSP_MASTER_DEV, SB_DSP_MASTER_DEV, 5, 1, 7),
0516 SB_DOUBLE("PCM Playback Volume",
0517 SB_DSP_PCM_DEV, SB_DSP_PCM_DEV, 5, 1, 7),
0518 SB_SINGLE("PCM Playback Filter", SB_DSP_PLAYBACK_FILT, 5, 1),
0519 SB_DOUBLE("Synth Playback Volume",
0520 SB_DSP_FM_DEV, SB_DSP_FM_DEV, 5, 1, 7),
0521 SB_DOUBLE("CD Playback Volume", SB_DSP_CD_DEV, SB_DSP_CD_DEV, 5, 1, 7),
0522 SB_DOUBLE("Line Playback Volume",
0523 SB_DSP_LINE_DEV, SB_DSP_LINE_DEV, 5, 1, 7),
0524 SB_SINGLE("Mic Playback Volume", SB_DSP_MIC_DEV, 1, 3),
0525 {
0526 .name = "Capture Source",
0527 .type = SB_MIX_CAPTURE_PRO
0528 },
0529 SB_SINGLE("Capture Filter", SB_DSP_CAPTURE_FILT, 5, 1),
0530 SB_SINGLE("Capture Low-Pass Filter", SB_DSP_CAPTURE_FILT, 3, 1)
0531 };
0532
0533 static const unsigned char snd_sbpro_init_values[][2] = {
0534 { SB_DSP_MASTER_DEV, 0 },
0535 { SB_DSP_PCM_DEV, 0 },
0536 { SB_DSP_FM_DEV, 0 },
0537 };
0538
0539
0540
0541
0542 static const struct sbmix_elem snd_sb16_controls[] = {
0543 SB_DOUBLE("Master Playback Volume",
0544 SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31),
0545 SB_DOUBLE("PCM Playback Volume",
0546 SB_DSP4_PCM_DEV, (SB_DSP4_PCM_DEV + 1), 3, 3, 31),
0547 SB16_INPUT_SW("Synth Capture Route",
0548 SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 6, 5),
0549 SB_DOUBLE("Synth Playback Volume",
0550 SB_DSP4_SYNTH_DEV, (SB_DSP4_SYNTH_DEV + 1), 3, 3, 31),
0551 SB16_INPUT_SW("CD Capture Route",
0552 SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 2, 1),
0553 SB_DOUBLE("CD Playback Switch",
0554 SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1),
0555 SB_DOUBLE("CD Playback Volume",
0556 SB_DSP4_CD_DEV, (SB_DSP4_CD_DEV + 1), 3, 3, 31),
0557 SB16_INPUT_SW("Mic Capture Route",
0558 SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 0, 0),
0559 SB_SINGLE("Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1),
0560 SB_SINGLE("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31),
0561 SB_SINGLE("Beep Volume", SB_DSP4_SPEAKER_DEV, 6, 3),
0562 SB_DOUBLE("Capture Volume",
0563 SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3),
0564 SB_DOUBLE("Playback Volume",
0565 SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3),
0566 SB16_INPUT_SW("Line Capture Route",
0567 SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 4, 3),
0568 SB_DOUBLE("Line Playback Switch",
0569 SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1),
0570 SB_DOUBLE("Line Playback Volume",
0571 SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31),
0572 SB_SINGLE("Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1),
0573 SB_SINGLE("3D Enhancement Switch", SB_DSP4_3DSE, 0, 1),
0574 SB_DOUBLE("Tone Control - Bass",
0575 SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15),
0576 SB_DOUBLE("Tone Control - Treble",
0577 SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15)
0578 };
0579
0580 static const unsigned char snd_sb16_init_values[][2] = {
0581 { SB_DSP4_MASTER_DEV + 0, 0 },
0582 { SB_DSP4_MASTER_DEV + 1, 0 },
0583 { SB_DSP4_PCM_DEV + 0, 0 },
0584 { SB_DSP4_PCM_DEV + 1, 0 },
0585 { SB_DSP4_SYNTH_DEV + 0, 0 },
0586 { SB_DSP4_SYNTH_DEV + 1, 0 },
0587 { SB_DSP4_INPUT_LEFT, 0 },
0588 { SB_DSP4_INPUT_RIGHT, 0 },
0589 { SB_DSP4_OUTPUT_SW, 0 },
0590 { SB_DSP4_SPEAKER_DEV, 0 },
0591 };
0592
0593
0594
0595
0596 static const struct sbmix_elem snd_dt019x_controls[] = {
0597
0598
0599 SB_DOUBLE("Master Playback Volume",
0600 SB_DT019X_MASTER_DEV, SB_DT019X_MASTER_DEV, 4, 0, 15),
0601 SB_DOUBLE("PCM Playback Switch",
0602 SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 2, 1, 1),
0603 SB_DOUBLE("PCM Playback Volume",
0604 SB_DT019X_PCM_DEV, SB_DT019X_PCM_DEV, 4, 0, 15),
0605 SB_DOUBLE("Synth Playback Switch",
0606 SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 4, 3, 1),
0607 SB_DOUBLE("Synth Playback Volume",
0608 SB_DT019X_SYNTH_DEV, SB_DT019X_SYNTH_DEV, 4, 0, 15),
0609 SB_DOUBLE("CD Playback Switch",
0610 SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1),
0611 SB_DOUBLE("CD Playback Volume",
0612 SB_DT019X_CD_DEV, SB_DT019X_CD_DEV, 4, 0, 15),
0613 SB_SINGLE("Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1),
0614 SB_SINGLE("Mic Playback Volume", SB_DT019X_MIC_DEV, 4, 7),
0615 SB_SINGLE("Beep Volume", SB_DT019X_SPKR_DEV, 0, 7),
0616 SB_DOUBLE("Line Playback Switch",
0617 SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1),
0618 SB_DOUBLE("Line Playback Volume",
0619 SB_DT019X_LINE_DEV, SB_DT019X_LINE_DEV, 4, 0, 15),
0620 {
0621 .name = "Capture Source",
0622 .type = SB_MIX_CAPTURE_DT019X
0623 }
0624 };
0625
0626 static const unsigned char snd_dt019x_init_values[][2] = {
0627 { SB_DT019X_MASTER_DEV, 0 },
0628 { SB_DT019X_PCM_DEV, 0 },
0629 { SB_DT019X_SYNTH_DEV, 0 },
0630 { SB_DT019X_CD_DEV, 0 },
0631 { SB_DT019X_MIC_DEV, 0 },
0632 { SB_DT019X_LINE_DEV, 0 },
0633 { SB_DSP4_OUTPUT_SW, 0 },
0634 { SB_DT019X_OUTPUT_SW2, 0 },
0635 { SB_DT019X_CAPTURE_SW, 0x06 },
0636 };
0637
0638
0639
0640
0641 static const struct sbmix_elem snd_als4000_controls[] = {
0642 SB_DOUBLE("PCM Playback Switch",
0643 SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 2, 1, 1),
0644 SB_DOUBLE("Synth Playback Switch",
0645 SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 4, 3, 1),
0646 SB_SINGLE("Mic Boost (+20dB)", SB_ALS4000_MIC_IN_GAIN, 0, 0x03),
0647 SB_SINGLE("Master Mono Playback Switch", SB_ALS4000_MONO_IO_CTRL, 5, 1),
0648 {
0649 .name = "Master Mono Capture Route",
0650 .type = SB_MIX_MONO_CAPTURE_ALS4K
0651 },
0652 SB_SINGLE("Mono Playback Switch", SB_DT019X_OUTPUT_SW2, 0, 1),
0653 SB_SINGLE("Analog Loopback Switch", SB_ALS4000_MIC_IN_GAIN, 7, 0x01),
0654 SB_SINGLE("3D Control - Switch", SB_ALS4000_3D_SND_FX, 6, 0x01),
0655 SB_SINGLE("Digital Loopback Switch",
0656 SB_ALS4000_CR3_CONFIGURATION, 7, 0x01),
0657
0658
0659 SB_SINGLE("3D Control - Level", SB_ALS4000_3D_SND_FX, 0, 0x07),
0660
0661 SB_SINGLE("3D Control - Freq", SB_ALS4000_3D_SND_FX, 4, 0x03),
0662
0663
0664
0665 SB_SINGLE("3D Control - Wide", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f),
0666 SB_SINGLE("3D PowerOff Switch", SB_ALS4000_3D_TIME_DELAY, 4, 0x01),
0667 SB_SINGLE("Master Playback 8kHz / 20kHz LPF Switch",
0668 SB_ALS4000_FMDAC, 5, 0x01),
0669 #ifdef NOT_AVAILABLE
0670 SB_SINGLE("FMDAC Switch (Option ?)", SB_ALS4000_FMDAC, 0, 0x01),
0671 SB_SINGLE("QSound Mode", SB_ALS4000_QSOUND, 1, 0x1f),
0672 #endif
0673 };
0674
0675 static const unsigned char snd_als4000_init_values[][2] = {
0676 { SB_DSP4_MASTER_DEV + 0, 0 },
0677 { SB_DSP4_MASTER_DEV + 1, 0 },
0678 { SB_DSP4_PCM_DEV + 0, 0 },
0679 { SB_DSP4_PCM_DEV + 1, 0 },
0680 { SB_DSP4_SYNTH_DEV + 0, 0 },
0681 { SB_DSP4_SYNTH_DEV + 1, 0 },
0682 { SB_DSP4_SPEAKER_DEV, 0 },
0683 { SB_DSP4_OUTPUT_SW, 0 },
0684 { SB_DSP4_INPUT_LEFT, 0 },
0685 { SB_DSP4_INPUT_RIGHT, 0 },
0686 { SB_DT019X_OUTPUT_SW2, 0 },
0687 { SB_ALS4000_MIC_IN_GAIN, 0 },
0688 };
0689
0690
0691
0692 static int snd_sbmixer_init(struct snd_sb *chip,
0693 const struct sbmix_elem *controls,
0694 int controls_count,
0695 const unsigned char map[][2],
0696 int map_count,
0697 char *name)
0698 {
0699 unsigned long flags;
0700 struct snd_card *card = chip->card;
0701 int idx, err;
0702
0703
0704 spin_lock_irqsave(&chip->mixer_lock, flags);
0705 snd_sbmixer_write(chip, 0x00, 0x00);
0706 spin_unlock_irqrestore(&chip->mixer_lock, flags);
0707
0708
0709 for (idx = 0; idx < map_count; idx++) {
0710 spin_lock_irqsave(&chip->mixer_lock, flags);
0711 snd_sbmixer_write(chip, map[idx][0], map[idx][1]);
0712 spin_unlock_irqrestore(&chip->mixer_lock, flags);
0713 }
0714
0715 for (idx = 0; idx < controls_count; idx++) {
0716 err = snd_sbmixer_add_ctl_elem(chip, &controls[idx]);
0717 if (err < 0)
0718 return err;
0719 }
0720 snd_component_add(card, name);
0721 strcpy(card->mixername, name);
0722 return 0;
0723 }
0724
0725 int snd_sbmixer_new(struct snd_sb *chip)
0726 {
0727 struct snd_card *card;
0728 int err;
0729
0730 if (snd_BUG_ON(!chip || !chip->card))
0731 return -EINVAL;
0732
0733 card = chip->card;
0734
0735 switch (chip->hardware) {
0736 case SB_HW_10:
0737 return 0;
0738 case SB_HW_20:
0739 case SB_HW_201:
0740 err = snd_sbmixer_init(chip,
0741 snd_sb20_controls,
0742 ARRAY_SIZE(snd_sb20_controls),
0743 snd_sb20_init_values,
0744 ARRAY_SIZE(snd_sb20_init_values),
0745 "CTL1335");
0746 if (err < 0)
0747 return err;
0748 break;
0749 case SB_HW_PRO:
0750 case SB_HW_JAZZ16:
0751 err = snd_sbmixer_init(chip,
0752 snd_sbpro_controls,
0753 ARRAY_SIZE(snd_sbpro_controls),
0754 snd_sbpro_init_values,
0755 ARRAY_SIZE(snd_sbpro_init_values),
0756 "CTL1345");
0757 if (err < 0)
0758 return err;
0759 break;
0760 case SB_HW_16:
0761 case SB_HW_ALS100:
0762 case SB_HW_CS5530:
0763 err = snd_sbmixer_init(chip,
0764 snd_sb16_controls,
0765 ARRAY_SIZE(snd_sb16_controls),
0766 snd_sb16_init_values,
0767 ARRAY_SIZE(snd_sb16_init_values),
0768 "CTL1745");
0769 if (err < 0)
0770 return err;
0771 break;
0772 case SB_HW_ALS4000:
0773
0774 err = snd_sbmixer_init(chip,
0775 snd_sb16_controls,
0776 16,
0777 snd_sb16_init_values,
0778 ARRAY_SIZE(snd_sb16_init_values),
0779 "ALS4000");
0780 if (err < 0)
0781 return err;
0782 err = snd_sbmixer_init(chip,
0783 snd_als4000_controls,
0784 ARRAY_SIZE(snd_als4000_controls),
0785 snd_als4000_init_values,
0786 ARRAY_SIZE(snd_als4000_init_values),
0787 "ALS4000");
0788 if (err < 0)
0789 return err;
0790 break;
0791 case SB_HW_DT019X:
0792 err = snd_sbmixer_init(chip,
0793 snd_dt019x_controls,
0794 ARRAY_SIZE(snd_dt019x_controls),
0795 snd_dt019x_init_values,
0796 ARRAY_SIZE(snd_dt019x_init_values),
0797 "DT019X");
0798 if (err < 0)
0799 return err;
0800 break;
0801 default:
0802 strcpy(card->mixername, "???");
0803 }
0804 return 0;
0805 }
0806
0807 #ifdef CONFIG_PM
0808 static const unsigned char sb20_saved_regs[] = {
0809 SB_DSP20_MASTER_DEV,
0810 SB_DSP20_PCM_DEV,
0811 SB_DSP20_FM_DEV,
0812 SB_DSP20_CD_DEV,
0813 };
0814
0815 static const unsigned char sbpro_saved_regs[] = {
0816 SB_DSP_MASTER_DEV,
0817 SB_DSP_PCM_DEV,
0818 SB_DSP_PLAYBACK_FILT,
0819 SB_DSP_FM_DEV,
0820 SB_DSP_CD_DEV,
0821 SB_DSP_LINE_DEV,
0822 SB_DSP_MIC_DEV,
0823 SB_DSP_CAPTURE_SOURCE,
0824 SB_DSP_CAPTURE_FILT,
0825 };
0826
0827 static const unsigned char sb16_saved_regs[] = {
0828 SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1,
0829 SB_DSP4_3DSE,
0830 SB_DSP4_BASS_DEV, SB_DSP4_BASS_DEV + 1,
0831 SB_DSP4_TREBLE_DEV, SB_DSP4_TREBLE_DEV + 1,
0832 SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1,
0833 SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT,
0834 SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1,
0835 SB_DSP4_OUTPUT_SW,
0836 SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1,
0837 SB_DSP4_LINE_DEV, SB_DSP4_LINE_DEV + 1,
0838 SB_DSP4_MIC_DEV,
0839 SB_DSP4_SPEAKER_DEV,
0840 SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1,
0841 SB_DSP4_OGAIN_DEV, SB_DSP4_OGAIN_DEV + 1,
0842 SB_DSP4_MIC_AGC
0843 };
0844
0845 static const unsigned char dt019x_saved_regs[] = {
0846 SB_DT019X_MASTER_DEV,
0847 SB_DT019X_PCM_DEV,
0848 SB_DT019X_SYNTH_DEV,
0849 SB_DT019X_CD_DEV,
0850 SB_DT019X_MIC_DEV,
0851 SB_DT019X_SPKR_DEV,
0852 SB_DT019X_LINE_DEV,
0853 SB_DSP4_OUTPUT_SW,
0854 SB_DT019X_OUTPUT_SW2,
0855 SB_DT019X_CAPTURE_SW,
0856 };
0857
0858 static const unsigned char als4000_saved_regs[] = {
0859
0860
0861 SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1,
0862 SB_DSP4_OUTPUT_SW,
0863 SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1,
0864 SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT,
0865 SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1,
0866 SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1,
0867 SB_DSP4_MIC_DEV,
0868 SB_DSP4_SPEAKER_DEV,
0869 SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1,
0870 SB_DSP4_OGAIN_DEV, SB_DSP4_OGAIN_DEV + 1,
0871 SB_DT019X_OUTPUT_SW2,
0872 SB_ALS4000_MONO_IO_CTRL,
0873 SB_ALS4000_MIC_IN_GAIN,
0874 SB_ALS4000_FMDAC,
0875 SB_ALS4000_3D_SND_FX,
0876 SB_ALS4000_3D_TIME_DELAY,
0877 SB_ALS4000_CR3_CONFIGURATION,
0878 };
0879
0880 static void save_mixer(struct snd_sb *chip, const unsigned char *regs, int num_regs)
0881 {
0882 unsigned char *val = chip->saved_regs;
0883 if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs)))
0884 return;
0885 for (; num_regs; num_regs--)
0886 *val++ = snd_sbmixer_read(chip, *regs++);
0887 }
0888
0889 static void restore_mixer(struct snd_sb *chip, const unsigned char *regs, int num_regs)
0890 {
0891 unsigned char *val = chip->saved_regs;
0892 if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs)))
0893 return;
0894 for (; num_regs; num_regs--)
0895 snd_sbmixer_write(chip, *regs++, *val++);
0896 }
0897
0898 void snd_sbmixer_suspend(struct snd_sb *chip)
0899 {
0900 switch (chip->hardware) {
0901 case SB_HW_20:
0902 case SB_HW_201:
0903 save_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs));
0904 break;
0905 case SB_HW_PRO:
0906 case SB_HW_JAZZ16:
0907 save_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs));
0908 break;
0909 case SB_HW_16:
0910 case SB_HW_ALS100:
0911 case SB_HW_CS5530:
0912 save_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs));
0913 break;
0914 case SB_HW_ALS4000:
0915 save_mixer(chip, als4000_saved_regs, ARRAY_SIZE(als4000_saved_regs));
0916 break;
0917 case SB_HW_DT019X:
0918 save_mixer(chip, dt019x_saved_regs, ARRAY_SIZE(dt019x_saved_regs));
0919 break;
0920 default:
0921 break;
0922 }
0923 }
0924
0925 void snd_sbmixer_resume(struct snd_sb *chip)
0926 {
0927 switch (chip->hardware) {
0928 case SB_HW_20:
0929 case SB_HW_201:
0930 restore_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs));
0931 break;
0932 case SB_HW_PRO:
0933 case SB_HW_JAZZ16:
0934 restore_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs));
0935 break;
0936 case SB_HW_16:
0937 case SB_HW_ALS100:
0938 case SB_HW_CS5530:
0939 restore_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs));
0940 break;
0941 case SB_HW_ALS4000:
0942 restore_mixer(chip, als4000_saved_regs, ARRAY_SIZE(als4000_saved_regs));
0943 break;
0944 case SB_HW_DT019X:
0945 restore_mixer(chip, dt019x_saved_regs, ARRAY_SIZE(dt019x_saved_regs));
0946 break;
0947 default:
0948 break;
0949 }
0950 }
0951 #endif