Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9024ccc authored by John Utz's avatar John Utz Committed by Jaroslav Kysela
Browse files

[ALSA] ac97 - Smart 5.1 for VIA 1617a codec



This patch provides a single 8 way enum called 'Smart 5.1 Select' with
some reasonable names for each enum that allows the user to choose
which of the 8 possible settings for vt1617a's version of what via
calls 'Smart 5.1'.

Signed-off-by: default avatarJohn Utz <john.utz@dmx.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@suse.cz>
parent 7f29673b
Loading
Loading
Loading
Loading
+99 −4
Original line number Diff line number Diff line
@@ -3277,16 +3277,111 @@ static int patch_vt1616(struct snd_ac97 * ac97)
/*
 * VT1617A codec
 */
static int patch_vt1617a(struct snd_ac97 * ac97)

/*
 * unfortunately, the vt1617a stashes the twiddlers required for
 * nooding the i/o jacks on 2 different regs. * thameans that we cant
 * use the easy way provided by AC97_ENUM_DOUBLE() we have to write
 * are own funcs.
 *
 * NB: this is absolutely and utterly different from the vt1618. dunno
 * about the 1616.
 */

/* copied from ac97_surround_jack_mode_info() */
static int snd_ac97_vt1617a_smart51_info(struct snd_kcontrol *kcontrol,
					 struct snd_ctl_elem_info *uinfo)
{
	/* ordering in this list reflects vt1617a docs for Reg 20 and
	 * 7a and Table 6 that lays out the matrix NB WRT Table6: SM51
	 * is SM51EN *AND* it's Bit14, not Bit15 so the table is very
	 * counter-intuitive */ 

	static const char* texts[] = { "LineIn Mic1", "LineIn Mic1 Mic3",
				       "Surr LFE/C Mic3", "LineIn LFE/C Mic3",
				       "LineIn Mic2", "LineIn Mic2 Mic1",
				       "Surr LFE Mic1", "Surr LFE Mic1 Mic2"};
	return ac97_enum_text_info(kcontrol, uinfo, texts, 8);
}

static int snd_ac97_vt1617a_smart51_get(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
{
	ushort usSM51, usMS;  

	struct snd_ac97 *pac97;
	
	pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */

	/* grab our desirec bits, then mash them together in a manner
	 * consistent with Table 6 on page 17 in the 1617a docs */
 
	usSM51 = snd_ac97_read(pac97, 0x7a) >> 14;
	usMS   = snd_ac97_read(pac97, 0x20) >> 8;
  
	ucontrol->value.enumerated.item[0] = (usSM51 << 1) + usMS;

	return 0;
}

static int snd_ac97_vt1617a_smart51_put(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
{
	ushort usSM51, usMS, usReg;  

	struct snd_ac97 *pac97;

	pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */

	usSM51 = ucontrol->value.enumerated.item[0] >> 1;
	usMS   = ucontrol->value.enumerated.item[0] &  1;

	/* push our values into the register - consider that things will be left
	 * in a funky state if the write fails */

	usReg = snd_ac97_read(pac97, 0x7a);
	snd_ac97_write_cache(pac97, 0x7a, (usReg & 0x3FFF) + (usSM51 << 14));
	usReg = snd_ac97_read(pac97, 0x20);
	snd_ac97_write_cache(pac97, 0x20, (usReg & 0xFEFF) + (usMS   <<  8));

	return 0;
}

static const struct snd_kcontrol_new snd_ac97_controls_vt1617a[] = {

	AC97_SINGLE("Center/LFE Exchange", 0x5a, 8, 1, 0),
	/*
	 * These are used to enable/disable surround sound on motherboards
	 * that have 3 bidirectional analog jacks
	 */
	{
	/* bring analog power consumption to normal, like WinXP driver
	 * for EPIA SP
		.iface         = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name          = "Smart 5.1 Select",
		.info          = snd_ac97_vt1617a_smart51_info,
		.get           = snd_ac97_vt1617a_smart51_get,
		.put           = snd_ac97_vt1617a_smart51_put,
	},
};

int patch_vt1617a(struct snd_ac97 * ac97)
{
	int err = 0;

	/* we choose to not fail out at this point, but we tell the
	   caller when we return */

	err = patch_build_controls(ac97, &snd_ac97_controls_vt1617a[0],
				   ARRAY_SIZE(snd_ac97_controls_vt1617a));

	/* bring analog power consumption to normal by turning off the
	 * headphone amplifier, like WinXP driver for EPIA SP
	 */
	snd_ac97_write_cache(ac97, 0x5c, 0x20);
	ac97->ext_id |= AC97_EI_SPDIF;	/* force the detection of spdif */
	ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
	ac97->build_ops = &patch_vt1616_ops;
	return 0;

	return err;
}

/*