1 /* 2 * Support for Digigram Lola PCI-e boards 3 * 4 * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the Free 8 * Software Foundation; either version 2 of the License, or (at your option) 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 * more details. 15 * 16 * You should have received a copy of the GNU General Public License along with 17 * this program; if not, write to the Free Software Foundation, Inc., 59 18 * Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 */ 20 21 #include <linux/kernel.h> 22 #include <linux/init.h> 23 #include <linux/vmalloc.h> 24 #include <linux/io.h> 25 #include <sound/core.h> 26 #include <sound/control.h> 27 #include <sound/pcm.h> 28 #include <sound/tlv.h> 29 #include "lola.h" 30 31 static int __devinit lola_init_pin(struct lola *chip, struct lola_pin *pin, 32 int dir, int nid) 33 { 34 unsigned int val; 35 int err; 36 37 pin->nid = nid; 38 err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); 39 if (err < 0) { 40 printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); 41 return err; 42 } 43 val &= 0x00f00fff; /* test TYPE and bits 0..11 */ 44 if (val == 0x00400200) /* Type = 4, Digital = 1 */ 45 pin->is_analog = false; 46 else if (val == 0x0040000a && dir == CAPT) /* Dig=0, InAmp/ovrd */ 47 pin->is_analog = true; 48 else if (val == 0x0040000c && dir == PLAY) /* Dig=0, OutAmp/ovrd */ 49 pin->is_analog = true; 50 else { 51 printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n", val, nid); 52 return -EINVAL; 53 } 54 55 /* analog parameters only following, so continue in case of Digital pin 56 */ 57 if (!pin->is_analog) 58 return 0; 59 60 if (dir == PLAY) 61 err = lola_read_param(chip, nid, LOLA_PAR_AMP_OUT_CAP, &val); 62 else 63 err = lola_read_param(chip, nid, LOLA_PAR_AMP_IN_CAP, &val); 64 if (err < 0) { 65 printk(KERN_ERR SFX "Can't read AMP-caps for 0x%x\n", nid); 66 return err; 67 } 68 69 pin->amp_mute = LOLA_AMP_MUTE_CAPABLE(val); 70 pin->amp_step_size = LOLA_AMP_STEP_SIZE(val); 71 pin->amp_num_steps = LOLA_AMP_NUM_STEPS(val); 72 if (pin->amp_num_steps) { 73 /* zero as mute state */ 74 pin->amp_num_steps++; 75 pin->amp_step_size++; 76 } 77 pin->amp_offset = LOLA_AMP_OFFSET(val); 78 79 err = lola_codec_read(chip, nid, LOLA_VERB_GET_MAX_LEVEL, 0, 0, &val, 80 NULL); 81 if (err < 0) { 82 printk(KERN_ERR SFX "Can't get MAX_LEVEL 0x%x\n", nid); 83 return err; 84 } 85 pin->max_level = val & 0x3ff; /* 10 bits */ 86 87 pin->config_default_reg = 0; 88 pin->fixed_gain_list_len = 0; 89 pin->cur_gain_step = 0; 90 91 return 0; 92 } 93 94 int __devinit lola_init_pins(struct lola *chip, int dir, int *nidp) 95 { 96 int i, err, nid; 97 nid = *nidp; 98 for (i = 0; i < chip->pin[dir].num_pins; i++, nid++) { 99 err = lola_init_pin(chip, &chip->pin[dir].pins[i], dir, nid); 100 if (err < 0) 101 return err; 102 } 103 *nidp = nid; 104 return 0; 105 } 106 107 void lola_free_mixer(struct lola *chip) 108 { 109 if (chip->mixer.array_saved) 110 vfree(chip->mixer.array_saved); 111 } 112 113 int __devinit lola_init_mixer_widget(struct lola *chip, int nid) 114 { 115 unsigned int val; 116 int err; 117 118 err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); 119 if (err < 0) { 120 printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); 121 return err; 122 } 123 124 if ((val & 0xfff00000) != 0x02f00000) { /* test SubType and Type */ 125 snd_printdd("No valid mixer widget\n"); 126 return 0; 127 } 128 129 chip->mixer.nid = nid; 130 chip->mixer.caps = val; 131 chip->mixer.array = (struct lola_mixer_array __iomem *) 132 (chip->bar[BAR1].remap_addr + LOLA_BAR1_SOURCE_GAIN_ENABLE); 133 134 /* reserve memory to copy mixer data for sleep mode transitions */ 135 chip->mixer.array_saved = vmalloc(sizeof(struct lola_mixer_array)); 136 137 /* mixer matrix sources are physical input data and play streams */ 138 chip->mixer.src_stream_outs = chip->pcm[PLAY].num_streams; 139 chip->mixer.src_phys_ins = chip->pin[CAPT].num_pins; 140 141 /* mixer matrix destinations are record streams and physical output */ 142 chip->mixer.dest_stream_ins = chip->pcm[CAPT].num_streams; 143 chip->mixer.dest_phys_outs = chip->pin[PLAY].num_pins; 144 145 /* mixer matrix can have unused areas between PhysIn and 146 * Play or Record and PhysOut zones 147 */ 148 chip->mixer.src_stream_out_ofs = chip->mixer.src_phys_ins + 149 LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(val); 150 chip->mixer.dest_phys_out_ofs = chip->mixer.dest_stream_ins + 151 LOLA_MIXER_DEST_REC_OUTPUT_SEPATATION(val); 152 153 /* example : MixerMatrix of LoLa881 154 * 0-------8------16-------8------16 155 * | | | | | 156 * | INPUT | | INPUT | | 157 * | -> |unused | -> |unused | 158 * | RECORD| | OUTPUT| | 159 * | | | | | 160 * 8-------------------------------- 161 * | | | | | 162 * | | | | | 163 * |unused |unused |unused |unused | 164 * | | | | | 165 * | | | | | 166 * 16------------------------------- 167 * | | | | | 168 * | PLAY | | PLAY | | 169 * | -> |unused | -> |unused | 170 * | RECORD| | OUTPUT| | 171 * | | | | | 172 * 8-------------------------------- 173 * | | | | | 174 * | | | | | 175 * |unused |unused |unused |unused | 176 * | | | | | 177 * | | | | | 178 * 16------------------------------- 179 */ 180 if (chip->mixer.src_stream_out_ofs > MAX_AUDIO_INOUT_COUNT || 181 chip->mixer.dest_phys_out_ofs > MAX_STREAM_IN_COUNT) { 182 printk(KERN_ERR SFX "Invalid mixer widget size\n"); 183 return -EINVAL; 184 } 185 186 chip->mixer.src_mask = ((1U << chip->mixer.src_phys_ins) - 1) | 187 (((1U << chip->mixer.src_stream_outs) - 1) 188 << chip->mixer.src_stream_out_ofs); 189 chip->mixer.dest_mask = ((1U << chip->mixer.dest_stream_ins) - 1) | 190 (((1U << chip->mixer.dest_phys_outs) - 1) 191 << chip->mixer.dest_phys_out_ofs); 192 193 return 0; 194 } 195 196 static int lola_mixer_set_src_gain(struct lola *chip, unsigned int id, 197 unsigned short gain, bool on) 198 { 199 unsigned int oldval, val; 200 201 if (!(chip->mixer.src_mask & (1 << id))) 202 return -EINVAL; 203 writew(gain, &chip->mixer.array->src_gain[id]); 204 oldval = val = readl(&chip->mixer.array->src_gain_enable); 205 if (on) 206 val |= (1 << id); 207 else 208 val &= ~(1 << id); 209 writel(val, &chip->mixer.array->src_gain_enable); 210 lola_codec_flush(chip); 211 /* inform micro-controller about the new source gain */ 212 return lola_codec_write(chip, chip->mixer.nid, 213 LOLA_VERB_SET_SOURCE_GAIN, id, 0); 214 } 215 216 #if 0 /* not used */ 217 static int lola_mixer_set_src_gains(struct lola *chip, unsigned int mask, 218 unsigned short *gains) 219 { 220 int i; 221 222 if ((chip->mixer.src_mask & mask) != mask) 223 return -EINVAL; 224 for (i = 0; i < LOLA_MIXER_DIM; i++) { 225 if (mask & (1 << i)) { 226 writew(*gains, &chip->mixer.array->src_gain[i]); 227 gains++; 228 } 229 } 230 writel(mask, &chip->mixer.array->src_gain_enable); 231 lola_codec_flush(chip); 232 if (chip->mixer.caps & LOLA_PEAK_METER_CAN_AGC_MASK) { 233 /* update for all srcs at once */ 234 return lola_codec_write(chip, chip->mixer.nid, 235 LOLA_VERB_SET_SOURCE_GAIN, 0x80, 0); 236 } 237 /* update manually */ 238 for (i = 0; i < LOLA_MIXER_DIM; i++) { 239 if (mask & (1 << i)) { 240 lola_codec_write(chip, chip->mixer.nid, 241 LOLA_VERB_SET_SOURCE_GAIN, i, 0); 242 } 243 } 244 return 0; 245 } 246 #endif /* not used */ 247 248 static int lola_mixer_set_mapping_gain(struct lola *chip, 249 unsigned int src, unsigned int dest, 250 unsigned short gain, bool on) 251 { 252 unsigned int val; 253 254 if (!(chip->mixer.src_mask & (1 << src)) || 255 !(chip->mixer.dest_mask & (1 << dest))) 256 return -EINVAL; 257 if (on) 258 writew(gain, &chip->mixer.array->dest_mix_gain[dest][src]); 259 val = readl(&chip->mixer.array->dest_mix_gain_enable[dest]); 260 if (on) 261 val |= (1 << src); 262 else 263 val &= ~(1 << src); 264 writel(val, &chip->mixer.array->dest_mix_gain_enable[dest]); 265 lola_codec_flush(chip); 266 return lola_codec_write(chip, chip->mixer.nid, LOLA_VERB_SET_MIX_GAIN, 267 src, dest); 268 } 269 270 static int lola_mixer_set_dest_gains(struct lola *chip, unsigned int id, 271 unsigned int mask, unsigned short *gains) 272 { 273 int i; 274 275 if (!(chip->mixer.dest_mask & (1 << id)) || 276 (chip->mixer.src_mask & mask) != mask) 277 return -EINVAL; 278 for (i = 0; i < LOLA_MIXER_DIM; i++) { 279 if (mask & (1 << i)) { 280 writew(*gains, &chip->mixer.array->dest_mix_gain[id][i]); 281 gains++; 282 } 283 } 284 writel(mask, &chip->mixer.array->dest_mix_gain_enable[id]); 285 lola_codec_flush(chip); 286 /* update for all dests at once */ 287 return lola_codec_write(chip, chip->mixer.nid, 288 LOLA_VERB_SET_DESTINATION_GAIN, id, 0); 289 } 290 291 /* 292 */ 293 294 static int set_analog_volume(struct lola *chip, int dir, 295 unsigned int idx, unsigned int val, 296 bool external_call); 297 298 int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute) 299 { 300 struct lola_pin *pin; 301 int idx, max_idx; 302 303 pin = chip->pin[dir].pins; 304 max_idx = chip->pin[dir].num_pins; 305 for (idx = 0; idx < max_idx; idx++) { 306 if (pin[idx].is_analog) { 307 unsigned int val = mute ? 0 : pin[idx].cur_gain_step; 308 /* set volume and do not save the value */ 309 set_analog_volume(chip, dir, idx, val, false); 310 } 311 } 312 return lola_codec_flush(chip); 313 } 314 315 void lola_save_mixer(struct lola *chip) 316 { 317 /* mute analog output */ 318 if (chip->mixer.array_saved) { 319 /* store contents of mixer array */ 320 memcpy_fromio(chip->mixer.array_saved, chip->mixer.array, 321 sizeof(*chip->mixer.array)); 322 } 323 lola_setup_all_analog_gains(chip, PLAY, true); /* output mute */ 324 } 325 326 void lola_restore_mixer(struct lola *chip) 327 { 328 int i; 329 330 /*lola_reset_setups(chip);*/ 331 if (chip->mixer.array_saved) { 332 /* restore contents of mixer array */ 333 memcpy_toio(chip->mixer.array, chip->mixer.array_saved, 334 sizeof(*chip->mixer.array)); 335 /* inform micro-controller about all restored values 336 * and ignore return values 337 */ 338 for (i = 0; i < chip->mixer.src_phys_ins; i++) 339 lola_codec_write(chip, chip->mixer.nid, 340 LOLA_VERB_SET_SOURCE_GAIN, 341 i, 0); 342 for (i = 0; i < chip->mixer.src_stream_outs; i++) 343 lola_codec_write(chip, chip->mixer.nid, 344 LOLA_VERB_SET_SOURCE_GAIN, 345 chip->mixer.src_stream_out_ofs + i, 0); 346 for (i = 0; i < chip->mixer.dest_stream_ins; i++) 347 lola_codec_write(chip, chip->mixer.nid, 348 LOLA_VERB_SET_DESTINATION_GAIN, 349 i, 0); 350 for (i = 0; i < chip->mixer.dest_phys_outs; i++) 351 lola_codec_write(chip, chip->mixer.nid, 352 LOLA_VERB_SET_DESTINATION_GAIN, 353 chip->mixer.dest_phys_out_ofs + i, 0); 354 lola_codec_flush(chip); 355 } 356 } 357 358 /* 359 */ 360 361 static int set_analog_volume(struct lola *chip, int dir, 362 unsigned int idx, unsigned int val, 363 bool external_call) 364 { 365 struct lola_pin *pin; 366 int err; 367 368 if (idx >= chip->pin[dir].num_pins) 369 return -EINVAL; 370 pin = &chip->pin[dir].pins[idx]; 371 if (!pin->is_analog || pin->amp_num_steps <= val) 372 return -EINVAL; 373 if (external_call && pin->cur_gain_step == val) 374 return 0; 375 if (external_call) 376 lola_codec_flush(chip); 377 err = lola_codec_write(chip, pin->nid, 378 LOLA_VERB_SET_AMP_GAIN_MUTE, val, 0); 379 if (err < 0) 380 return err; 381 if (external_call) 382 pin->cur_gain_step = val; 383 return 0; 384 } 385 386 int lola_set_src_config(struct lola *chip, unsigned int src_mask, bool update) 387 { 388 int ret = 0; 389 int success = 0; 390 int n, err; 391 392 /* SRC can be activated and the dwInputSRCMask is valid? */ 393 if ((chip->input_src_caps_mask & src_mask) != src_mask) 394 return -EINVAL; 395 /* handle all even Inputs - SRC is a stereo setting !!! */ 396 for (n = 0; n < chip->pin[CAPT].num_pins; n += 2) { 397 unsigned int mask = 3U << n; /* handle the stereo case */ 398 unsigned int new_src, src_state; 399 if (!(chip->input_src_caps_mask & mask)) 400 continue; 401 /* if one IO needs SRC, both stereo IO will get SRC */ 402 new_src = (src_mask & mask) != 0; 403 if (update) { 404 src_state = (chip->input_src_mask & mask) != 0; 405 if (src_state == new_src) 406 continue; /* nothing to change for this IO */ 407 } 408 err = lola_codec_write(chip, chip->pcm[CAPT].streams[n].nid, 409 LOLA_VERB_SET_SRC, new_src, 0); 410 if (!err) 411 success++; 412 else 413 ret = err; 414 } 415 if (success) 416 ret = lola_codec_flush(chip); 417 if (!ret) 418 chip->input_src_mask = src_mask; 419 return ret; 420 } 421 422 /* 423 */ 424 static int init_mixer_values(struct lola *chip) 425 { 426 int i; 427 428 /* all src on */ 429 lola_set_src_config(chip, (1 << chip->pin[CAPT].num_pins) - 1, false); 430 431 /* clear all matrix */ 432 memset_io(chip->mixer.array, 0, sizeof(*chip->mixer.array)); 433 /* set src gain to 0dB */ 434 for (i = 0; i < chip->mixer.src_phys_ins; i++) 435 lola_mixer_set_src_gain(chip, i, 336, true); /* 0dB */ 436 for (i = 0; i < chip->mixer.src_stream_outs; i++) 437 lola_mixer_set_src_gain(chip, 438 i + chip->mixer.src_stream_out_ofs, 439 336, true); /* 0dB */ 440 /* set 1:1 dest gain */ 441 for (i = 0; i < chip->mixer.dest_stream_ins; i++) { 442 int src = i % chip->mixer.src_phys_ins; 443 lola_mixer_set_mapping_gain(chip, src, i, 336, true); 444 } 445 for (i = 0; i < chip->mixer.src_stream_outs; i++) { 446 int src = chip->mixer.src_stream_out_ofs + i; 447 int dst = chip->mixer.dest_phys_out_ofs + 448 i % chip->mixer.dest_phys_outs; 449 lola_mixer_set_mapping_gain(chip, src, dst, 336, true); 450 } 451 return 0; 452 } 453 454 /* 455 * analog mixer control element 456 */ 457 static int lola_analog_vol_info(struct snd_kcontrol *kcontrol, 458 struct snd_ctl_elem_info *uinfo) 459 { 460 struct lola *chip = snd_kcontrol_chip(kcontrol); 461 int dir = kcontrol->private_value; 462 463 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 464 uinfo->count = chip->pin[dir].num_pins; 465 uinfo->value.integer.min = 0; 466 uinfo->value.integer.max = chip->pin[dir].pins[0].amp_num_steps; 467 return 0; 468 } 469 470 static int lola_analog_vol_get(struct snd_kcontrol *kcontrol, 471 struct snd_ctl_elem_value *ucontrol) 472 { 473 struct lola *chip = snd_kcontrol_chip(kcontrol); 474 int dir = kcontrol->private_value; 475 int i; 476 477 for (i = 0; i < chip->pin[dir].num_pins; i++) 478 ucontrol->value.integer.value[i] = 479 chip->pin[dir].pins[i].cur_gain_step; 480 return 0; 481 } 482 483 static int lola_analog_vol_put(struct snd_kcontrol *kcontrol, 484 struct snd_ctl_elem_value *ucontrol) 485 { 486 struct lola *chip = snd_kcontrol_chip(kcontrol); 487 int dir = kcontrol->private_value; 488 int i, err; 489 490 for (i = 0; i < chip->pin[dir].num_pins; i++) { 491 err = set_analog_volume(chip, dir, i, 492 ucontrol->value.integer.value[i], 493 true); 494 if (err < 0) 495 return err; 496 } 497 return 0; 498 } 499 500 static int lola_analog_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, 501 unsigned int size, unsigned int __user *tlv) 502 { 503 struct lola *chip = snd_kcontrol_chip(kcontrol); 504 int dir = kcontrol->private_value; 505 unsigned int val1, val2; 506 struct lola_pin *pin; 507 508 if (size < 4 * sizeof(unsigned int)) 509 return -ENOMEM; 510 pin = &chip->pin[dir].pins[0]; 511 512 val2 = pin->amp_step_size * 25; 513 val1 = -1 * (int)pin->amp_offset * (int)val2; 514 #ifdef TLV_DB_SCALE_MUTE 515 val2 |= TLV_DB_SCALE_MUTE; 516 #endif 517 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, tlv)) 518 return -EFAULT; 519 if (put_user(2 * sizeof(unsigned int), tlv + 1)) 520 return -EFAULT; 521 if (put_user(val1, tlv + 2)) 522 return -EFAULT; 523 if (put_user(val2, tlv + 3)) 524 return -EFAULT; 525 return 0; 526 } 527 528 static struct snd_kcontrol_new lola_analog_mixer __devinitdata = { 529 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 530 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 531 SNDRV_CTL_ELEM_ACCESS_TLV_READ | 532 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), 533 .info = lola_analog_vol_info, 534 .get = lola_analog_vol_get, 535 .put = lola_analog_vol_put, 536 .tlv.c = lola_analog_vol_tlv, 537 }; 538 539 static int __devinit create_analog_mixer(struct lola *chip, int dir, char *name) 540 { 541 if (!chip->pin[dir].num_pins) 542 return 0; 543 lola_analog_mixer.name = name; 544 lola_analog_mixer.private_value = dir; 545 return snd_ctl_add(chip->card, 546 snd_ctl_new1(&lola_analog_mixer, chip)); 547 } 548 549 /* 550 */ 551 static int lola_input_src_info(struct snd_kcontrol *kcontrol, 552 struct snd_ctl_elem_info *uinfo) 553 { 554 struct lola *chip = snd_kcontrol_chip(kcontrol); 555 556 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 557 uinfo->count = chip->pin[CAPT].num_pins; 558 uinfo->value.integer.min = 0; 559 uinfo->value.integer.max = 1; 560 return 0; 561 } 562 563 static int lola_input_src_get(struct snd_kcontrol *kcontrol, 564 struct snd_ctl_elem_value *ucontrol) 565 { 566 struct lola *chip = snd_kcontrol_chip(kcontrol); 567 int i; 568 569 for (i = 0; i < chip->pin[CAPT].num_pins; i++) 570 ucontrol->value.integer.value[i] = 571 !!(chip->input_src_mask & (1 << i)); 572 return 0; 573 } 574 575 static int lola_input_src_put(struct snd_kcontrol *kcontrol, 576 struct snd_ctl_elem_value *ucontrol) 577 { 578 struct lola *chip = snd_kcontrol_chip(kcontrol); 579 int i; 580 unsigned int mask; 581 582 mask = 0; 583 for (i = 0; i < chip->pin[CAPT].num_pins; i++) 584 if (ucontrol->value.integer.value[i]) 585 mask |= 1 << i; 586 return lola_set_src_config(chip, mask, true); 587 } 588 589 static struct snd_kcontrol_new lola_input_src_mixer __devinitdata = { 590 .name = "Analog Capture Switch", 591 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 592 .info = lola_input_src_info, 593 .get = lola_input_src_get, 594 .put = lola_input_src_put, 595 }; 596 597 static int __devinit create_input_src_mixer(struct lola *chip) 598 { 599 return snd_ctl_add(chip->card, 600 snd_ctl_new1(&lola_input_src_mixer, chip)); 601 } 602 603 /* 604 * src gain mixer 605 */ 606 static int lola_src_gain_info(struct snd_kcontrol *kcontrol, 607 struct snd_ctl_elem_info *uinfo) 608 { 609 unsigned int count = (kcontrol->private_value >> 8) & 0xff; 610 611 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 612 uinfo->count = count; 613 uinfo->value.integer.min = 0; 614 uinfo->value.integer.max = 409; 615 return 0; 616 } 617 618 static int lola_src_gain_get(struct snd_kcontrol *kcontrol, 619 struct snd_ctl_elem_value *ucontrol) 620 { 621 struct lola *chip = snd_kcontrol_chip(kcontrol); 622 unsigned int ofs = kcontrol->private_value & 0xff; 623 unsigned int count = (kcontrol->private_value >> 8) & 0xff; 624 unsigned int mask, i; 625 626 mask = readl(&chip->mixer.array->src_gain_enable); 627 for (i = 0; i < count; i++) { 628 unsigned int idx = ofs + i; 629 unsigned short val; 630 if (!(chip->mixer.src_mask & (1 << idx))) 631 return -EINVAL; 632 if (mask & (1 << idx)) 633 val = readw(&chip->mixer.array->src_gain[idx]) + 1; 634 else 635 val = 0; 636 ucontrol->value.integer.value[i] = val; 637 } 638 return 0; 639 } 640 641 static int lola_src_gain_put(struct snd_kcontrol *kcontrol, 642 struct snd_ctl_elem_value *ucontrol) 643 { 644 struct lola *chip = snd_kcontrol_chip(kcontrol); 645 unsigned int ofs = kcontrol->private_value & 0xff; 646 unsigned int count = (kcontrol->private_value >> 8) & 0xff; 647 int i, err; 648 649 for (i = 0; i < count; i++) { 650 unsigned int idx = ofs + i; 651 unsigned short val = ucontrol->value.integer.value[i]; 652 if (val) 653 val--; 654 err = lola_mixer_set_src_gain(chip, idx, val, !!val); 655 if (err < 0) 656 return err; 657 } 658 return 0; 659 } 660 661 /* raw value: 0 = -84dB, 336 = 0dB, 408=18dB, incremented 1 for mute */ 662 static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv, -8425, 25, 1); 663 664 static struct snd_kcontrol_new lola_src_gain_mixer __devinitdata = { 665 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 666 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 667 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 668 .info = lola_src_gain_info, 669 .get = lola_src_gain_get, 670 .put = lola_src_gain_put, 671 .tlv.p = lola_src_gain_tlv, 672 }; 673 674 static int __devinit create_src_gain_mixer(struct lola *chip, 675 int num, int ofs, char *name) 676 { 677 lola_src_gain_mixer.name = name; 678 lola_src_gain_mixer.private_value = ofs + (num << 8); 679 return snd_ctl_add(chip->card, 680 snd_ctl_new1(&lola_src_gain_mixer, chip)); 681 } 682 683 /* 684 * destination gain (matrix-like) mixer 685 */ 686 static int lola_dest_gain_info(struct snd_kcontrol *kcontrol, 687 struct snd_ctl_elem_info *uinfo) 688 { 689 unsigned int src_num = (kcontrol->private_value >> 8) & 0xff; 690 691 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 692 uinfo->count = src_num; 693 uinfo->value.integer.min = 0; 694 uinfo->value.integer.max = 433; 695 return 0; 696 } 697 698 static int lola_dest_gain_get(struct snd_kcontrol *kcontrol, 699 struct snd_ctl_elem_value *ucontrol) 700 { 701 struct lola *chip = snd_kcontrol_chip(kcontrol); 702 unsigned int src_ofs = kcontrol->private_value & 0xff; 703 unsigned int src_num = (kcontrol->private_value >> 8) & 0xff; 704 unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff; 705 unsigned int dst, mask, i; 706 707 dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs; 708 mask = readl(&chip->mixer.array->dest_mix_gain_enable[dst]); 709 for (i = 0; i < src_num; i++) { 710 unsigned int src = src_ofs + i; 711 unsigned short val; 712 if (!(chip->mixer.src_mask & (1 << src))) 713 return -EINVAL; 714 if (mask & (1 << dst)) 715 val = readw(&chip->mixer.array->dest_mix_gain[dst][src]) + 1; 716 else 717 val = 0; 718 ucontrol->value.integer.value[i] = val; 719 } 720 return 0; 721 } 722 723 static int lola_dest_gain_put(struct snd_kcontrol *kcontrol, 724 struct snd_ctl_elem_value *ucontrol) 725 { 726 struct lola *chip = snd_kcontrol_chip(kcontrol); 727 unsigned int src_ofs = kcontrol->private_value & 0xff; 728 unsigned int src_num = (kcontrol->private_value >> 8) & 0xff; 729 unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff; 730 unsigned int dst, mask; 731 unsigned short gains[MAX_STREAM_COUNT]; 732 int i, num; 733 734 mask = 0; 735 num = 0; 736 for (i = 0; i < src_num; i++) { 737 unsigned short val = ucontrol->value.integer.value[i]; 738 if (val) { 739 gains[num++] = val - 1; 740 mask |= 1 << i; 741 } 742 } 743 mask <<= src_ofs; 744 dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs; 745 return lola_mixer_set_dest_gains(chip, dst, mask, gains); 746 } 747 748 static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv, -8425, 25, 1); 749 750 static struct snd_kcontrol_new lola_dest_gain_mixer __devinitdata = { 751 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 752 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 753 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 754 .info = lola_dest_gain_info, 755 .get = lola_dest_gain_get, 756 .put = lola_dest_gain_put, 757 .tlv.p = lola_dest_gain_tlv, 758 }; 759 760 static int __devinit create_dest_gain_mixer(struct lola *chip, 761 int src_num, int src_ofs, 762 int num, int ofs, char *name) 763 { 764 lola_dest_gain_mixer.count = num; 765 lola_dest_gain_mixer.name = name; 766 lola_dest_gain_mixer.private_value = 767 src_ofs + (src_num << 8) + (ofs << 16) + (num << 24); 768 return snd_ctl_add(chip->card, 769 snd_ctl_new1(&lola_dest_gain_mixer, chip)); 770 } 771 772 /* 773 */ 774 int __devinit lola_create_mixer(struct lola *chip) 775 { 776 int err; 777 778 err = create_analog_mixer(chip, PLAY, "Analog Playback Volume"); 779 if (err < 0) 780 return err; 781 err = create_analog_mixer(chip, CAPT, "Analog Capture Volume"); 782 if (err < 0) 783 return err; 784 err = create_input_src_mixer(chip); 785 if (err < 0) 786 return err; 787 err = create_src_gain_mixer(chip, chip->mixer.src_phys_ins, 0, 788 "Line Source Gain Volume"); 789 if (err < 0) 790 return err; 791 err = create_src_gain_mixer(chip, chip->mixer.src_stream_outs, 792 chip->mixer.src_stream_out_ofs, 793 "Stream Source Gain Volume"); 794 if (err < 0) 795 return err; 796 err = create_dest_gain_mixer(chip, 797 chip->mixer.src_phys_ins, 0, 798 chip->mixer.dest_stream_ins, 0, 799 "Line Capture Volume"); 800 if (err < 0) 801 return err; 802 err = create_dest_gain_mixer(chip, 803 chip->mixer.src_stream_outs, 804 chip->mixer.src_stream_out_ofs, 805 chip->mixer.dest_stream_ins, 0, 806 "Stream-Loopback Capture Volume"); 807 if (err < 0) 808 return err; 809 err = create_dest_gain_mixer(chip, 810 chip->mixer.src_phys_ins, 0, 811 chip->mixer.dest_phys_outs, 812 chip->mixer.dest_phys_out_ofs, 813 "Line-Loopback Playback Volume"); 814 if (err < 0) 815 return err; 816 err = create_dest_gain_mixer(chip, 817 chip->mixer.src_stream_outs, 818 chip->mixer.src_stream_out_ofs, 819 chip->mixer.dest_phys_outs, 820 chip->mixer.dest_phys_out_ofs, 821 "Stream Playback Volume"); 822 if (err < 0) 823 return err; 824 825 return init_mixer_values(chip); 826 } 827