diff options
Diffstat (limited to 'sound/pci/ac97/ac97_patch.c')
-rw-r--r-- | sound/pci/ac97/ac97_patch.c | 208 |
1 files changed, 205 insertions, 3 deletions
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index f4fbc795ee81..6ce3cbe98a6a 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -2560,6 +2560,14 @@ static int patch_ad1986(struct snd_ac97 * ac97) | |||
2560 | return 0; | 2560 | return 0; |
2561 | } | 2561 | } |
2562 | 2562 | ||
2563 | /* | ||
2564 | * realtek ALC203: use mono-out for pin 37 | ||
2565 | */ | ||
2566 | static int patch_alc203(struct snd_ac97 *ac97) | ||
2567 | { | ||
2568 | snd_ac97_update_bits(ac97, 0x7a, 0x400, 0x400); | ||
2569 | return 0; | ||
2570 | } | ||
2563 | 2571 | ||
2564 | /* | 2572 | /* |
2565 | * realtek ALC65x/850 codecs | 2573 | * realtek ALC65x/850 codecs |
@@ -3457,7 +3465,7 @@ static int patch_vt1616(struct snd_ac97 * ac97) | |||
3457 | 3465 | ||
3458 | /* | 3466 | /* |
3459 | * unfortunately, the vt1617a stashes the twiddlers required for | 3467 | * unfortunately, the vt1617a stashes the twiddlers required for |
3460 | * 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 |
3461 | * 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 |
3462 | * are own funcs. | 3470 | * are own funcs. |
3463 | * | 3471 | * |
@@ -3490,7 +3498,7 @@ static int snd_ac97_vt1617a_smart51_get(struct snd_kcontrol *kcontrol, | |||
3490 | 3498 | ||
3491 | pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */ | 3499 | pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */ |
3492 | 3500 | ||
3493 | /* grab our desirec bits, then mash them together in a manner | 3501 | /* grab our desired bits, then mash them together in a manner |
3494 | * consistent with Table 6 on page 17 in the 1617a docs */ | 3502 | * consistent with Table 6 on page 17 in the 1617a docs */ |
3495 | 3503 | ||
3496 | usSM51 = snd_ac97_read(pac97, 0x7a) >> 14; | 3504 | usSM51 = snd_ac97_read(pac97, 0x7a) >> 14; |
@@ -3540,7 +3548,7 @@ static const struct snd_kcontrol_new snd_ac97_controls_vt1617a[] = { | |||
3540 | }, | 3548 | }, |
3541 | }; | 3549 | }; |
3542 | 3550 | ||
3543 | int patch_vt1617a(struct snd_ac97 * ac97) | 3551 | static int patch_vt1617a(struct snd_ac97 * ac97) |
3544 | { | 3552 | { |
3545 | int err = 0; | 3553 | int err = 0; |
3546 | int val; | 3554 | int val; |
@@ -3568,6 +3576,200 @@ int patch_vt1617a(struct snd_ac97 * ac97) | |||
3568 | return err; | 3576 | return err; |
3569 | } | 3577 | } |
3570 | 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 | static 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 | |||
3571 | /* | 3773 | /* |
3572 | */ | 3774 | */ |
3573 | static void it2646_update_jacks(struct snd_ac97 *ac97) | 3775 | static void it2646_update_jacks(struct snd_ac97 *ac97) |