diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/ac97/ac97_patch.c | 103 |
1 files changed, 99 insertions, 4 deletions
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 43455fc07b77..3eac0f86266c 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -3277,16 +3277,111 @@ static int patch_vt1616(struct snd_ac97 * ac97) | |||
3277 | /* | 3277 | /* |
3278 | * VT1617A codec | 3278 | * VT1617A codec |
3279 | */ | 3279 | */ |
3280 | static int patch_vt1617a(struct snd_ac97 * ac97) | 3280 | |
3281 | /* | ||
3282 | * unfortunately, the vt1617a stashes the twiddlers required for | ||
3283 | * nooding the i/o jacks on 2 different regs. * thameans that we cant | ||
3284 | * use the easy way provided by AC97_ENUM_DOUBLE() we have to write | ||
3285 | * are own funcs. | ||
3286 | * | ||
3287 | * NB: this is absolutely and utterly different from the vt1618. dunno | ||
3288 | * about the 1616. | ||
3289 | */ | ||
3290 | |||
3291 | /* copied from ac97_surround_jack_mode_info() */ | ||
3292 | static int snd_ac97_vt1617a_smart51_info(struct snd_kcontrol *kcontrol, | ||
3293 | struct snd_ctl_elem_info *uinfo) | ||
3281 | { | 3294 | { |
3282 | /* bring analog power consumption to normal, like WinXP driver | 3295 | /* ordering in this list reflects vt1617a docs for Reg 20 and |
3283 | * for EPIA SP | 3296 | * 7a and Table 6 that lays out the matrix NB WRT Table6: SM51 |
3297 | * is SM51EN *AND* it's Bit14, not Bit15 so the table is very | ||
3298 | * counter-intuitive */ | ||
3299 | |||
3300 | static const char* texts[] = { "LineIn Mic1", "LineIn Mic1 Mic3", | ||
3301 | "Surr LFE/C Mic3", "LineIn LFE/C Mic3", | ||
3302 | "LineIn Mic2", "LineIn Mic2 Mic1", | ||
3303 | "Surr LFE Mic1", "Surr LFE Mic1 Mic2"}; | ||
3304 | return ac97_enum_text_info(kcontrol, uinfo, texts, 8); | ||
3305 | } | ||
3306 | |||
3307 | static int snd_ac97_vt1617a_smart51_get(struct snd_kcontrol *kcontrol, | ||
3308 | struct snd_ctl_elem_value *ucontrol) | ||
3309 | { | ||
3310 | ushort usSM51, usMS; | ||
3311 | |||
3312 | struct snd_ac97 *pac97; | ||
3313 | |||
3314 | pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */ | ||
3315 | |||
3316 | /* grab our desirec bits, then mash them together in a manner | ||
3317 | * consistent with Table 6 on page 17 in the 1617a docs */ | ||
3318 | |||
3319 | usSM51 = snd_ac97_read(pac97, 0x7a) >> 14; | ||
3320 | usMS = snd_ac97_read(pac97, 0x20) >> 8; | ||
3321 | |||
3322 | ucontrol->value.enumerated.item[0] = (usSM51 << 1) + usMS; | ||
3323 | |||
3324 | return 0; | ||
3325 | } | ||
3326 | |||
3327 | static int snd_ac97_vt1617a_smart51_put(struct snd_kcontrol *kcontrol, | ||
3328 | struct snd_ctl_elem_value *ucontrol) | ||
3329 | { | ||
3330 | ushort usSM51, usMS, usReg; | ||
3331 | |||
3332 | struct snd_ac97 *pac97; | ||
3333 | |||
3334 | pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */ | ||
3335 | |||
3336 | usSM51 = ucontrol->value.enumerated.item[0] >> 1; | ||
3337 | usMS = ucontrol->value.enumerated.item[0] & 1; | ||
3338 | |||
3339 | /* push our values into the register - consider that things will be left | ||
3340 | * in a funky state if the write fails */ | ||
3341 | |||
3342 | usReg = snd_ac97_read(pac97, 0x7a); | ||
3343 | snd_ac97_write_cache(pac97, 0x7a, (usReg & 0x3FFF) + (usSM51 << 14)); | ||
3344 | usReg = snd_ac97_read(pac97, 0x20); | ||
3345 | snd_ac97_write_cache(pac97, 0x20, (usReg & 0xFEFF) + (usMS << 8)); | ||
3346 | |||
3347 | return 0; | ||
3348 | } | ||
3349 | |||
3350 | static const struct snd_kcontrol_new snd_ac97_controls_vt1617a[] = { | ||
3351 | |||
3352 | AC97_SINGLE("Center/LFE Exchange", 0x5a, 8, 1, 0), | ||
3353 | /* | ||
3354 | * These are used to enable/disable surround sound on motherboards | ||
3355 | * that have 3 bidirectional analog jacks | ||
3356 | */ | ||
3357 | { | ||
3358 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3359 | .name = "Smart 5.1 Select", | ||
3360 | .info = snd_ac97_vt1617a_smart51_info, | ||
3361 | .get = snd_ac97_vt1617a_smart51_get, | ||
3362 | .put = snd_ac97_vt1617a_smart51_put, | ||
3363 | }, | ||
3364 | }; | ||
3365 | |||
3366 | int patch_vt1617a(struct snd_ac97 * ac97) | ||
3367 | { | ||
3368 | int err = 0; | ||
3369 | |||
3370 | /* we choose to not fail out at this point, but we tell the | ||
3371 | caller when we return */ | ||
3372 | |||
3373 | err = patch_build_controls(ac97, &snd_ac97_controls_vt1617a[0], | ||
3374 | ARRAY_SIZE(snd_ac97_controls_vt1617a)); | ||
3375 | |||
3376 | /* bring analog power consumption to normal by turning off the | ||
3377 | * headphone amplifier, like WinXP driver for EPIA SP | ||
3284 | */ | 3378 | */ |
3285 | snd_ac97_write_cache(ac97, 0x5c, 0x20); | 3379 | snd_ac97_write_cache(ac97, 0x5c, 0x20); |
3286 | ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ | 3380 | ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ |
3287 | ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; | 3381 | ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; |
3288 | ac97->build_ops = &patch_vt1616_ops; | 3382 | ac97->build_ops = &patch_vt1616_ops; |
3289 | return 0; | 3383 | |
3384 | return err; | ||
3290 | } | 3385 | } |
3291 | 3386 | ||
3292 | /* | 3387 | /* |