0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/init.h>
0010 #include <linux/vmalloc.h>
0011 #include <linux/io.h>
0012 #include <sound/core.h>
0013 #include <sound/control.h>
0014 #include <sound/pcm.h>
0015 #include <sound/tlv.h>
0016 #include "lola.h"
0017
0018 static int lola_init_pin(struct lola *chip, struct lola_pin *pin,
0019 int dir, int nid)
0020 {
0021 unsigned int val;
0022 int err;
0023
0024 pin->nid = nid;
0025 err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
0026 if (err < 0) {
0027 dev_err(chip->card->dev, "Can't read wcaps for 0x%x\n", nid);
0028 return err;
0029 }
0030 val &= 0x00f00fff;
0031 if (val == 0x00400200)
0032 pin->is_analog = false;
0033 else if (val == 0x0040000a && dir == CAPT)
0034 pin->is_analog = true;
0035 else if (val == 0x0040000c && dir == PLAY)
0036 pin->is_analog = true;
0037 else {
0038 dev_err(chip->card->dev, "Invalid wcaps 0x%x for 0x%x\n", val, nid);
0039 return -EINVAL;
0040 }
0041
0042
0043
0044 if (!pin->is_analog)
0045 return 0;
0046
0047 if (dir == PLAY)
0048 err = lola_read_param(chip, nid, LOLA_PAR_AMP_OUT_CAP, &val);
0049 else
0050 err = lola_read_param(chip, nid, LOLA_PAR_AMP_IN_CAP, &val);
0051 if (err < 0) {
0052 dev_err(chip->card->dev, "Can't read AMP-caps for 0x%x\n", nid);
0053 return err;
0054 }
0055
0056 pin->amp_mute = LOLA_AMP_MUTE_CAPABLE(val);
0057 pin->amp_step_size = LOLA_AMP_STEP_SIZE(val);
0058 pin->amp_num_steps = LOLA_AMP_NUM_STEPS(val);
0059 if (pin->amp_num_steps) {
0060
0061 pin->amp_num_steps++;
0062 pin->amp_step_size++;
0063 }
0064 pin->amp_offset = LOLA_AMP_OFFSET(val);
0065
0066 err = lola_codec_read(chip, nid, LOLA_VERB_GET_MAX_LEVEL, 0, 0, &val,
0067 NULL);
0068 if (err < 0) {
0069 dev_err(chip->card->dev, "Can't get MAX_LEVEL 0x%x\n", nid);
0070 return err;
0071 }
0072 pin->max_level = val & 0x3ff;
0073
0074 pin->config_default_reg = 0;
0075 pin->fixed_gain_list_len = 0;
0076 pin->cur_gain_step = 0;
0077
0078 return 0;
0079 }
0080
0081 int lola_init_pins(struct lola *chip, int dir, int *nidp)
0082 {
0083 int i, err, nid;
0084 nid = *nidp;
0085 for (i = 0; i < chip->pin[dir].num_pins; i++, nid++) {
0086 err = lola_init_pin(chip, &chip->pin[dir].pins[i], dir, nid);
0087 if (err < 0)
0088 return err;
0089 if (chip->pin[dir].pins[i].is_analog)
0090 chip->pin[dir].num_analog_pins++;
0091 }
0092 *nidp = nid;
0093 return 0;
0094 }
0095
0096 void lola_free_mixer(struct lola *chip)
0097 {
0098 vfree(chip->mixer.array_saved);
0099 }
0100
0101 int lola_init_mixer_widget(struct lola *chip, int nid)
0102 {
0103 unsigned int val;
0104 int err;
0105
0106 err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
0107 if (err < 0) {
0108 dev_err(chip->card->dev, "Can't read wcaps for 0x%x\n", nid);
0109 return err;
0110 }
0111
0112 if ((val & 0xfff00000) != 0x02f00000) {
0113 dev_dbg(chip->card->dev, "No valid mixer widget\n");
0114 return 0;
0115 }
0116
0117 chip->mixer.nid = nid;
0118 chip->mixer.caps = val;
0119 chip->mixer.array = (struct lola_mixer_array __iomem *)
0120 (chip->bar[BAR1].remap_addr + LOLA_BAR1_SOURCE_GAIN_ENABLE);
0121
0122
0123 chip->mixer.array_saved = vmalloc(sizeof(struct lola_mixer_array));
0124 if (!chip->mixer.array_saved)
0125 return -ENOMEM;
0126
0127
0128 chip->mixer.src_stream_outs = chip->pcm[PLAY].num_streams;
0129 chip->mixer.src_phys_ins = chip->pin[CAPT].num_pins;
0130
0131
0132 chip->mixer.dest_stream_ins = chip->pcm[CAPT].num_streams;
0133 chip->mixer.dest_phys_outs = chip->pin[PLAY].num_pins;
0134
0135
0136
0137
0138 chip->mixer.src_stream_out_ofs = chip->mixer.src_phys_ins +
0139 LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(val);
0140 chip->mixer.dest_phys_out_ofs = chip->mixer.dest_stream_ins +
0141 LOLA_MIXER_DEST_REC_OUTPUT_SEPARATION(val);
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 if (chip->mixer.src_stream_out_ofs > MAX_AUDIO_INOUT_COUNT ||
0192 chip->mixer.dest_phys_out_ofs > MAX_STREAM_IN_COUNT) {
0193 dev_err(chip->card->dev, "Invalid mixer widget size\n");
0194 return -EINVAL;
0195 }
0196
0197 chip->mixer.src_mask = ((1U << chip->mixer.src_phys_ins) - 1) |
0198 (((1U << chip->mixer.src_stream_outs) - 1)
0199 << chip->mixer.src_stream_out_ofs);
0200 chip->mixer.dest_mask = ((1U << chip->mixer.dest_stream_ins) - 1) |
0201 (((1U << chip->mixer.dest_phys_outs) - 1)
0202 << chip->mixer.dest_phys_out_ofs);
0203
0204 dev_dbg(chip->card->dev, "Mixer src_mask=%x, dest_mask=%x\n",
0205 chip->mixer.src_mask, chip->mixer.dest_mask);
0206
0207 return 0;
0208 }
0209
0210 static int lola_mixer_set_src_gain(struct lola *chip, unsigned int id,
0211 unsigned short gain, bool on)
0212 {
0213 unsigned int oldval, val;
0214
0215 if (!(chip->mixer.src_mask & (1 << id)))
0216 return -EINVAL;
0217 oldval = val = readl(&chip->mixer.array->src_gain_enable);
0218 if (on)
0219 val |= (1 << id);
0220 else
0221 val &= ~(1 << id);
0222
0223 if ((val == oldval) &&
0224 (gain == readw(&chip->mixer.array->src_gain[id])))
0225 return 0;
0226
0227 dev_dbg(chip->card->dev,
0228 "lola_mixer_set_src_gain (id=%d, gain=%d) enable=%x\n",
0229 id, gain, val);
0230 writew(gain, &chip->mixer.array->src_gain[id]);
0231 writel(val, &chip->mixer.array->src_gain_enable);
0232 lola_codec_flush(chip);
0233
0234 return lola_codec_write(chip, chip->mixer.nid,
0235 LOLA_VERB_SET_SOURCE_GAIN, id, 0);
0236 }
0237
0238 #if 0
0239 static int lola_mixer_set_src_gains(struct lola *chip, unsigned int mask,
0240 unsigned short *gains)
0241 {
0242 int i;
0243
0244 if ((chip->mixer.src_mask & mask) != mask)
0245 return -EINVAL;
0246 for (i = 0; i < LOLA_MIXER_DIM; i++) {
0247 if (mask & (1 << i)) {
0248 writew(*gains, &chip->mixer.array->src_gain[i]);
0249 gains++;
0250 }
0251 }
0252 writel(mask, &chip->mixer.array->src_gain_enable);
0253 lola_codec_flush(chip);
0254 if (chip->mixer.caps & LOLA_PEAK_METER_CAN_AGC_MASK) {
0255
0256 return lola_codec_write(chip, chip->mixer.nid,
0257 LOLA_VERB_SET_SOURCE_GAIN, 0x80, 0);
0258 }
0259
0260 for (i = 0; i < LOLA_MIXER_DIM; i++) {
0261 if (mask & (1 << i)) {
0262 lola_codec_write(chip, chip->mixer.nid,
0263 LOLA_VERB_SET_SOURCE_GAIN, i, 0);
0264 }
0265 }
0266 return 0;
0267 }
0268 #endif
0269
0270 static int lola_mixer_set_mapping_gain(struct lola *chip,
0271 unsigned int src, unsigned int dest,
0272 unsigned short gain, bool on)
0273 {
0274 unsigned int val;
0275
0276 if (!(chip->mixer.src_mask & (1 << src)) ||
0277 !(chip->mixer.dest_mask & (1 << dest)))
0278 return -EINVAL;
0279 if (on)
0280 writew(gain, &chip->mixer.array->dest_mix_gain[dest][src]);
0281 val = readl(&chip->mixer.array->dest_mix_gain_enable[dest]);
0282 if (on)
0283 val |= (1 << src);
0284 else
0285 val &= ~(1 << src);
0286 writel(val, &chip->mixer.array->dest_mix_gain_enable[dest]);
0287 lola_codec_flush(chip);
0288 return lola_codec_write(chip, chip->mixer.nid, LOLA_VERB_SET_MIX_GAIN,
0289 src, dest);
0290 }
0291
0292 #if 0
0293 static int lola_mixer_set_dest_gains(struct lola *chip, unsigned int id,
0294 unsigned int mask, unsigned short *gains)
0295 {
0296 int i;
0297
0298 if (!(chip->mixer.dest_mask & (1 << id)) ||
0299 (chip->mixer.src_mask & mask) != mask)
0300 return -EINVAL;
0301 for (i = 0; i < LOLA_MIXER_DIM; i++) {
0302 if (mask & (1 << i)) {
0303 writew(*gains, &chip->mixer.array->dest_mix_gain[id][i]);
0304 gains++;
0305 }
0306 }
0307 writel(mask, &chip->mixer.array->dest_mix_gain_enable[id]);
0308 lola_codec_flush(chip);
0309
0310 return lola_codec_write(chip, chip->mixer.nid,
0311 LOLA_VERB_SET_DESTINATION_GAIN, id, 0);
0312 }
0313 #endif
0314
0315
0316
0317
0318 static int set_analog_volume(struct lola *chip, int dir,
0319 unsigned int idx, unsigned int val,
0320 bool external_call);
0321
0322 int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute)
0323 {
0324 struct lola_pin *pin;
0325 int idx, max_idx;
0326
0327 pin = chip->pin[dir].pins;
0328 max_idx = chip->pin[dir].num_pins;
0329 for (idx = 0; idx < max_idx; idx++) {
0330 if (pin[idx].is_analog) {
0331 unsigned int val = mute ? 0 : pin[idx].cur_gain_step;
0332
0333 set_analog_volume(chip, dir, idx, val, false);
0334 }
0335 }
0336 return lola_codec_flush(chip);
0337 }
0338
0339 void lola_save_mixer(struct lola *chip)
0340 {
0341
0342 if (chip->mixer.array_saved) {
0343
0344 memcpy_fromio(chip->mixer.array_saved, chip->mixer.array,
0345 sizeof(*chip->mixer.array));
0346 }
0347 lola_setup_all_analog_gains(chip, PLAY, true);
0348 }
0349
0350 void lola_restore_mixer(struct lola *chip)
0351 {
0352 int i;
0353
0354
0355 if (chip->mixer.array_saved) {
0356
0357 memcpy_toio(chip->mixer.array, chip->mixer.array_saved,
0358 sizeof(*chip->mixer.array));
0359
0360
0361
0362 for (i = 0; i < chip->mixer.src_phys_ins; i++)
0363 lola_codec_write(chip, chip->mixer.nid,
0364 LOLA_VERB_SET_SOURCE_GAIN,
0365 i, 0);
0366 for (i = 0; i < chip->mixer.src_stream_outs; i++)
0367 lola_codec_write(chip, chip->mixer.nid,
0368 LOLA_VERB_SET_SOURCE_GAIN,
0369 chip->mixer.src_stream_out_ofs + i, 0);
0370 for (i = 0; i < chip->mixer.dest_stream_ins; i++)
0371 lola_codec_write(chip, chip->mixer.nid,
0372 LOLA_VERB_SET_DESTINATION_GAIN,
0373 i, 0);
0374 for (i = 0; i < chip->mixer.dest_phys_outs; i++)
0375 lola_codec_write(chip, chip->mixer.nid,
0376 LOLA_VERB_SET_DESTINATION_GAIN,
0377 chip->mixer.dest_phys_out_ofs + i, 0);
0378 lola_codec_flush(chip);
0379 }
0380 }
0381
0382
0383
0384
0385 static int set_analog_volume(struct lola *chip, int dir,
0386 unsigned int idx, unsigned int val,
0387 bool external_call)
0388 {
0389 struct lola_pin *pin;
0390 int err;
0391
0392 if (idx >= chip->pin[dir].num_pins)
0393 return -EINVAL;
0394 pin = &chip->pin[dir].pins[idx];
0395 if (!pin->is_analog || pin->amp_num_steps <= val)
0396 return -EINVAL;
0397 if (external_call && pin->cur_gain_step == val)
0398 return 0;
0399 if (external_call)
0400 lola_codec_flush(chip);
0401 dev_dbg(chip->card->dev,
0402 "set_analog_volume (dir=%d idx=%d, volume=%d)\n",
0403 dir, idx, val);
0404 err = lola_codec_write(chip, pin->nid,
0405 LOLA_VERB_SET_AMP_GAIN_MUTE, val, 0);
0406 if (err < 0)
0407 return err;
0408 if (external_call)
0409 pin->cur_gain_step = val;
0410 return 0;
0411 }
0412
0413 int lola_set_src_config(struct lola *chip, unsigned int src_mask, bool update)
0414 {
0415 int ret = 0;
0416 int success = 0;
0417 int n, err;
0418
0419
0420 if ((chip->input_src_caps_mask & src_mask) != src_mask)
0421 return -EINVAL;
0422
0423 for (n = 0; n < chip->pin[CAPT].num_pins; n += 2) {
0424 unsigned int mask = 3U << n;
0425 unsigned int new_src, src_state;
0426 if (!(chip->input_src_caps_mask & mask))
0427 continue;
0428
0429 new_src = (src_mask & mask) != 0;
0430 if (update) {
0431 src_state = (chip->input_src_mask & mask) != 0;
0432 if (src_state == new_src)
0433 continue;
0434 }
0435 err = lola_codec_write(chip, chip->pcm[CAPT].streams[n].nid,
0436 LOLA_VERB_SET_SRC, new_src, 0);
0437 if (!err)
0438 success++;
0439 else
0440 ret = err;
0441 }
0442 if (success)
0443 ret = lola_codec_flush(chip);
0444 if (!ret)
0445 chip->input_src_mask = src_mask;
0446 return ret;
0447 }
0448
0449
0450
0451 static int init_mixer_values(struct lola *chip)
0452 {
0453 int i;
0454
0455
0456 lola_set_src_config(chip, (1 << chip->pin[CAPT].num_pins) - 1, false);
0457
0458
0459 memset_io(chip->mixer.array, 0, sizeof(*chip->mixer.array));
0460
0461 for (i = 0; i < chip->mixer.dest_stream_ins; i++)
0462 lola_codec_write(chip, chip->mixer.nid,
0463 LOLA_VERB_SET_DESTINATION_GAIN,
0464 i, 0);
0465
0466 for (i = 0; i < chip->mixer.dest_phys_outs; i++)
0467 lola_codec_write(chip, chip->mixer.nid,
0468 LOLA_VERB_SET_DESTINATION_GAIN,
0469 chip->mixer.dest_phys_out_ofs + i, 0);
0470
0471
0472 for (i = 0; i < chip->mixer.src_phys_ins; i++)
0473 lola_mixer_set_src_gain(chip, i, 336, true);
0474
0475
0476 for (i = 0; i < chip->mixer.src_stream_outs; i++)
0477 lola_mixer_set_src_gain(chip,
0478 i + chip->mixer.src_stream_out_ofs,
0479 336, true);
0480
0481 for (i = 0; i < chip->mixer.dest_stream_ins; i++) {
0482 int src = i % chip->mixer.src_phys_ins;
0483 lola_mixer_set_mapping_gain(chip, src, i, 336, true);
0484 }
0485
0486
0487
0488
0489 for (i = 0; i < chip->mixer.src_stream_outs; i++) {
0490 int src = chip->mixer.src_stream_out_ofs + i;
0491 int dst = chip->mixer.dest_phys_out_ofs +
0492 i % chip->mixer.dest_phys_outs;
0493 lola_mixer_set_mapping_gain(chip, src, dst, 336, true);
0494 }
0495 return 0;
0496 }
0497
0498
0499
0500
0501 static int lola_analog_vol_info(struct snd_kcontrol *kcontrol,
0502 struct snd_ctl_elem_info *uinfo)
0503 {
0504 struct lola *chip = snd_kcontrol_chip(kcontrol);
0505 int dir = kcontrol->private_value;
0506
0507 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0508 uinfo->count = chip->pin[dir].num_pins;
0509 uinfo->value.integer.min = 0;
0510 uinfo->value.integer.max = chip->pin[dir].pins[0].amp_num_steps;
0511 return 0;
0512 }
0513
0514 static int lola_analog_vol_get(struct snd_kcontrol *kcontrol,
0515 struct snd_ctl_elem_value *ucontrol)
0516 {
0517 struct lola *chip = snd_kcontrol_chip(kcontrol);
0518 int dir = kcontrol->private_value;
0519 int i;
0520
0521 for (i = 0; i < chip->pin[dir].num_pins; i++)
0522 ucontrol->value.integer.value[i] =
0523 chip->pin[dir].pins[i].cur_gain_step;
0524 return 0;
0525 }
0526
0527 static int lola_analog_vol_put(struct snd_kcontrol *kcontrol,
0528 struct snd_ctl_elem_value *ucontrol)
0529 {
0530 struct lola *chip = snd_kcontrol_chip(kcontrol);
0531 int dir = kcontrol->private_value;
0532 int i, err;
0533
0534 for (i = 0; i < chip->pin[dir].num_pins; i++) {
0535 err = set_analog_volume(chip, dir, i,
0536 ucontrol->value.integer.value[i],
0537 true);
0538 if (err < 0)
0539 return err;
0540 }
0541 return 0;
0542 }
0543
0544 static int lola_analog_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
0545 unsigned int size, unsigned int __user *tlv)
0546 {
0547 struct lola *chip = snd_kcontrol_chip(kcontrol);
0548 int dir = kcontrol->private_value;
0549 unsigned int val1, val2;
0550 struct lola_pin *pin;
0551
0552 if (size < 4 * sizeof(unsigned int))
0553 return -ENOMEM;
0554 pin = &chip->pin[dir].pins[0];
0555
0556 val2 = pin->amp_step_size * 25;
0557 val1 = -1 * (int)pin->amp_offset * (int)val2;
0558 #ifdef TLV_DB_SCALE_MUTE
0559 val2 |= TLV_DB_SCALE_MUTE;
0560 #endif
0561 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, tlv))
0562 return -EFAULT;
0563 if (put_user(2 * sizeof(unsigned int), tlv + 1))
0564 return -EFAULT;
0565 if (put_user(val1, tlv + 2))
0566 return -EFAULT;
0567 if (put_user(val2, tlv + 3))
0568 return -EFAULT;
0569 return 0;
0570 }
0571
0572 static struct snd_kcontrol_new lola_analog_mixer = {
0573 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0574 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
0575 SNDRV_CTL_ELEM_ACCESS_TLV_READ |
0576 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
0577 .info = lola_analog_vol_info,
0578 .get = lola_analog_vol_get,
0579 .put = lola_analog_vol_put,
0580 .tlv.c = lola_analog_vol_tlv,
0581 };
0582
0583 static int create_analog_mixer(struct lola *chip, int dir, char *name)
0584 {
0585 if (!chip->pin[dir].num_pins)
0586 return 0;
0587
0588 if (chip->pin[dir].num_pins != chip->pin[dir].num_analog_pins)
0589 return 0;
0590 lola_analog_mixer.name = name;
0591 lola_analog_mixer.private_value = dir;
0592 return snd_ctl_add(chip->card,
0593 snd_ctl_new1(&lola_analog_mixer, chip));
0594 }
0595
0596
0597
0598
0599 static int lola_input_src_info(struct snd_kcontrol *kcontrol,
0600 struct snd_ctl_elem_info *uinfo)
0601 {
0602 struct lola *chip = snd_kcontrol_chip(kcontrol);
0603
0604 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0605 uinfo->count = chip->pin[CAPT].num_pins;
0606 uinfo->value.integer.min = 0;
0607 uinfo->value.integer.max = 1;
0608 return 0;
0609 }
0610
0611 static int lola_input_src_get(struct snd_kcontrol *kcontrol,
0612 struct snd_ctl_elem_value *ucontrol)
0613 {
0614 struct lola *chip = snd_kcontrol_chip(kcontrol);
0615 int i;
0616
0617 for (i = 0; i < chip->pin[CAPT].num_pins; i++)
0618 ucontrol->value.integer.value[i] =
0619 !!(chip->input_src_mask & (1 << i));
0620 return 0;
0621 }
0622
0623 static int lola_input_src_put(struct snd_kcontrol *kcontrol,
0624 struct snd_ctl_elem_value *ucontrol)
0625 {
0626 struct lola *chip = snd_kcontrol_chip(kcontrol);
0627 int i;
0628 unsigned int mask;
0629
0630 mask = 0;
0631 for (i = 0; i < chip->pin[CAPT].num_pins; i++)
0632 if (ucontrol->value.integer.value[i])
0633 mask |= 1 << i;
0634 return lola_set_src_config(chip, mask, true);
0635 }
0636
0637 static const struct snd_kcontrol_new lola_input_src_mixer = {
0638 .name = "Digital SRC Capture Switch",
0639 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0640 .info = lola_input_src_info,
0641 .get = lola_input_src_get,
0642 .put = lola_input_src_put,
0643 };
0644
0645
0646
0647
0648
0649 static int create_input_src_mixer(struct lola *chip)
0650 {
0651 if (!chip->input_src_caps_mask)
0652 return 0;
0653
0654 return snd_ctl_add(chip->card,
0655 snd_ctl_new1(&lola_input_src_mixer, chip));
0656 }
0657
0658
0659
0660
0661 static int lola_src_gain_info(struct snd_kcontrol *kcontrol,
0662 struct snd_ctl_elem_info *uinfo)
0663 {
0664 unsigned int count = (kcontrol->private_value >> 8) & 0xff;
0665
0666 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0667 uinfo->count = count;
0668 uinfo->value.integer.min = 0;
0669 uinfo->value.integer.max = 409;
0670 return 0;
0671 }
0672
0673 static int lola_src_gain_get(struct snd_kcontrol *kcontrol,
0674 struct snd_ctl_elem_value *ucontrol)
0675 {
0676 struct lola *chip = snd_kcontrol_chip(kcontrol);
0677 unsigned int ofs = kcontrol->private_value & 0xff;
0678 unsigned int count = (kcontrol->private_value >> 8) & 0xff;
0679 unsigned int mask, i;
0680
0681 mask = readl(&chip->mixer.array->src_gain_enable);
0682 for (i = 0; i < count; i++) {
0683 unsigned int idx = ofs + i;
0684 unsigned short val;
0685 if (!(chip->mixer.src_mask & (1 << idx)))
0686 return -EINVAL;
0687 if (mask & (1 << idx))
0688 val = readw(&chip->mixer.array->src_gain[idx]) + 1;
0689 else
0690 val = 0;
0691 ucontrol->value.integer.value[i] = val;
0692 }
0693 return 0;
0694 }
0695
0696 static int lola_src_gain_put(struct snd_kcontrol *kcontrol,
0697 struct snd_ctl_elem_value *ucontrol)
0698 {
0699 struct lola *chip = snd_kcontrol_chip(kcontrol);
0700 unsigned int ofs = kcontrol->private_value & 0xff;
0701 unsigned int count = (kcontrol->private_value >> 8) & 0xff;
0702 int i, err;
0703
0704 for (i = 0; i < count; i++) {
0705 unsigned int idx = ofs + i;
0706 unsigned short val = ucontrol->value.integer.value[i];
0707 if (val)
0708 val--;
0709 err = lola_mixer_set_src_gain(chip, idx, val, !!val);
0710 if (err < 0)
0711 return err;
0712 }
0713 return 0;
0714 }
0715
0716
0717 static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv, -8425, 25, 1);
0718
0719 static struct snd_kcontrol_new lola_src_gain_mixer = {
0720 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0721 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
0722 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
0723 .info = lola_src_gain_info,
0724 .get = lola_src_gain_get,
0725 .put = lola_src_gain_put,
0726 .tlv.p = lola_src_gain_tlv,
0727 };
0728
0729 static int create_src_gain_mixer(struct lola *chip,
0730 int num, int ofs, char *name)
0731 {
0732 lola_src_gain_mixer.name = name;
0733 lola_src_gain_mixer.private_value = ofs + (num << 8);
0734 return snd_ctl_add(chip->card,
0735 snd_ctl_new1(&lola_src_gain_mixer, chip));
0736 }
0737
0738 #if 0
0739
0740
0741
0742 static int lola_dest_gain_info(struct snd_kcontrol *kcontrol,
0743 struct snd_ctl_elem_info *uinfo)
0744 {
0745 unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
0746
0747 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0748 uinfo->count = src_num;
0749 uinfo->value.integer.min = 0;
0750 uinfo->value.integer.max = 433;
0751 return 0;
0752 }
0753
0754 static int lola_dest_gain_get(struct snd_kcontrol *kcontrol,
0755 struct snd_ctl_elem_value *ucontrol)
0756 {
0757 struct lola *chip = snd_kcontrol_chip(kcontrol);
0758 unsigned int src_ofs = kcontrol->private_value & 0xff;
0759 unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
0760 unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff;
0761 unsigned int dst, mask, i;
0762
0763 dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs;
0764 mask = readl(&chip->mixer.array->dest_mix_gain_enable[dst]);
0765 for (i = 0; i < src_num; i++) {
0766 unsigned int src = src_ofs + i;
0767 unsigned short val;
0768 if (!(chip->mixer.src_mask & (1 << src)))
0769 return -EINVAL;
0770 if (mask & (1 << dst))
0771 val = readw(&chip->mixer.array->dest_mix_gain[dst][src]) + 1;
0772 else
0773 val = 0;
0774 ucontrol->value.integer.value[i] = val;
0775 }
0776 return 0;
0777 }
0778
0779 static int lola_dest_gain_put(struct snd_kcontrol *kcontrol,
0780 struct snd_ctl_elem_value *ucontrol)
0781 {
0782 struct lola *chip = snd_kcontrol_chip(kcontrol);
0783 unsigned int src_ofs = kcontrol->private_value & 0xff;
0784 unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
0785 unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff;
0786 unsigned int dst, mask;
0787 unsigned short gains[MAX_STREAM_COUNT];
0788 int i, num;
0789
0790 mask = 0;
0791 num = 0;
0792 for (i = 0; i < src_num; i++) {
0793 unsigned short val = ucontrol->value.integer.value[i];
0794 if (val) {
0795 gains[num++] = val - 1;
0796 mask |= 1 << i;
0797 }
0798 }
0799 mask <<= src_ofs;
0800 dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs;
0801 return lola_mixer_set_dest_gains(chip, dst, mask, gains);
0802 }
0803
0804 static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv, -8425, 25, 1);
0805
0806 static struct snd_kcontrol_new lola_dest_gain_mixer = {
0807 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0808 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
0809 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
0810 .info = lola_dest_gain_info,
0811 .get = lola_dest_gain_get,
0812 .put = lola_dest_gain_put,
0813 .tlv.p = lola_dest_gain_tlv,
0814 };
0815
0816 static int create_dest_gain_mixer(struct lola *chip,
0817 int src_num, int src_ofs,
0818 int num, int ofs, char *name)
0819 {
0820 lola_dest_gain_mixer.count = num;
0821 lola_dest_gain_mixer.name = name;
0822 lola_dest_gain_mixer.private_value =
0823 src_ofs + (src_num << 8) + (ofs << 16) + (num << 24);
0824 return snd_ctl_add(chip->card,
0825 snd_ctl_new1(&lola_dest_gain_mixer, chip));
0826 }
0827 #endif
0828
0829
0830
0831 int lola_create_mixer(struct lola *chip)
0832 {
0833 int err;
0834
0835 err = create_analog_mixer(chip, PLAY, "Analog Playback Volume");
0836 if (err < 0)
0837 return err;
0838 err = create_analog_mixer(chip, CAPT, "Analog Capture Volume");
0839 if (err < 0)
0840 return err;
0841 err = create_input_src_mixer(chip);
0842 if (err < 0)
0843 return err;
0844 err = create_src_gain_mixer(chip, chip->mixer.src_phys_ins, 0,
0845 "Digital Capture Volume");
0846 if (err < 0)
0847 return err;
0848 err = create_src_gain_mixer(chip, chip->mixer.src_stream_outs,
0849 chip->mixer.src_stream_out_ofs,
0850 "Digital Playback Volume");
0851 if (err < 0)
0852 return err;
0853 #if 0
0854
0855 err = create_dest_gain_mixer(chip,
0856 chip->mixer.src_phys_ins, 0,
0857 chip->mixer.dest_stream_ins, 0,
0858 "Line Capture Volume");
0859 if (err < 0)
0860 return err;
0861 err = create_dest_gain_mixer(chip,
0862 chip->mixer.src_stream_outs,
0863 chip->mixer.src_stream_out_ofs,
0864 chip->mixer.dest_stream_ins, 0,
0865 "Stream-Loopback Capture Volume");
0866 if (err < 0)
0867 return err;
0868 err = create_dest_gain_mixer(chip,
0869 chip->mixer.src_phys_ins, 0,
0870 chip->mixer.dest_phys_outs,
0871 chip->mixer.dest_phys_out_ofs,
0872 "Line-Loopback Playback Volume");
0873 if (err < 0)
0874 return err;
0875 err = create_dest_gain_mixer(chip,
0876 chip->mixer.src_stream_outs,
0877 chip->mixer.src_stream_out_ofs,
0878 chip->mixer.dest_phys_outs,
0879 chip->mixer.dest_phys_out_ofs,
0880 "Stream Playback Volume");
0881 if (err < 0)
0882 return err;
0883 #endif
0884 return init_mixer_values(chip);
0885 }