diff options
Diffstat (limited to 'sound/pci/ac97/ac97_patch.c')
-rw-r--r-- | sound/pci/ac97/ac97_patch.c | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 1292dcee072d..0746e9ccc20b 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -669,6 +669,7 @@ AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1), | |||
669 | AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1), | 669 | AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1), |
670 | AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0), | 670 | AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0), |
671 | 671 | ||
672 | AC97_SINGLE("Master Left Inv Switch", AC97_MASTER, 6, 1, 0), | ||
672 | AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0), | 673 | AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0), |
673 | AC97_SINGLE("Headphone ZC Switch", AC97_HEADPHONE, 7, 1, 0), | 674 | AC97_SINGLE("Headphone ZC Switch", AC97_HEADPHONE, 7, 1, 0), |
674 | AC97_SINGLE("Mono ZC Switch", AC97_MASTER_MONO, 7, 1, 0), | 675 | AC97_SINGLE("Mono ZC Switch", AC97_MASTER_MONO, 7, 1, 0), |
@@ -3352,8 +3353,66 @@ AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0), | |||
3352 | AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0), | 3353 | AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0), |
3353 | }; | 3354 | }; |
3354 | 3355 | ||
3356 | static const char *slave_vols_vt1616[] = { | ||
3357 | "Front Playback Volume", | ||
3358 | "Surround Playback Volume", | ||
3359 | "Center Playback Volume", | ||
3360 | "LFE Playback Volume", | ||
3361 | NULL | ||
3362 | }; | ||
3363 | |||
3364 | static const char *slave_sws_vt1616[] = { | ||
3365 | "Front Playback Switch", | ||
3366 | "Surround Playback Switch", | ||
3367 | "Center Playback Switch", | ||
3368 | "LFE Playback Switch", | ||
3369 | NULL | ||
3370 | }; | ||
3371 | |||
3372 | /* find a mixer control element with the given name */ | ||
3373 | static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97, | ||
3374 | const char *name) | ||
3375 | { | ||
3376 | struct snd_ctl_elem_id id; | ||
3377 | memset(&id, 0, sizeof(id)); | ||
3378 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
3379 | strcpy(id.name, name); | ||
3380 | return snd_ctl_find_id(ac97->bus->card, &id); | ||
3381 | } | ||
3382 | |||
3383 | /* create a virtual master control and add slaves */ | ||
3384 | int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name, | ||
3385 | const unsigned int *tlv, const char **slaves) | ||
3386 | { | ||
3387 | struct snd_kcontrol *kctl; | ||
3388 | const char **s; | ||
3389 | int err; | ||
3390 | |||
3391 | kctl = snd_ctl_make_virtual_master(name, tlv); | ||
3392 | if (!kctl) | ||
3393 | return -ENOMEM; | ||
3394 | err = snd_ctl_add(ac97->bus->card, kctl); | ||
3395 | if (err < 0) | ||
3396 | return err; | ||
3397 | |||
3398 | for (s = slaves; *s; s++) { | ||
3399 | struct snd_kcontrol *sctl; | ||
3400 | |||
3401 | sctl = snd_ac97_find_mixer_ctl(ac97, *s); | ||
3402 | if (!sctl) { | ||
3403 | snd_printdd("Cannot find slave %s, skipped\n", *s); | ||
3404 | continue; | ||
3405 | } | ||
3406 | err = snd_ctl_add_slave(kctl, sctl); | ||
3407 | if (err < 0) | ||
3408 | return err; | ||
3409 | } | ||
3410 | return 0; | ||
3411 | } | ||
3412 | |||
3355 | static int patch_vt1616_specific(struct snd_ac97 * ac97) | 3413 | static int patch_vt1616_specific(struct snd_ac97 * ac97) |
3356 | { | 3414 | { |
3415 | struct snd_kcontrol *kctl; | ||
3357 | int err; | 3416 | int err; |
3358 | 3417 | ||
3359 | if (snd_ac97_try_bit(ac97, 0x5a, 9)) | 3418 | if (snd_ac97_try_bit(ac97, 0x5a, 9)) |
@@ -3361,6 +3420,24 @@ static int patch_vt1616_specific(struct snd_ac97 * ac97) | |||
3361 | return err; | 3420 | return err; |
3362 | if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1)) < 0) | 3421 | if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1)) < 0) |
3363 | return err; | 3422 | return err; |
3423 | |||
3424 | /* There is already a misnamed master switch. Rename it. */ | ||
3425 | kctl = snd_ac97_find_mixer_ctl(ac97, "Master Playback Volume"); | ||
3426 | if (!kctl) | ||
3427 | return -EINVAL; | ||
3428 | |||
3429 | snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Front Playback"); | ||
3430 | |||
3431 | err = snd_ac97_add_vmaster(ac97, "Master Playback Volume", | ||
3432 | kctl->tlv.p, slave_vols_vt1616); | ||
3433 | if (err < 0) | ||
3434 | return err; | ||
3435 | |||
3436 | err = snd_ac97_add_vmaster(ac97, "Master Playback Switch", | ||
3437 | NULL, slave_sws_vt1616); | ||
3438 | if (err < 0) | ||
3439 | return err; | ||
3440 | |||
3364 | return 0; | 3441 | return 0; |
3365 | } | 3442 | } |
3366 | 3443 | ||
@@ -3633,7 +3710,7 @@ static int patch_ucb1400(struct snd_ac97 * ac97) | |||
3633 | { | 3710 | { |
3634 | ac97->build_ops = &patch_ucb1400_ops; | 3711 | ac97->build_ops = &patch_ucb1400_ops; |
3635 | /* enable headphone driver and smart low power mode by default */ | 3712 | /* enable headphone driver and smart low power mode by default */ |
3636 | snd_ac97_write(ac97, 0x6a, 0x0050); | 3713 | snd_ac97_write_cache(ac97, 0x6a, 0x0050); |
3637 | snd_ac97_write(ac97, 0x6c, 0x0030); | 3714 | snd_ac97_write_cache(ac97, 0x6c, 0x0030); |
3638 | return 0; | 3715 | return 0; |
3639 | } | 3716 | } |