aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2008-01-28 02:35:20 -0500
committerJaroslav Kysela <perex@perex.cz>2008-01-31 11:30:17 -0500
commita3601560496d7b46d2d1187169824d11570ff63a (patch)
treeabcb52cdea5f118815994895b2375ad000fc4d24 /sound/pci
parent1e821dd2763c97df1a0a451e553d218cb8886cd7 (diff)
[ALSA] oxygen: add front panel controls
Add mixer controls for the front panel AC97 codec. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/oxygen/oxygen.h2
-rw-r--r--sound/pci/oxygen/oxygen_lib.c3
-rw-r--r--sound/pci/oxygen/oxygen_mixer.c117
-rw-r--r--sound/pci/oxygen/virtuoso.c4
4 files changed, 100 insertions, 26 deletions
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index 55ce2448805d..e71c53498995 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -86,7 +86,7 @@ struct oxygen_model {
86 struct snd_pcm_hw_params *params); 86 struct snd_pcm_hw_params *params);
87 void (*update_dac_volume)(struct oxygen *chip); 87 void (*update_dac_volume)(struct oxygen *chip);
88 void (*update_dac_mute)(struct oxygen *chip); 88 void (*update_dac_mute)(struct oxygen *chip);
89 void (*ac97_switch_hook)(struct oxygen *chip, 89 void (*ac97_switch_hook)(struct oxygen *chip, unsigned int codec,
90 unsigned int reg, int mute); 90 unsigned int reg, int mute);
91 size_t model_data_size; 91 size_t model_data_size;
92 u8 dac_channels; 92 u8 dac_channels;
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index de6bf41c3e96..540e56b75794 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -365,8 +365,7 @@ static void __devinit oxygen_init(struct oxygen *chip)
365 oxygen_write_ac97(chip, 1, AC97_AUX, 0x8808); 365 oxygen_write_ac97(chip, 1, AC97_AUX, 0x8808);
366 oxygen_write_ac97(chip, 1, AC97_PCM, 0x0808); 366 oxygen_write_ac97(chip, 1, AC97_PCM, 0x0808);
367 oxygen_write_ac97(chip, 1, AC97_REC_SEL, 0x0000); 367 oxygen_write_ac97(chip, 1, AC97_REC_SEL, 0x0000);
368 oxygen_write_ac97(chip, 1, AC97_REC_GAIN, 0x8000); 368 oxygen_write_ac97(chip, 1, AC97_REC_GAIN, 0x0000);
369 oxygen_ac97_clear_bits(chip, 1, AC97_REC_GAIN, 0x1c00);
370 oxygen_ac97_set_bits(chip, 1, 0x6a, 0x0040); 369 oxygen_ac97_set_bits(chip, 1, 0x6a, 0x0040);
371 } 370 }
372} 371}
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index cf34b1229b0b..a8e4623415d9 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -450,13 +450,14 @@ static int ac97_switch_get(struct snd_kcontrol *ctl,
450 struct snd_ctl_elem_value *value) 450 struct snd_ctl_elem_value *value)
451{ 451{
452 struct oxygen *chip = ctl->private_data; 452 struct oxygen *chip = ctl->private_data;
453 unsigned int codec = (ctl->private_value >> 24) & 1;
453 unsigned int index = ctl->private_value & 0xff; 454 unsigned int index = ctl->private_value & 0xff;
454 unsigned int bitnr = (ctl->private_value >> 8) & 0xff; 455 unsigned int bitnr = (ctl->private_value >> 8) & 0xff;
455 int invert = ctl->private_value & (1 << 16); 456 int invert = ctl->private_value & (1 << 16);
456 u16 reg; 457 u16 reg;
457 458
458 mutex_lock(&chip->mutex); 459 mutex_lock(&chip->mutex);
459 reg = oxygen_read_ac97(chip, 0, index); 460 reg = oxygen_read_ac97(chip, codec, index);
460 mutex_unlock(&chip->mutex); 461 mutex_unlock(&chip->mutex);
461 if (!(reg & (1 << bitnr)) ^ !invert) 462 if (!(reg & (1 << bitnr)) ^ !invert)
462 value->value.integer.value[0] = 1; 463 value->value.integer.value[0] = 1;
@@ -469,6 +470,7 @@ static int ac97_switch_put(struct snd_kcontrol *ctl,
469 struct snd_ctl_elem_value *value) 470 struct snd_ctl_elem_value *value)
470{ 471{
471 struct oxygen *chip = ctl->private_data; 472 struct oxygen *chip = ctl->private_data;
473 unsigned int codec = (ctl->private_value >> 24) & 1;
472 unsigned int index = ctl->private_value & 0xff; 474 unsigned int index = ctl->private_value & 0xff;
473 unsigned int bitnr = (ctl->private_value >> 8) & 0xff; 475 unsigned int bitnr = (ctl->private_value >> 8) & 0xff;
474 int invert = ctl->private_value & (1 << 16); 476 int invert = ctl->private_value & (1 << 16);
@@ -476,7 +478,7 @@ static int ac97_switch_put(struct snd_kcontrol *ctl,
476 int change; 478 int change;
477 479
478 mutex_lock(&chip->mutex); 480 mutex_lock(&chip->mutex);
479 oldreg = oxygen_read_ac97(chip, 0, index); 481 oldreg = oxygen_read_ac97(chip, codec, index);
480 newreg = oldreg; 482 newreg = oldreg;
481 if (!value->value.integer.value[0] ^ !invert) 483 if (!value->value.integer.value[0] ^ !invert)
482 newreg |= 1 << bitnr; 484 newreg |= 1 << bitnr;
@@ -484,9 +486,9 @@ static int ac97_switch_put(struct snd_kcontrol *ctl,
484 newreg &= ~(1 << bitnr); 486 newreg &= ~(1 << bitnr);
485 change = newreg != oldreg; 487 change = newreg != oldreg;
486 if (change) { 488 if (change) {
487 oxygen_write_ac97(chip, 0, index, newreg); 489 oxygen_write_ac97(chip, codec, index, newreg);
488 if (bitnr == 15 && chip->model->ac97_switch_hook) 490 if (bitnr == 15 && chip->model->ac97_switch_hook)
489 chip->model->ac97_switch_hook(chip, index, 491 chip->model->ac97_switch_hook(chip, codec, index,
490 newreg & 0x8000); 492 newreg & 0x8000);
491 } 493 }
492 mutex_unlock(&chip->mutex); 494 mutex_unlock(&chip->mutex);
@@ -507,11 +509,12 @@ static int ac97_volume_get(struct snd_kcontrol *ctl,
507 struct snd_ctl_elem_value *value) 509 struct snd_ctl_elem_value *value)
508{ 510{
509 struct oxygen *chip = ctl->private_data; 511 struct oxygen *chip = ctl->private_data;
510 unsigned int index = ctl->private_value; 512 unsigned int codec = (ctl->private_value >> 24) & 1;
513 unsigned int index = ctl->private_value & 0xff;
511 u16 reg; 514 u16 reg;
512 515
513 mutex_lock(&chip->mutex); 516 mutex_lock(&chip->mutex);
514 reg = oxygen_read_ac97(chip, 0, index); 517 reg = oxygen_read_ac97(chip, codec, index);
515 mutex_unlock(&chip->mutex); 518 mutex_unlock(&chip->mutex);
516 value->value.integer.value[0] = 31 - (reg & 0x1f); 519 value->value.integer.value[0] = 31 - (reg & 0x1f);
517 value->value.integer.value[1] = 31 - ((reg >> 8) & 0x1f); 520 value->value.integer.value[1] = 31 - ((reg >> 8) & 0x1f);
@@ -522,12 +525,13 @@ static int ac97_volume_put(struct snd_kcontrol *ctl,
522 struct snd_ctl_elem_value *value) 525 struct snd_ctl_elem_value *value)
523{ 526{
524 struct oxygen *chip = ctl->private_data; 527 struct oxygen *chip = ctl->private_data;
525 unsigned int index = ctl->private_value; 528 unsigned int codec = (ctl->private_value >> 24) & 1;
529 unsigned int index = ctl->private_value & 0xff;
526 u16 oldreg, newreg; 530 u16 oldreg, newreg;
527 int change; 531 int change;
528 532
529 mutex_lock(&chip->mutex); 533 mutex_lock(&chip->mutex);
530 oldreg = oxygen_read_ac97(chip, 0, index); 534 oldreg = oxygen_read_ac97(chip, codec, index);
531 newreg = oldreg; 535 newreg = oldreg;
532 newreg = (newreg & ~0x1f) | 536 newreg = (newreg & ~0x1f) |
533 (31 - (value->value.integer.value[0] & 0x1f)); 537 (31 - (value->value.integer.value[0] & 0x1f));
@@ -535,30 +539,77 @@ static int ac97_volume_put(struct snd_kcontrol *ctl,
535 ((31 - (value->value.integer.value[0] & 0x1f)) << 8); 539 ((31 - (value->value.integer.value[0] & 0x1f)) << 8);
536 change = newreg != oldreg; 540 change = newreg != oldreg;
537 if (change) 541 if (change)
538 oxygen_write_ac97(chip, 0, index, newreg); 542 oxygen_write_ac97(chip, codec, index, newreg);
539 mutex_unlock(&chip->mutex); 543 mutex_unlock(&chip->mutex);
540 return change; 544 return change;
541} 545}
542 546
543#define AC97_SWITCH(xname, index, bitnr, invert) { \ 547static int ac97_fp_rec_volume_info(struct snd_kcontrol *ctl,
548 struct snd_ctl_elem_info *info)
549{
550 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
551 info->count = 2;
552 info->value.integer.min = 0;
553 info->value.integer.max = 7;
554 return 0;
555}
556
557static int ac97_fp_rec_volume_get(struct snd_kcontrol *ctl,
558 struct snd_ctl_elem_value *value)
559{
560 struct oxygen *chip = ctl->private_data;
561 u16 reg;
562
563 mutex_lock(&chip->mutex);
564 reg = oxygen_read_ac97(chip, 1, AC97_REC_GAIN);
565 mutex_unlock(&chip->mutex);
566 value->value.integer.value[0] = reg & 7;
567 value->value.integer.value[1] = (reg >> 8) & 7;
568 return 0;
569}
570
571static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl,
572 struct snd_ctl_elem_value *value)
573{
574 struct oxygen *chip = ctl->private_data;
575 u16 oldreg, newreg;
576 int change;
577
578 mutex_lock(&chip->mutex);
579 oldreg = oxygen_read_ac97(chip, 1, AC97_REC_GAIN);
580 newreg = oldreg & ~0x0707;
581 newreg = newreg | (value->value.integer.value[0] & 7);
582 newreg = newreg | ((value->value.integer.value[0] & 7) << 8);
583 change = newreg != oldreg;
584 if (change)
585 oxygen_write_ac97(chip, 1, AC97_REC_GAIN, newreg);
586 mutex_unlock(&chip->mutex);
587 return change;
588}
589
590#define AC97_SWITCH(xname, codec, index, bitnr, invert) { \
544 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 591 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
545 .name = xname, \ 592 .name = xname, \
546 .info = snd_ctl_boolean_mono_info, \ 593 .info = snd_ctl_boolean_mono_info, \
547 .get = ac97_switch_get, \ 594 .get = ac97_switch_get, \
548 .put = ac97_switch_put, \ 595 .put = ac97_switch_put, \
549 .private_value = ((invert) << 16) | ((bitnr) << 8) | (index), \ 596 .private_value = ((codec) << 24) | ((invert) << 16) | \
597 ((bitnr) << 8) | (index), \
550 } 598 }
551#define AC97_VOLUME(xname, index) { \ 599#define AC97_VOLUME(xname, codec, index) { \
552 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 600 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
553 .name = xname, \ 601 .name = xname, \
602 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
603 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
554 .info = ac97_volume_info, \ 604 .info = ac97_volume_info, \
555 .get = ac97_volume_get, \ 605 .get = ac97_volume_get, \
556 .put = ac97_volume_put, \ 606 .put = ac97_volume_put, \
557 .tlv = { .p = ac97_db_scale, }, \ 607 .tlv = { .p = ac97_db_scale, }, \
558 .private_value = (index), \ 608 .private_value = ((codec) << 24) | (index), \
559 } 609 }
560 610
561static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0); 611static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0);
612static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0);
562 613
563static const struct snd_kcontrol_new controls[] = { 614static const struct snd_kcontrol_new controls[] = {
564 { 615 {
@@ -642,15 +693,31 @@ static const struct snd_kcontrol_new controls[] = {
642}; 693};
643 694
644static const struct snd_kcontrol_new ac97_controls[] = { 695static const struct snd_kcontrol_new ac97_controls[] = {
645 AC97_VOLUME("Mic Capture Volume", AC97_MIC), 696 AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC),
646 AC97_SWITCH("Mic Capture Switch", AC97_MIC, 15, 1), 697 AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1),
647 AC97_SWITCH("Mic Boost (+20dB)", AC97_MIC, 6, 0), 698 AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0),
648 AC97_VOLUME("Line Capture Volume", AC97_LINE), 699 AC97_VOLUME("Line Capture Volume", 0, AC97_LINE),
649 AC97_SWITCH("Line Capture Switch", AC97_LINE, 15, 1), 700 AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1),
650 AC97_VOLUME("CD Capture Volume", AC97_CD), 701 AC97_VOLUME("CD Capture Volume", 0, AC97_CD),
651 AC97_SWITCH("CD Capture Switch", AC97_CD, 15, 1), 702 AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1),
652 AC97_VOLUME("Aux Capture Volume", AC97_AUX), 703 AC97_VOLUME("Aux Capture Volume", 0, AC97_AUX),
653 AC97_SWITCH("Aux Capture Switch", AC97_AUX, 15, 1), 704 AC97_SWITCH("Aux Capture Switch", 0, AC97_AUX, 15, 1),
705};
706
707static const struct snd_kcontrol_new ac97_fp_controls[] = {
708 AC97_VOLUME("Front Panel Playback Volume", 1, AC97_HEADPHONE),
709 AC97_SWITCH("Front Panel Playback Switch", 1, AC97_HEADPHONE, 15, 1),
710 {
711 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
712 .name = "Front Panel Capture Volume",
713 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
714 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
715 .info = ac97_fp_rec_volume_info,
716 .get = ac97_fp_rec_volume_get,
717 .put = ac97_fp_rec_volume_put,
718 .tlv = { .p = ac97_rec_db_scale, },
719 },
720 AC97_SWITCH("Front Panel Capture Switch", 1, AC97_REC_GAIN, 15, 1),
654}; 721};
655 722
656static void oxygen_any_ctl_free(struct snd_kcontrol *ctl) 723static void oxygen_any_ctl_free(struct snd_kcontrol *ctl)
@@ -717,5 +784,11 @@ int oxygen_mixer_init(struct oxygen *chip)
717 if (err < 0) 784 if (err < 0)
718 return err; 785 return err;
719 } 786 }
787 if (chip->has_ac97_1) {
788 err = add_controls(chip, ac97_fp_controls,
789 ARRAY_SIZE(ac97_fp_controls));
790 if (err < 0)
791 return err;
792 }
720 return chip->model->mixer_init ? chip->model->mixer_init(chip) : 0; 793 return chip->model->mixer_init ? chip->model->mixer_init(chip) : 0;
721} 794}
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 23bfab448844..2e1a6996fa86 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -247,9 +247,11 @@ static void mute_ac97_ctl(struct oxygen *chip, unsigned int control)
247 } 247 }
248} 248}
249 249
250static void xonar_ac97_switch_hook(struct oxygen *chip, 250static void xonar_ac97_switch_hook(struct oxygen *chip, unsigned int codec,
251 unsigned int reg, int mute) 251 unsigned int reg, int mute)
252{ 252{
253 if (codec != 0)
254 return;
253 /* line-in is exclusive */ 255 /* line-in is exclusive */
254 switch (reg) { 256 switch (reg) {
255 case AC97_LINE: 257 case AC97_LINE: