diff options
author | John L. Utz III <john.utz@dmx.com> | 2008-08-28 10:04:40 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-08-29 04:06:18 -0400 |
commit | 9e285e1a58bcf957cde9c0c559a1b9b0f708bb2f (patch) | |
tree | ec48890aaa0e07a7ece119153b2c5fbbcfe29897 /sound/pci/ac97 | |
parent | ac68c16a44df6dd9edfde31917ae304526f60398 (diff) |
ALSA: ac97 - vt1618 7.1 Audio Support
1. Implement 7.1 Output for vt1618 codec.
2. Fix typos in comments from my previous 1617a patch.
Signed-off-by: John L. Utz III <john.utz@dmx.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/pci/ac97')
-rw-r--r-- | sound/pci/ac97/ac97_codec.c | 2 | ||||
-rw-r--r-- | sound/pci/ac97/ac97_patch.c | 198 |
2 files changed, 197 insertions, 3 deletions
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index d0023e99bdf9..6704acbca8c0 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
@@ -168,7 +168,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { | |||
168 | { 0x54584e20, 0xffffffff, "TLC320AD9xC", NULL, NULL }, | 168 | { 0x54584e20, 0xffffffff, "TLC320AD9xC", NULL, NULL }, |
169 | { 0x56494161, 0xffffffff, "VIA1612A", NULL, NULL }, // modified ICE1232 with S/PDIF | 169 | { 0x56494161, 0xffffffff, "VIA1612A", NULL, NULL }, // modified ICE1232 with S/PDIF |
170 | { 0x56494170, 0xffffffff, "VIA1617A", patch_vt1617a, NULL }, // modified VT1616 with S/PDIF | 170 | { 0x56494170, 0xffffffff, "VIA1617A", patch_vt1617a, NULL }, // modified VT1616 with S/PDIF |
171 | { 0x56494182, 0xffffffff, "VIA1618", NULL, NULL }, | 171 | { 0x56494182, 0xffffffff, "VIA1618", patch_vt1618, NULL }, |
172 | { 0x57454301, 0xffffffff, "W83971D", NULL, NULL }, | 172 | { 0x57454301, 0xffffffff, "W83971D", NULL, NULL }, |
173 | { 0x574d4c00, 0xffffffff, "WM9701,WM9701A", NULL, NULL }, | 173 | { 0x574d4c00, 0xffffffff, "WM9701,WM9701A", NULL, NULL }, |
174 | { 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL}, | 174 | { 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL}, |
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index bb028f8f9a2e..d0cab1d38789 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -3465,7 +3465,7 @@ static int patch_vt1616(struct snd_ac97 * ac97) | |||
3465 | 3465 | ||
3466 | /* | 3466 | /* |
3467 | * unfortunately, the vt1617a stashes the twiddlers required for | 3467 | * unfortunately, the vt1617a stashes the twiddlers required for |
3468 | * nooding the i/o jacks on 2 different regs. * thameans that we cant | 3468 | * noodling the i/o jacks on 2 different regs. that means that we can't |
3469 | * use the easy way provided by AC97_ENUM_DOUBLE() we have to write | 3469 | * use the easy way provided by AC97_ENUM_DOUBLE() we have to write |
3470 | * are own funcs. | 3470 | * are own funcs. |
3471 | * | 3471 | * |
@@ -3498,7 +3498,7 @@ static int snd_ac97_vt1617a_smart51_get(struct snd_kcontrol *kcontrol, | |||
3498 | 3498 | ||
3499 | pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */ | 3499 | pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */ |
3500 | 3500 | ||
3501 | /* grab our desirec bits, then mash them together in a manner | 3501 | /* grab our desired bits, then mash them together in a manner |
3502 | * consistent with Table 6 on page 17 in the 1617a docs */ | 3502 | * consistent with Table 6 on page 17 in the 1617a docs */ |
3503 | 3503 | ||
3504 | usSM51 = snd_ac97_read(pac97, 0x7a) >> 14; | 3504 | usSM51 = snd_ac97_read(pac97, 0x7a) >> 14; |
@@ -3576,6 +3576,200 @@ int patch_vt1617a(struct snd_ac97 * ac97) | |||
3576 | return err; | 3576 | return err; |
3577 | } | 3577 | } |
3578 | 3578 | ||
3579 | /* VIA VT1618 8 CHANNEL AC97 CODEC | ||
3580 | * | ||
3581 | * VIA implements 'Smart 5.1' completely differently on the 1618 than | ||
3582 | * it does on the 1617a. awesome! They seem to have sourced this | ||
3583 | * particular revision of the technology from somebody else, it's | ||
3584 | * called Universal Audio Jack and it shows up on some other folk's chips | ||
3585 | * as well. | ||
3586 | * | ||
3587 | * ordering in this list reflects vt1618 docs for Reg 60h and | ||
3588 | * the block diagram, DACs are as follows: | ||
3589 | * | ||
3590 | * OUT_O -> Front, | ||
3591 | * OUT_1 -> Surround, | ||
3592 | * OUT_2 -> C/LFE | ||
3593 | * | ||
3594 | * Unlike the 1617a, each OUT has a consistent set of mappings | ||
3595 | * for all bitpatterns other than 00: | ||
3596 | * | ||
3597 | * 01 Unmixed Output | ||
3598 | * 10 Line In | ||
3599 | * 11 Mic In | ||
3600 | * | ||
3601 | * Special Case of 00: | ||
3602 | * | ||
3603 | * OUT_0 Mixed Output | ||
3604 | * OUT_1 Reserved | ||
3605 | * OUT_2 Reserved | ||
3606 | * | ||
3607 | * I have no idea what the hell Reserved does, but on an MSI | ||
3608 | * CN700T, i have to set it to get 5.1 output - YMMV, bad | ||
3609 | * shit may happen. | ||
3610 | * | ||
3611 | * If other chips use Universal Audio Jack, then this code might be applicable | ||
3612 | * to them. | ||
3613 | */ | ||
3614 | |||
3615 | struct vt1618_uaj_item { | ||
3616 | unsigned short mask; | ||
3617 | unsigned short shift; | ||
3618 | const char *items[4]; | ||
3619 | }; | ||
3620 | |||
3621 | /* This list reflects the vt1618 docs for Vendor Defined Register 0x60. */ | ||
3622 | |||
3623 | static struct vt1618_uaj_item vt1618_uaj[3] = { | ||
3624 | { | ||
3625 | /* speaker jack */ | ||
3626 | .mask = 0x03, | ||
3627 | .shift = 0, | ||
3628 | .items = { | ||
3629 | "Speaker Out", "DAC Unmixed Out", "Line In", "Mic In" | ||
3630 | } | ||
3631 | }, | ||
3632 | { | ||
3633 | /* line jack */ | ||
3634 | .mask = 0x0c, | ||
3635 | .shift = 2, | ||
3636 | .items = { | ||
3637 | "Surround Out", "DAC Unmixed Out", "Line In", "Mic In" | ||
3638 | } | ||
3639 | }, | ||
3640 | { | ||
3641 | /* mic jack */ | ||
3642 | .mask = 0x30, | ||
3643 | .shift = 4, | ||
3644 | .items = { | ||
3645 | "Center LFE Out", "DAC Unmixed Out", "Line In", "Mic In" | ||
3646 | }, | ||
3647 | }, | ||
3648 | }; | ||
3649 | |||
3650 | static int snd_ac97_vt1618_UAJ_info(struct snd_kcontrol *kcontrol, | ||
3651 | struct snd_ctl_elem_info *uinfo) | ||
3652 | { | ||
3653 | return ac97_enum_text_info(kcontrol, uinfo, | ||
3654 | vt1618_uaj[kcontrol->private_value].items, | ||
3655 | 4); | ||
3656 | } | ||
3657 | |||
3658 | /* All of the vt1618 Universal Audio Jack twiddlers are on | ||
3659 | * Vendor Defined Register 0x60, page 0. The bits, and thus | ||
3660 | * the mask, are the only thing that changes | ||
3661 | */ | ||
3662 | static int snd_ac97_vt1618_UAJ_get(struct snd_kcontrol *kcontrol, | ||
3663 | struct snd_ctl_elem_value *ucontrol) | ||
3664 | { | ||
3665 | unsigned short datpag, uaj; | ||
3666 | struct snd_ac97 *pac97 = snd_kcontrol_chip(kcontrol); | ||
3667 | |||
3668 | mutex_lock(&pac97->page_mutex); | ||
3669 | |||
3670 | datpag = snd_ac97_read(pac97, AC97_INT_PAGING) & AC97_PAGE_MASK; | ||
3671 | snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, 0); | ||
3672 | |||
3673 | uaj = snd_ac97_read(pac97, 0x60) & | ||
3674 | vt1618_uaj[kcontrol->private_value].mask; | ||
3675 | |||
3676 | snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, datpag); | ||
3677 | mutex_unlock(&pac97->page_mutex); | ||
3678 | |||
3679 | ucontrol->value.enumerated.item[0] = uaj >> | ||
3680 | vt1618_uaj[kcontrol->private_value].shift; | ||
3681 | |||
3682 | return 0; | ||
3683 | } | ||
3684 | |||
3685 | static int snd_ac97_vt1618_UAJ_put(struct snd_kcontrol *kcontrol, | ||
3686 | struct snd_ctl_elem_value *ucontrol) | ||
3687 | { | ||
3688 | return ac97_update_bits_page(snd_kcontrol_chip(kcontrol), 0x60, | ||
3689 | vt1618_uaj[kcontrol->private_value].mask, | ||
3690 | ucontrol->value.enumerated.item[0]<< | ||
3691 | vt1618_uaj[kcontrol->private_value].shift, | ||
3692 | 0); | ||
3693 | } | ||
3694 | |||
3695 | /* config aux in jack - not found on 3 jack motherboards or soundcards */ | ||
3696 | |||
3697 | static int snd_ac97_vt1618_aux_info(struct snd_kcontrol *kcontrol, | ||
3698 | struct snd_ctl_elem_info *uinfo) | ||
3699 | { | ||
3700 | static const char *txt_aux[] = {"Aux In", "Back Surr Out"}; | ||
3701 | |||
3702 | return ac97_enum_text_info(kcontrol, uinfo, txt_aux, 2); | ||
3703 | } | ||
3704 | |||
3705 | static int snd_ac97_vt1618_aux_get(struct snd_kcontrol *kcontrol, | ||
3706 | struct snd_ctl_elem_value *ucontrol) | ||
3707 | { | ||
3708 | ucontrol->value.enumerated.item[0] = | ||
3709 | (snd_ac97_read(snd_kcontrol_chip(kcontrol), 0x5c) & 0x0008)>>3; | ||
3710 | return 0; | ||
3711 | } | ||
3712 | |||
3713 | static int snd_ac97_vt1618_aux_put(struct snd_kcontrol *kcontrol, | ||
3714 | struct snd_ctl_elem_value *ucontrol) | ||
3715 | { | ||
3716 | /* toggle surround rear dac power */ | ||
3717 | |||
3718 | snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x5c, 0x0008, | ||
3719 | ucontrol->value.enumerated.item[0] << 3); | ||
3720 | |||
3721 | /* toggle aux in surround rear out jack */ | ||
3722 | |||
3723 | return snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x76, 0x0008, | ||
3724 | ucontrol->value.enumerated.item[0] << 3); | ||
3725 | } | ||
3726 | |||
3727 | static const struct snd_kcontrol_new snd_ac97_controls_vt1618[] = { | ||
3728 | AC97_SINGLE("Exchange Center/LFE", 0x5a, 8, 1, 0), | ||
3729 | AC97_SINGLE("DC Offset", 0x5a, 10, 1, 0), | ||
3730 | AC97_SINGLE("Soft Mute", 0x5c, 0, 1, 1), | ||
3731 | AC97_SINGLE("Headphone Amp", 0x5c, 5, 1, 1), | ||
3732 | AC97_DOUBLE("Back Surr Volume", 0x5e, 8, 0, 31, 1), | ||
3733 | AC97_SINGLE("Back Surr Switch", 0x5e, 15, 1, 1), | ||
3734 | { | ||
3735 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3736 | .name = "Speaker Jack Mode", | ||
3737 | .info = snd_ac97_vt1618_UAJ_info, | ||
3738 | .get = snd_ac97_vt1618_UAJ_get, | ||
3739 | .put = snd_ac97_vt1618_UAJ_put, | ||
3740 | .private_value = 0 | ||
3741 | }, | ||
3742 | { | ||
3743 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3744 | .name = "Line Jack Mode", | ||
3745 | .info = snd_ac97_vt1618_UAJ_info, | ||
3746 | .get = snd_ac97_vt1618_UAJ_get, | ||
3747 | .put = snd_ac97_vt1618_UAJ_put, | ||
3748 | .private_value = 1 | ||
3749 | }, | ||
3750 | { | ||
3751 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3752 | .name = "Mic Jack Mode", | ||
3753 | .info = snd_ac97_vt1618_UAJ_info, | ||
3754 | .get = snd_ac97_vt1618_UAJ_get, | ||
3755 | .put = snd_ac97_vt1618_UAJ_put, | ||
3756 | .private_value = 2 | ||
3757 | }, | ||
3758 | { | ||
3759 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3760 | .name = "Aux Jack Mode", | ||
3761 | .info = snd_ac97_vt1618_aux_info, | ||
3762 | .get = snd_ac97_vt1618_aux_get, | ||
3763 | .put = snd_ac97_vt1618_aux_put, | ||
3764 | } | ||
3765 | }; | ||
3766 | |||
3767 | int patch_vt1618(struct snd_ac97 *ac97) | ||
3768 | { | ||
3769 | return patch_build_controls(ac97, snd_ac97_controls_vt1618, | ||
3770 | ARRAY_SIZE(snd_ac97_controls_vt1618)); | ||
3771 | } | ||
3772 | |||
3579 | /* | 3773 | /* |
3580 | */ | 3774 | */ |
3581 | static void it2646_update_jacks(struct snd_ac97 *ac97) | 3775 | static void it2646_update_jacks(struct snd_ac97 *ac97) |