Skip to content

Commit

Permalink
ALSA: ac97 - vt1618 7.1 Audio Support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
John L. Utz III authored and Jaroslav Kysela committed Aug 29, 2008
1 parent ac68c16 commit 9e285e1
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 3 deletions.
2 changes: 1 addition & 1 deletion sound/pci/ac97/ac97_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
{ 0x54584e20, 0xffffffff, "TLC320AD9xC", NULL, NULL },
{ 0x56494161, 0xffffffff, "VIA1612A", NULL, NULL }, // modified ICE1232 with S/PDIF
{ 0x56494170, 0xffffffff, "VIA1617A", patch_vt1617a, NULL }, // modified VT1616 with S/PDIF
{ 0x56494182, 0xffffffff, "VIA1618", NULL, NULL },
{ 0x56494182, 0xffffffff, "VIA1618", patch_vt1618, NULL },
{ 0x57454301, 0xffffffff, "W83971D", NULL, NULL },
{ 0x574d4c00, 0xffffffff, "WM9701,WM9701A", NULL, NULL },
{ 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL},
Expand Down
198 changes: 196 additions & 2 deletions sound/pci/ac97/ac97_patch.c
Original file line number Diff line number Diff line change
Expand Up @@ -3465,7 +3465,7 @@ static int patch_vt1616(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
* noodling the i/o jacks on 2 different regs. that means that we can't
* use the easy way provided by AC97_ENUM_DOUBLE() we have to write
* are own funcs.
*
Expand Down Expand Up @@ -3498,7 +3498,7 @@ static int snd_ac97_vt1617a_smart51_get(struct snd_kcontrol *kcontrol,

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

/* grab our desirec bits, then mash them together in a manner
/* grab our desired 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;
Expand Down Expand Up @@ -3576,6 +3576,200 @@ int patch_vt1617a(struct snd_ac97 * ac97)
return err;
}

/* VIA VT1618 8 CHANNEL AC97 CODEC
*
* VIA implements 'Smart 5.1' completely differently on the 1618 than
* it does on the 1617a. awesome! They seem to have sourced this
* particular revision of the technology from somebody else, it's
* called Universal Audio Jack and it shows up on some other folk's chips
* as well.
*
* ordering in this list reflects vt1618 docs for Reg 60h and
* the block diagram, DACs are as follows:
*
* OUT_O -> Front,
* OUT_1 -> Surround,
* OUT_2 -> C/LFE
*
* Unlike the 1617a, each OUT has a consistent set of mappings
* for all bitpatterns other than 00:
*
* 01 Unmixed Output
* 10 Line In
* 11 Mic In
*
* Special Case of 00:
*
* OUT_0 Mixed Output
* OUT_1 Reserved
* OUT_2 Reserved
*
* I have no idea what the hell Reserved does, but on an MSI
* CN700T, i have to set it to get 5.1 output - YMMV, bad
* shit may happen.
*
* If other chips use Universal Audio Jack, then this code might be applicable
* to them.
*/

struct vt1618_uaj_item {
unsigned short mask;
unsigned short shift;
const char *items[4];
};

/* This list reflects the vt1618 docs for Vendor Defined Register 0x60. */

static struct vt1618_uaj_item vt1618_uaj[3] = {
{
/* speaker jack */
.mask = 0x03,
.shift = 0,
.items = {
"Speaker Out", "DAC Unmixed Out", "Line In", "Mic In"
}
},
{
/* line jack */
.mask = 0x0c,
.shift = 2,
.items = {
"Surround Out", "DAC Unmixed Out", "Line In", "Mic In"
}
},
{
/* mic jack */
.mask = 0x30,
.shift = 4,
.items = {
"Center LFE Out", "DAC Unmixed Out", "Line In", "Mic In"
},
},
};

static int snd_ac97_vt1618_UAJ_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
return ac97_enum_text_info(kcontrol, uinfo,
vt1618_uaj[kcontrol->private_value].items,
4);
}

/* All of the vt1618 Universal Audio Jack twiddlers are on
* Vendor Defined Register 0x60, page 0. The bits, and thus
* the mask, are the only thing that changes
*/
static int snd_ac97_vt1618_UAJ_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
unsigned short datpag, uaj;
struct snd_ac97 *pac97 = snd_kcontrol_chip(kcontrol);

mutex_lock(&pac97->page_mutex);

datpag = snd_ac97_read(pac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, 0);

uaj = snd_ac97_read(pac97, 0x60) &
vt1618_uaj[kcontrol->private_value].mask;

snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, datpag);
mutex_unlock(&pac97->page_mutex);

ucontrol->value.enumerated.item[0] = uaj >>
vt1618_uaj[kcontrol->private_value].shift;

return 0;
}

static int snd_ac97_vt1618_UAJ_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
return ac97_update_bits_page(snd_kcontrol_chip(kcontrol), 0x60,
vt1618_uaj[kcontrol->private_value].mask,
ucontrol->value.enumerated.item[0]<<
vt1618_uaj[kcontrol->private_value].shift,
0);
}

/* config aux in jack - not found on 3 jack motherboards or soundcards */

static int snd_ac97_vt1618_aux_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
static const char *txt_aux[] = {"Aux In", "Back Surr Out"};

return ac97_enum_text_info(kcontrol, uinfo, txt_aux, 2);
}

static int snd_ac97_vt1618_aux_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.enumerated.item[0] =
(snd_ac97_read(snd_kcontrol_chip(kcontrol), 0x5c) & 0x0008)>>3;
return 0;
}

static int snd_ac97_vt1618_aux_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
/* toggle surround rear dac power */

snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x5c, 0x0008,
ucontrol->value.enumerated.item[0] << 3);

/* toggle aux in surround rear out jack */

return snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x76, 0x0008,
ucontrol->value.enumerated.item[0] << 3);
}

static const struct snd_kcontrol_new snd_ac97_controls_vt1618[] = {
AC97_SINGLE("Exchange Center/LFE", 0x5a, 8, 1, 0),
AC97_SINGLE("DC Offset", 0x5a, 10, 1, 0),
AC97_SINGLE("Soft Mute", 0x5c, 0, 1, 1),
AC97_SINGLE("Headphone Amp", 0x5c, 5, 1, 1),
AC97_DOUBLE("Back Surr Volume", 0x5e, 8, 0, 31, 1),
AC97_SINGLE("Back Surr Switch", 0x5e, 15, 1, 1),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Speaker Jack Mode",
.info = snd_ac97_vt1618_UAJ_info,
.get = snd_ac97_vt1618_UAJ_get,
.put = snd_ac97_vt1618_UAJ_put,
.private_value = 0
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line Jack Mode",
.info = snd_ac97_vt1618_UAJ_info,
.get = snd_ac97_vt1618_UAJ_get,
.put = snd_ac97_vt1618_UAJ_put,
.private_value = 1
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Jack Mode",
.info = snd_ac97_vt1618_UAJ_info,
.get = snd_ac97_vt1618_UAJ_get,
.put = snd_ac97_vt1618_UAJ_put,
.private_value = 2
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Aux Jack Mode",
.info = snd_ac97_vt1618_aux_info,
.get = snd_ac97_vt1618_aux_get,
.put = snd_ac97_vt1618_aux_put,
}
};

int patch_vt1618(struct snd_ac97 *ac97)
{
return patch_build_controls(ac97, snd_ac97_controls_vt1618,
ARRAY_SIZE(snd_ac97_controls_vt1618));
}

/*
*/
static void it2646_update_jacks(struct snd_ac97 *ac97)
Expand Down

0 comments on commit 9e285e1

Please sign in to comment.