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