ca0106_mixer.c (27143B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> 4 * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit 5 * Version: 0.0.18 6 * 7 * FEATURES currently supported: 8 * See ca0106_main.c for features. 9 * 10 * Changelog: 11 * Support interrupts per period. 12 * Removed noise from Center/LFE channel when in Analog mode. 13 * Rename and remove mixer controls. 14 * 0.0.6 15 * Use separate card based DMA buffer for periods table list. 16 * 0.0.7 17 * Change remove and rename ctrls into lists. 18 * 0.0.8 19 * Try to fix capture sources. 20 * 0.0.9 21 * Fix AC3 output. 22 * Enable S32_LE format support. 23 * 0.0.10 24 * Enable playback 48000 and 96000 rates. (Rates other that these do not work, even with "plug:front".) 25 * 0.0.11 26 * Add Model name recognition. 27 * 0.0.12 28 * Correct interrupt timing. interrupt at end of period, instead of in the middle of a playback period. 29 * Remove redundent "voice" handling. 30 * 0.0.13 31 * Single trigger call for multi channels. 32 * 0.0.14 33 * Set limits based on what the sound card hardware can do. 34 * playback periods_min=2, periods_max=8 35 * capture hw constraints require period_size = n * 64 bytes. 36 * playback hw constraints require period_size = n * 64 bytes. 37 * 0.0.15 38 * Separated ca0106.c into separate functional .c files. 39 * 0.0.16 40 * Modified Copyright message. 41 * 0.0.17 42 * Implement Mic and Line in Capture. 43 * 0.0.18 44 * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) 45 * 46 * This code was initially based on code from ALSA's emu10k1x.c which is: 47 * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> 48 */ 49#include <linux/delay.h> 50#include <linux/init.h> 51#include <linux/interrupt.h> 52#include <linux/moduleparam.h> 53#include <sound/core.h> 54#include <sound/initval.h> 55#include <sound/pcm.h> 56#include <sound/ac97_codec.h> 57#include <sound/info.h> 58#include <sound/tlv.h> 59#include <linux/io.h> 60 61#include "ca0106.h" 62 63static void ca0106_spdif_enable(struct snd_ca0106 *emu) 64{ 65 unsigned int val; 66 67 if (emu->spdif_enable) { 68 /* Digital */ 69 snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); 70 snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000); 71 val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000; 72 snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val); 73 val = inl(emu->port + CA0106_GPIO) & ~0x101; 74 outl(val, emu->port + CA0106_GPIO); 75 76 } else { 77 /* Analog */ 78 snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); 79 snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000); 80 val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000; 81 snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val); 82 val = inl(emu->port + CA0106_GPIO) | 0x101; 83 outl(val, emu->port + CA0106_GPIO); 84 } 85} 86 87static void ca0106_set_capture_source(struct snd_ca0106 *emu) 88{ 89 unsigned int val = emu->capture_source; 90 unsigned int source, mask; 91 source = (val << 28) | (val << 24) | (val << 20) | (val << 16); 92 mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff; 93 snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask); 94} 95 96static void ca0106_set_i2c_capture_source(struct snd_ca0106 *emu, 97 unsigned int val, int force) 98{ 99 unsigned int ngain, ogain; 100 u32 source; 101 102 snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ 103 ngain = emu->i2c_capture_volume[val][0]; /* Left */ 104 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ 105 if (force || ngain != ogain) 106 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ngain & 0xff); 107 ngain = emu->i2c_capture_volume[val][1]; /* Right */ 108 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */ 109 if (force || ngain != ogain) 110 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ngain & 0xff); 111 source = 1 << val; 112 snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */ 113 emu->i2c_capture_source = val; 114} 115 116static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu) 117{ 118 u32 tmp; 119 120 if (emu->capture_mic_line_in) { 121 /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */ 122 tmp = inl(emu->port + CA0106_GPIO) & ~0x400; 123 tmp = tmp | 0x400; 124 outl(tmp, emu->port + CA0106_GPIO); 125 /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); */ 126 } else { 127 /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */ 128 tmp = inl(emu->port + CA0106_GPIO) & ~0x400; 129 outl(tmp, emu->port + CA0106_GPIO); 130 /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); */ 131 } 132} 133 134static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx) 135{ 136 snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]); 137} 138 139/* 140 */ 141static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1); 142static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1); 143 144#define snd_ca0106_shared_spdif_info snd_ctl_boolean_mono_info 145 146static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol, 147 struct snd_ctl_elem_value *ucontrol) 148{ 149 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 150 151 ucontrol->value.integer.value[0] = emu->spdif_enable; 152 return 0; 153} 154 155static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol, 156 struct snd_ctl_elem_value *ucontrol) 157{ 158 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 159 unsigned int val; 160 int change = 0; 161 162 val = !!ucontrol->value.integer.value[0]; 163 change = (emu->spdif_enable != val); 164 if (change) { 165 emu->spdif_enable = val; 166 ca0106_spdif_enable(emu); 167 } 168 return change; 169} 170 171static int snd_ca0106_capture_source_info(struct snd_kcontrol *kcontrol, 172 struct snd_ctl_elem_info *uinfo) 173{ 174 static const char * const texts[6] = { 175 "IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out" 176 }; 177 178 return snd_ctl_enum_info(uinfo, 1, 6, texts); 179} 180 181static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol, 182 struct snd_ctl_elem_value *ucontrol) 183{ 184 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 185 186 ucontrol->value.enumerated.item[0] = emu->capture_source; 187 return 0; 188} 189 190static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol, 191 struct snd_ctl_elem_value *ucontrol) 192{ 193 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 194 unsigned int val; 195 int change = 0; 196 197 val = ucontrol->value.enumerated.item[0] ; 198 if (val >= 6) 199 return -EINVAL; 200 change = (emu->capture_source != val); 201 if (change) { 202 emu->capture_source = val; 203 ca0106_set_capture_source(emu); 204 } 205 return change; 206} 207 208static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol, 209 struct snd_ctl_elem_info *uinfo) 210{ 211 static const char * const texts[4] = { 212 "Phone", "Mic", "Line in", "Aux" 213 }; 214 215 return snd_ctl_enum_info(uinfo, 1, 4, texts); 216} 217 218static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol, 219 struct snd_ctl_elem_value *ucontrol) 220{ 221 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 222 223 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source; 224 return 0; 225} 226 227static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol, 228 struct snd_ctl_elem_value *ucontrol) 229{ 230 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 231 unsigned int source_id; 232 int change = 0; 233 /* If the capture source has changed, 234 * update the capture volume from the cached value 235 * for the particular source. 236 */ 237 source_id = ucontrol->value.enumerated.item[0] ; 238 if (source_id >= 4) 239 return -EINVAL; 240 change = (emu->i2c_capture_source != source_id); 241 if (change) { 242 ca0106_set_i2c_capture_source(emu, source_id, 0); 243 } 244 return change; 245} 246 247static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol, 248 struct snd_ctl_elem_info *uinfo) 249{ 250 static const char * const texts[2] = { "Side out", "Line in" }; 251 252 return snd_ctl_enum_info(uinfo, 1, 2, texts); 253} 254 255static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol, 256 struct snd_ctl_elem_info *uinfo) 257{ 258 static const char * const texts[2] = { "Line in", "Mic in" }; 259 260 return snd_ctl_enum_info(uinfo, 1, 2, texts); 261} 262 263static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol, 264 struct snd_ctl_elem_value *ucontrol) 265{ 266 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 267 268 ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in; 269 return 0; 270} 271 272static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, 273 struct snd_ctl_elem_value *ucontrol) 274{ 275 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 276 unsigned int val; 277 int change = 0; 278 279 val = ucontrol->value.enumerated.item[0] ; 280 if (val > 1) 281 return -EINVAL; 282 change = (emu->capture_mic_line_in != val); 283 if (change) { 284 emu->capture_mic_line_in = val; 285 ca0106_set_capture_mic_line_in(emu); 286 } 287 return change; 288} 289 290static const struct snd_kcontrol_new snd_ca0106_capture_mic_line_in = 291{ 292 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 293 .name = "Shared Mic/Line in Capture Switch", 294 .info = snd_ca0106_capture_mic_line_in_info, 295 .get = snd_ca0106_capture_mic_line_in_get, 296 .put = snd_ca0106_capture_mic_line_in_put 297}; 298 299static const struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out = 300{ 301 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 302 .name = "Shared Line in/Side out Capture Switch", 303 .info = snd_ca0106_capture_line_in_side_out_info, 304 .get = snd_ca0106_capture_mic_line_in_get, 305 .put = snd_ca0106_capture_mic_line_in_put 306}; 307 308 309static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol, 310 struct snd_ctl_elem_info *uinfo) 311{ 312 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 313 uinfo->count = 1; 314 return 0; 315} 316 317static void decode_spdif_bits(unsigned char *status, unsigned int bits) 318{ 319 status[0] = (bits >> 0) & 0xff; 320 status[1] = (bits >> 8) & 0xff; 321 status[2] = (bits >> 16) & 0xff; 322 status[3] = (bits >> 24) & 0xff; 323} 324 325static int snd_ca0106_spdif_get_default(struct snd_kcontrol *kcontrol, 326 struct snd_ctl_elem_value *ucontrol) 327{ 328 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 329 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 330 331 decode_spdif_bits(ucontrol->value.iec958.status, 332 emu->spdif_bits[idx]); 333 return 0; 334} 335 336static int snd_ca0106_spdif_get_stream(struct snd_kcontrol *kcontrol, 337 struct snd_ctl_elem_value *ucontrol) 338{ 339 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 340 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 341 342 decode_spdif_bits(ucontrol->value.iec958.status, 343 emu->spdif_str_bits[idx]); 344 return 0; 345} 346 347static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol, 348 struct snd_ctl_elem_value *ucontrol) 349{ 350 ucontrol->value.iec958.status[0] = 0xff; 351 ucontrol->value.iec958.status[1] = 0xff; 352 ucontrol->value.iec958.status[2] = 0xff; 353 ucontrol->value.iec958.status[3] = 0xff; 354 return 0; 355} 356 357static unsigned int encode_spdif_bits(unsigned char *status) 358{ 359 return ((unsigned int)status[0] << 0) | 360 ((unsigned int)status[1] << 8) | 361 ((unsigned int)status[2] << 16) | 362 ((unsigned int)status[3] << 24); 363} 364 365static int snd_ca0106_spdif_put_default(struct snd_kcontrol *kcontrol, 366 struct snd_ctl_elem_value *ucontrol) 367{ 368 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 369 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 370 unsigned int val; 371 372 val = encode_spdif_bits(ucontrol->value.iec958.status); 373 if (val != emu->spdif_bits[idx]) { 374 emu->spdif_bits[idx] = val; 375 /* FIXME: this isn't safe, but needed to keep the compatibility 376 * with older alsa-lib config 377 */ 378 emu->spdif_str_bits[idx] = val; 379 ca0106_set_spdif_bits(emu, idx); 380 return 1; 381 } 382 return 0; 383} 384 385static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol, 386 struct snd_ctl_elem_value *ucontrol) 387{ 388 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 389 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 390 unsigned int val; 391 392 val = encode_spdif_bits(ucontrol->value.iec958.status); 393 if (val != emu->spdif_str_bits[idx]) { 394 emu->spdif_str_bits[idx] = val; 395 ca0106_set_spdif_bits(emu, idx); 396 return 1; 397 } 398 return 0; 399} 400 401static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol, 402 struct snd_ctl_elem_info *uinfo) 403{ 404 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 405 uinfo->count = 2; 406 uinfo->value.integer.min = 0; 407 uinfo->value.integer.max = 255; 408 return 0; 409} 410 411static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol, 412 struct snd_ctl_elem_value *ucontrol) 413{ 414 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 415 unsigned int value; 416 int channel_id, reg; 417 418 channel_id = (kcontrol->private_value >> 8) & 0xff; 419 reg = kcontrol->private_value & 0xff; 420 421 value = snd_ca0106_ptr_read(emu, reg, channel_id); 422 ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */ 423 ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */ 424 return 0; 425} 426 427static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol, 428 struct snd_ctl_elem_value *ucontrol) 429{ 430 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 431 unsigned int oval, nval; 432 int channel_id, reg; 433 434 channel_id = (kcontrol->private_value >> 8) & 0xff; 435 reg = kcontrol->private_value & 0xff; 436 437 oval = snd_ca0106_ptr_read(emu, reg, channel_id); 438 nval = ((0xff - ucontrol->value.integer.value[0]) << 24) | 439 ((0xff - ucontrol->value.integer.value[1]) << 16); 440 nval |= ((0xff - ucontrol->value.integer.value[0]) << 8) | 441 ((0xff - ucontrol->value.integer.value[1]) ); 442 if (oval == nval) 443 return 0; 444 snd_ca0106_ptr_write(emu, reg, channel_id, nval); 445 return 1; 446} 447 448static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol, 449 struct snd_ctl_elem_info *uinfo) 450{ 451 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 452 uinfo->count = 2; 453 uinfo->value.integer.min = 0; 454 uinfo->value.integer.max = 255; 455 return 0; 456} 457 458static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol, 459 struct snd_ctl_elem_value *ucontrol) 460{ 461 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 462 int source_id; 463 464 source_id = kcontrol->private_value; 465 466 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0]; 467 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1]; 468 return 0; 469} 470 471static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, 472 struct snd_ctl_elem_value *ucontrol) 473{ 474 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 475 unsigned int ogain; 476 unsigned int ngain; 477 int source_id; 478 int change = 0; 479 480 source_id = kcontrol->private_value; 481 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ 482 ngain = ucontrol->value.integer.value[0]; 483 if (ngain > 0xff) 484 return -EINVAL; 485 if (ogain != ngain) { 486 if (emu->i2c_capture_source == source_id) 487 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); 488 emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0]; 489 change = 1; 490 } 491 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ 492 ngain = ucontrol->value.integer.value[1]; 493 if (ngain > 0xff) 494 return -EINVAL; 495 if (ogain != ngain) { 496 if (emu->i2c_capture_source == source_id) 497 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); 498 emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1]; 499 change = 1; 500 } 501 502 return change; 503} 504 505#define spi_mute_info snd_ctl_boolean_mono_info 506 507static int spi_mute_get(struct snd_kcontrol *kcontrol, 508 struct snd_ctl_elem_value *ucontrol) 509{ 510 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 511 unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT; 512 unsigned int bit = kcontrol->private_value & SPI_REG_MASK; 513 514 ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit); 515 return 0; 516} 517 518static int spi_mute_put(struct snd_kcontrol *kcontrol, 519 struct snd_ctl_elem_value *ucontrol) 520{ 521 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); 522 unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT; 523 unsigned int bit = kcontrol->private_value & SPI_REG_MASK; 524 int ret; 525 526 ret = emu->spi_dac_reg[reg] & bit; 527 if (ucontrol->value.integer.value[0]) { 528 if (!ret) /* bit already cleared, do nothing */ 529 return 0; 530 emu->spi_dac_reg[reg] &= ~bit; 531 } else { 532 if (ret) /* bit already set, do nothing */ 533 return 0; 534 emu->spi_dac_reg[reg] |= bit; 535 } 536 537 ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]); 538 return ret ? -EINVAL : 1; 539} 540 541#define CA_VOLUME(xname,chid,reg) \ 542{ \ 543 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 544 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ 545 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ 546 .info = snd_ca0106_volume_info, \ 547 .get = snd_ca0106_volume_get, \ 548 .put = snd_ca0106_volume_put, \ 549 .tlv = { .p = snd_ca0106_db_scale1 }, \ 550 .private_value = ((chid) << 8) | (reg) \ 551} 552 553static const struct snd_kcontrol_new snd_ca0106_volume_ctls[] = { 554 CA_VOLUME("Analog Front Playback Volume", 555 CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2), 556 CA_VOLUME("Analog Rear Playback Volume", 557 CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2), 558 CA_VOLUME("Analog Center/LFE Playback Volume", 559 CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2), 560 CA_VOLUME("Analog Side Playback Volume", 561 CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2), 562 563 CA_VOLUME("IEC958 Front Playback Volume", 564 CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1), 565 CA_VOLUME("IEC958 Rear Playback Volume", 566 CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1), 567 CA_VOLUME("IEC958 Center/LFE Playback Volume", 568 CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1), 569 CA_VOLUME("IEC958 Unknown Playback Volume", 570 CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1), 571 572 CA_VOLUME("CAPTURE feedback Playback Volume", 573 1, CAPTURE_CONTROL), 574 575 { 576 .access = SNDRV_CTL_ELEM_ACCESS_READ, 577 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 578 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), 579 .count = 4, 580 .info = snd_ca0106_spdif_info, 581 .get = snd_ca0106_spdif_get_mask 582 }, 583 { 584 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 585 .name = "IEC958 Playback Switch", 586 .info = snd_ca0106_shared_spdif_info, 587 .get = snd_ca0106_shared_spdif_get, 588 .put = snd_ca0106_shared_spdif_put 589 }, 590 { 591 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 592 .name = "Digital Source Capture Enum", 593 .info = snd_ca0106_capture_source_info, 594 .get = snd_ca0106_capture_source_get, 595 .put = snd_ca0106_capture_source_put 596 }, 597 { 598 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 599 .name = "Analog Source Capture Enum", 600 .info = snd_ca0106_i2c_capture_source_info, 601 .get = snd_ca0106_i2c_capture_source_get, 602 .put = snd_ca0106_i2c_capture_source_put 603 }, 604 { 605 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 606 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), 607 .count = 4, 608 .info = snd_ca0106_spdif_info, 609 .get = snd_ca0106_spdif_get_default, 610 .put = snd_ca0106_spdif_put_default 611 }, 612 { 613 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 614 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), 615 .count = 4, 616 .info = snd_ca0106_spdif_info, 617 .get = snd_ca0106_spdif_get_stream, 618 .put = snd_ca0106_spdif_put_stream 619 }, 620}; 621 622#define I2C_VOLUME(xname,chid) \ 623{ \ 624 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 625 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ 626 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ 627 .info = snd_ca0106_i2c_volume_info, \ 628 .get = snd_ca0106_i2c_volume_get, \ 629 .put = snd_ca0106_i2c_volume_put, \ 630 .tlv = { .p = snd_ca0106_db_scale2 }, \ 631 .private_value = chid \ 632} 633 634static const struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] = { 635 I2C_VOLUME("Phone Capture Volume", 0), 636 I2C_VOLUME("Mic Capture Volume", 1), 637 I2C_VOLUME("Line in Capture Volume", 2), 638 I2C_VOLUME("Aux Capture Volume", 3), 639}; 640 641static const int spi_dmute_reg[] = { 642 SPI_DMUTE0_REG, 643 SPI_DMUTE1_REG, 644 SPI_DMUTE2_REG, 645 0, 646 SPI_DMUTE4_REG, 647}; 648static const int spi_dmute_bit[] = { 649 SPI_DMUTE0_BIT, 650 SPI_DMUTE1_BIT, 651 SPI_DMUTE2_BIT, 652 0, 653 SPI_DMUTE4_BIT, 654}; 655 656static struct snd_kcontrol_new 657snd_ca0106_volume_spi_dac_ctl(const struct snd_ca0106_details *details, 658 int channel_id) 659{ 660 struct snd_kcontrol_new spi_switch = {0}; 661 int reg, bit; 662 int dac_id; 663 664 spi_switch.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 665 spi_switch.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; 666 spi_switch.info = spi_mute_info; 667 spi_switch.get = spi_mute_get; 668 spi_switch.put = spi_mute_put; 669 670 switch (channel_id) { 671 case PCM_FRONT_CHANNEL: 672 spi_switch.name = "Analog Front Playback Switch"; 673 dac_id = (details->spi_dac & 0xf000) >> (4 * 3); 674 break; 675 case PCM_REAR_CHANNEL: 676 spi_switch.name = "Analog Rear Playback Switch"; 677 dac_id = (details->spi_dac & 0x0f00) >> (4 * 2); 678 break; 679 case PCM_CENTER_LFE_CHANNEL: 680 spi_switch.name = "Analog Center/LFE Playback Switch"; 681 dac_id = (details->spi_dac & 0x00f0) >> (4 * 1); 682 break; 683 case PCM_UNKNOWN_CHANNEL: 684 spi_switch.name = "Analog Side Playback Switch"; 685 dac_id = (details->spi_dac & 0x000f) >> (4 * 0); 686 break; 687 default: 688 /* Unused channel */ 689 spi_switch.name = NULL; 690 dac_id = 0; 691 } 692 reg = spi_dmute_reg[dac_id]; 693 bit = spi_dmute_bit[dac_id]; 694 695 spi_switch.private_value = (reg << SPI_REG_SHIFT) | bit; 696 697 return spi_switch; 698} 699 700static int remove_ctl(struct snd_card *card, const char *name) 701{ 702 struct snd_ctl_elem_id id; 703 memset(&id, 0, sizeof(id)); 704 strcpy(id.name, name); 705 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 706 return snd_ctl_remove_id(card, &id); 707} 708 709static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name) 710{ 711 struct snd_ctl_elem_id sid; 712 memset(&sid, 0, sizeof(sid)); 713 /* FIXME: strcpy is bad. */ 714 strcpy(sid.name, name); 715 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 716 return snd_ctl_find_id(card, &sid); 717} 718 719static int rename_ctl(struct snd_card *card, const char *src, const char *dst) 720{ 721 struct snd_kcontrol *kctl = ctl_find(card, src); 722 if (kctl) { 723 strcpy(kctl->id.name, dst); 724 return 0; 725 } 726 return -ENOENT; 727} 728 729#define ADD_CTLS(emu, ctls) \ 730 do { \ 731 int i, _err; \ 732 for (i = 0; i < ARRAY_SIZE(ctls); i++) { \ 733 _err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \ 734 if (_err < 0) \ 735 return _err; \ 736 } \ 737 } while (0) 738 739static 740DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1); 741 742static const char * const follower_vols[] = { 743 "Analog Front Playback Volume", 744 "Analog Rear Playback Volume", 745 "Analog Center/LFE Playback Volume", 746 "Analog Side Playback Volume", 747 "IEC958 Front Playback Volume", 748 "IEC958 Rear Playback Volume", 749 "IEC958 Center/LFE Playback Volume", 750 "IEC958 Unknown Playback Volume", 751 "CAPTURE feedback Playback Volume", 752 NULL 753}; 754 755static const char * const follower_sws[] = { 756 "Analog Front Playback Switch", 757 "Analog Rear Playback Switch", 758 "Analog Center/LFE Playback Switch", 759 "Analog Side Playback Switch", 760 "IEC958 Playback Switch", 761 NULL 762}; 763 764static void add_followers(struct snd_card *card, 765 struct snd_kcontrol *master, const char * const *list) 766{ 767 for (; *list; list++) { 768 struct snd_kcontrol *follower = ctl_find(card, *list); 769 if (follower) 770 snd_ctl_add_follower(master, follower); 771 } 772} 773 774int snd_ca0106_mixer(struct snd_ca0106 *emu) 775{ 776 int err; 777 struct snd_card *card = emu->card; 778 const char * const *c; 779 struct snd_kcontrol *vmaster; 780 static const char * const ca0106_remove_ctls[] = { 781 "Master Mono Playback Switch", 782 "Master Mono Playback Volume", 783 "3D Control - Switch", 784 "3D Control Sigmatel - Depth", 785 "PCM Playback Switch", 786 "PCM Playback Volume", 787 "CD Playback Switch", 788 "CD Playback Volume", 789 "Phone Playback Switch", 790 "Phone Playback Volume", 791 "Video Playback Switch", 792 "Video Playback Volume", 793 "Beep Playback Switch", 794 "Beep Playback Volume", 795 "Mono Output Select", 796 "Capture Source", 797 "Capture Switch", 798 "Capture Volume", 799 "External Amplifier", 800 "Sigmatel 4-Speaker Stereo Playback Switch", 801 "Surround Phase Inversion Playback Switch", 802 NULL 803 }; 804 static const char * const ca0106_rename_ctls[] = { 805 "Master Playback Switch", "Capture Switch", 806 "Master Playback Volume", "Capture Volume", 807 "Line Playback Switch", "AC97 Line Capture Switch", 808 "Line Playback Volume", "AC97 Line Capture Volume", 809 "Aux Playback Switch", "AC97 Aux Capture Switch", 810 "Aux Playback Volume", "AC97 Aux Capture Volume", 811 "Mic Playback Switch", "AC97 Mic Capture Switch", 812 "Mic Playback Volume", "AC97 Mic Capture Volume", 813 "Mic Select", "AC97 Mic Select", 814 "Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)", 815 NULL 816 }; 817#if 1 818 for (c = ca0106_remove_ctls; *c; c++) 819 remove_ctl(card, *c); 820 for (c = ca0106_rename_ctls; *c; c += 2) 821 rename_ctl(card, c[0], c[1]); 822#endif 823 824 ADD_CTLS(emu, snd_ca0106_volume_ctls); 825 if (emu->details->i2c_adc == 1) { 826 ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls); 827 if (emu->details->gpio_type == 1) 828 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)); 829 else /* gpio_type == 2 */ 830 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu)); 831 if (err < 0) 832 return err; 833 } 834 if (emu->details->spi_dac) { 835 int i; 836 for (i = 0;; i++) { 837 struct snd_kcontrol_new ctl; 838 ctl = snd_ca0106_volume_spi_dac_ctl(emu->details, i); 839 if (!ctl.name) 840 break; 841 err = snd_ctl_add(card, snd_ctl_new1(&ctl, emu)); 842 if (err < 0) 843 return err; 844 } 845 } 846 847 /* Create virtual master controls */ 848 vmaster = snd_ctl_make_virtual_master("Master Playback Volume", 849 snd_ca0106_master_db_scale); 850 if (!vmaster) 851 return -ENOMEM; 852 err = snd_ctl_add(card, vmaster); 853 if (err < 0) 854 return err; 855 add_followers(card, vmaster, follower_vols); 856 857 if (emu->details->spi_dac) { 858 vmaster = snd_ctl_make_virtual_master("Master Playback Switch", 859 NULL); 860 if (!vmaster) 861 return -ENOMEM; 862 err = snd_ctl_add(card, vmaster); 863 if (err < 0) 864 return err; 865 add_followers(card, vmaster, follower_sws); 866 } 867 868 strcpy(card->mixername, "CA0106"); 869 return 0; 870} 871 872#ifdef CONFIG_PM_SLEEP 873struct ca0106_vol_tbl { 874 unsigned int channel_id; 875 unsigned int reg; 876}; 877 878static const struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = { 879 { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 }, 880 { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 }, 881 { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 }, 882 { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 }, 883 { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 }, 884 { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 }, 885 { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 }, 886 { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 }, 887 { 1, CAPTURE_CONTROL }, 888}; 889 890void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip) 891{ 892 int i; 893 894 /* save volumes */ 895 for (i = 0; i < NUM_SAVED_VOLUMES; i++) 896 chip->saved_vol[i] = 897 snd_ca0106_ptr_read(chip, saved_volumes[i].reg, 898 saved_volumes[i].channel_id); 899} 900 901void snd_ca0106_mixer_resume(struct snd_ca0106 *chip) 902{ 903 int i; 904 905 for (i = 0; i < NUM_SAVED_VOLUMES; i++) 906 snd_ca0106_ptr_write(chip, saved_volumes[i].reg, 907 saved_volumes[i].channel_id, 908 chip->saved_vol[i]); 909 910 ca0106_spdif_enable(chip); 911 ca0106_set_capture_source(chip); 912 ca0106_set_i2c_capture_source(chip, chip->i2c_capture_source, 1); 913 for (i = 0; i < 4; i++) 914 ca0106_set_spdif_bits(chip, i); 915 if (chip->details->i2c_adc) 916 ca0106_set_capture_mic_line_in(chip); 917} 918#endif /* CONFIG_PM_SLEEP */