diff options
author | Maxim Levitsky <maximlevitsky@gmail.com> | 2007-09-03 09:29:04 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2007-10-16 09:59:48 -0400 |
commit | 0fb87bb474f978446786263deff6263284e6e011 (patch) | |
tree | 31ae8630dd58f4c35a66dfc82fcf5378d29f2c22 /sound/pci/hda/patch_sigmatel.c | |
parent | d804ad9258c1460916a5e5854655a0dc543fd8a5 (diff) |
[ALSA] hda-codec - add support for swapping center/LFE channels to STAC codecs
Center/LFE channels are located on same jack, so it can be usefull
to swap them.
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 76 |
1 files changed, 72 insertions, 4 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index b4a1d73b5721..297f74019279 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -146,6 +146,7 @@ struct sigmatel_spec { | |||
146 | 146 | ||
147 | /* i/o switches */ | 147 | /* i/o switches */ |
148 | unsigned int io_switch[2]; | 148 | unsigned int io_switch[2]; |
149 | unsigned int clfe_swap; | ||
149 | 150 | ||
150 | struct hda_pcm pcm_rec[2]; /* PCM information */ | 151 | struct hda_pcm pcm_rec[2]; /* PCM information */ |
151 | 152 | ||
@@ -1406,6 +1407,36 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1406 | return 1; | 1407 | return 1; |
1407 | } | 1408 | } |
1408 | 1409 | ||
1410 | #define stac92xx_clfe_switch_info snd_ctl_boolean_mono_info | ||
1411 | |||
1412 | static int stac92xx_clfe_switch_get(struct snd_kcontrol *kcontrol, | ||
1413 | struct snd_ctl_elem_value *ucontrol) | ||
1414 | { | ||
1415 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1416 | struct sigmatel_spec *spec = codec->spec; | ||
1417 | |||
1418 | ucontrol->value.integer.value[0] = spec->clfe_swap; | ||
1419 | return 0; | ||
1420 | } | ||
1421 | |||
1422 | static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol, | ||
1423 | struct snd_ctl_elem_value *ucontrol) | ||
1424 | { | ||
1425 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1426 | struct sigmatel_spec *spec = codec->spec; | ||
1427 | hda_nid_t nid = kcontrol->private_value & 0xff; | ||
1428 | |||
1429 | if (spec->clfe_swap == ucontrol->value.integer.value[0]) | ||
1430 | return 0; | ||
1431 | |||
1432 | spec->clfe_swap = ucontrol->value.integer.value[0]; | ||
1433 | |||
1434 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
1435 | spec->clfe_swap ? 0x4 : 0x0); | ||
1436 | |||
1437 | return 1; | ||
1438 | } | ||
1439 | |||
1409 | #define STAC_CODEC_IO_SWITCH(xname, xpval) \ | 1440 | #define STAC_CODEC_IO_SWITCH(xname, xpval) \ |
1410 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 1441 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1411 | .name = xname, \ | 1442 | .name = xname, \ |
@@ -1416,17 +1447,28 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1416 | .private_value = xpval, \ | 1447 | .private_value = xpval, \ |
1417 | } | 1448 | } |
1418 | 1449 | ||
1450 | #define STAC_CODEC_CLFE_SWITCH(xname, xpval) \ | ||
1451 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1452 | .name = xname, \ | ||
1453 | .index = 0, \ | ||
1454 | .info = stac92xx_clfe_switch_info, \ | ||
1455 | .get = stac92xx_clfe_switch_get, \ | ||
1456 | .put = stac92xx_clfe_switch_put, \ | ||
1457 | .private_value = xpval, \ | ||
1458 | } | ||
1419 | 1459 | ||
1420 | enum { | 1460 | enum { |
1421 | STAC_CTL_WIDGET_VOL, | 1461 | STAC_CTL_WIDGET_VOL, |
1422 | STAC_CTL_WIDGET_MUTE, | 1462 | STAC_CTL_WIDGET_MUTE, |
1423 | STAC_CTL_WIDGET_IO_SWITCH, | 1463 | STAC_CTL_WIDGET_IO_SWITCH, |
1464 | STAC_CTL_WIDGET_CLFE_SWITCH | ||
1424 | }; | 1465 | }; |
1425 | 1466 | ||
1426 | static struct snd_kcontrol_new stac92xx_control_templates[] = { | 1467 | static struct snd_kcontrol_new stac92xx_control_templates[] = { |
1427 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), | 1468 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), |
1428 | HDA_CODEC_MUTE(NULL, 0, 0, 0), | 1469 | HDA_CODEC_MUTE(NULL, 0, 0, 0), |
1429 | STAC_CODEC_IO_SWITCH(NULL, 0), | 1470 | STAC_CODEC_IO_SWITCH(NULL, 0), |
1471 | STAC_CODEC_CLFE_SWITCH(NULL, 0), | ||
1430 | }; | 1472 | }; |
1431 | 1473 | ||
1432 | /* add dynamic controls */ | 1474 | /* add dynamic controls */ |
@@ -1620,7 +1662,7 @@ static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_ | |||
1620 | } | 1662 | } |
1621 | 1663 | ||
1622 | /* add playback controls from the parsed DAC table */ | 1664 | /* add playback controls from the parsed DAC table */ |
1623 | static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | 1665 | static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, |
1624 | const struct auto_pin_cfg *cfg) | 1666 | const struct auto_pin_cfg *cfg) |
1625 | { | 1667 | { |
1626 | static const char *chname[4] = { | 1668 | static const char *chname[4] = { |
@@ -1629,6 +1671,10 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | |||
1629 | hda_nid_t nid; | 1671 | hda_nid_t nid; |
1630 | int i, err; | 1672 | int i, err; |
1631 | 1673 | ||
1674 | struct sigmatel_spec *spec = codec->spec; | ||
1675 | unsigned int wid_caps; | ||
1676 | |||
1677 | |||
1632 | for (i = 0; i < cfg->line_outs; i++) { | 1678 | for (i = 0; i < cfg->line_outs; i++) { |
1633 | if (!spec->multiout.dac_nids[i]) | 1679 | if (!spec->multiout.dac_nids[i]) |
1634 | continue; | 1680 | continue; |
@@ -1643,6 +1689,18 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | |||
1643 | err = create_controls(spec, "LFE", nid, 2); | 1689 | err = create_controls(spec, "LFE", nid, 2); |
1644 | if (err < 0) | 1690 | if (err < 0) |
1645 | return err; | 1691 | return err; |
1692 | |||
1693 | wid_caps = get_wcaps(codec, nid); | ||
1694 | |||
1695 | if (wid_caps & AC_WCAP_LR_SWAP) { | ||
1696 | err = stac92xx_add_control(spec, | ||
1697 | STAC_CTL_WIDGET_CLFE_SWITCH, | ||
1698 | "Swap Center/LFE Playback Switch", nid); | ||
1699 | |||
1700 | if (err < 0) | ||
1701 | return err; | ||
1702 | } | ||
1703 | |||
1646 | } else { | 1704 | } else { |
1647 | err = create_controls(spec, chname[i], nid, 3); | 1705 | err = create_controls(spec, chname[i], nid, 3); |
1648 | if (err < 0) | 1706 | if (err < 0) |
@@ -1895,9 +1953,19 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
1895 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) | 1953 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) |
1896 | return err; | 1954 | return err; |
1897 | 1955 | ||
1898 | if ((err = stac92xx_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 1956 | err = stac92xx_auto_create_multi_out_ctls(codec, &spec->autocfg); |
1899 | (err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg)) < 0 || | 1957 | |
1900 | (err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) | 1958 | if (err < 0) |
1959 | return err; | ||
1960 | |||
1961 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); | ||
1962 | |||
1963 | if (err < 0) | ||
1964 | return err; | ||
1965 | |||
1966 | err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg); | ||
1967 | |||
1968 | if (err < 0) | ||
1901 | return err; | 1969 | return err; |
1902 | 1970 | ||
1903 | if (spec->num_dmics > 0) | 1971 | if (spec->num_dmics > 0) |