diff options
author | ariff <ariff@FreeBSD.org> | 2006-12-09 17:52:54 +0000 |
---|---|---|
committer | ariff <ariff@FreeBSD.org> | 2006-12-09 17:52:54 +0000 |
commit | 405791020de1e49802172d855e15c85f15592639 (patch) | |
tree | c3c28894140fb59ba921398851ab5d6cee18ede6 /sys/dev/sound | |
parent | ef305f6c5dabdfee29b5bb238f95bd58aed2ce45 (diff) | |
download | FreeBSD-src-405791020de1e49802172d855e15c85f15592639.zip FreeBSD-src-405791020de1e49802172d855e15c85f15592639.tar.gz |
- Fix headphone/speakers automute on Lenovo 3000 N100.
Tested by: xride
- GPIO commit cleanups and fixes for possible breakage during
previous commit.
Diffstat (limited to 'sys/dev/sound')
-rw-r--r-- | sys/dev/sound/pci/hda/hdac.c | 121 |
1 files changed, 74 insertions, 47 deletions
diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c index 3b5abf1..b7ae541 100644 --- a/sys/dev/sound/pci/hda/hdac.c +++ b/sys/dev/sound/pci/hda/hdac.c @@ -80,7 +80,7 @@ #include "mixer_if.h" -#define HDA_DRV_TEST_REV "20061203_0035" +#define HDA_DRV_TEST_REV "20061210_0036" #define HDA_WIDGET_PARSER_REV 1 SND_DECLARE_FILE("$FreeBSD$"); @@ -242,10 +242,11 @@ SND_DECLARE_FILE("$FreeBSD$"); #define HDA_QUIRK_GPIO0 (1 << 0) #define HDA_QUIRK_GPIO1 (1 << 1) #define HDA_QUIRK_GPIO2 (1 << 2) -#define HDA_QUIRK_SOFTPCMVOL (1 << 15) -#define HDA_QUIRK_FIXEDRATE (1 << 16) -#define HDA_QUIRK_FORCESTEREO (1 << 17) -#define HDA_QUIRK_EAPDINV (1 << 18) +#define HDA_QUIRK_GPIOFLUSH (1 << 15) +#define HDA_QUIRK_SOFTPCMVOL (1 << 16) +#define HDA_QUIRK_FIXEDRATE (1 << 17) +#define HDA_QUIRK_FORCESTEREO (1 << 18) +#define HDA_QUIRK_EAPDINV (1 << 19) static const struct { char *key; @@ -254,6 +255,7 @@ static const struct { { "gpio0", HDA_QUIRK_GPIO0 }, { "gpio1", HDA_QUIRK_GPIO1 }, { "gpio2", HDA_QUIRK_GPIO2 }, + { "gpioflush", HDA_QUIRK_GPIOFLUSH }, { "softpcmvol", HDA_QUIRK_SOFTPCMVOL }, { "fixedrate", HDA_QUIRK_FIXEDRATE }, { "forcestereo", HDA_QUIRK_FORCESTEREO }, @@ -448,33 +450,38 @@ static const struct { uint32_t model; uint32_t id; int type; + int inverted; nid_t hpnid; nid_t spkrnid[8]; nid_t eapdnid; } hdac_hp_switch[] = { /* Specific OEM models */ - { HP_V3000_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL, + { HP_V3000_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL, 0, 17, { 16, -1 }, 16 }, - { HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, + { HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 0, 6, { 5, -1 }, 5 }, - { HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, + { HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 0, 6, { 5, -1 }, 5 }, - { DELL_D820_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, + { DELL_D820_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 0, 13, { 14, -1 }, -1 }, - { DELL_I1300_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, + { DELL_I1300_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 0, 13, { 14, -1 }, -1 }, - { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDAC_HP_SWITCH_CTRL, + { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDAC_HP_SWITCH_CTRL, 0, 10, { 13, -1 }, -1 }, + { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDAC_HP_SWITCH_CTL, 1, + 26, { 27, -1 }, -1 }, /* * All models that at least come from the same vendor with * simmilar codec. */ - { HP_ALL_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL, + { HP_ALL_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL, 0, 17, { 16, -1 }, 16 }, - { HP_ALL_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, + { HP_ALL_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL, 0, 6, { 5, -1 }, 5 }, - { DELL_ALL_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, + { DELL_ALL_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL, 0, 13, { 14, -1 }, -1 }, + { LENOVO_ALL_SUBVENDOR, HDA_CODEC_AD1986A, HDAC_HP_SWITCH_CTL, 1, + 26, { 27, -1 }, -1 }, }; #define HDAC_HP_SWITCH_LEN \ (sizeof(hdac_hp_switch) / sizeof(hdac_hp_switch[0])) @@ -683,6 +690,7 @@ hdac_hp_switch_handler(struct hdac_devinfo *devinfo) hdac_hp_switch[i].hpnid, res); ); res >>= 31; + res ^= hdac_hp_switch[i].inverted; switch (hdac_hp_switch[i].type) { case HDAC_HP_SWITCH_CTL: @@ -3457,11 +3465,11 @@ static const struct { { HDA_MATCH_ALL, HDA_MATCH_ALL, HDA_QUIRK_FORCESTEREO, 0 }, { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, - HDA_QUIRK_GPIO1, 0 }, + HDA_QUIRK_GPIO0, 0 }, { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, - HDA_QUIRK_GPIO1, 0 }, + HDA_QUIRK_GPIO0, 0 }, { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, - HDA_QUIRK_GPIO2, 0 }, + HDA_QUIRK_GPIO1, 0 }, { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, HDA_QUIRK_EAPDINV, 0 }, { ASUS_A8JC_SUBVENDOR, HDA_CODEC_AD1986A, @@ -3470,6 +3478,8 @@ static const struct { HDA_QUIRK_EAPDINV, 0 }, { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, HDA_QUIRK_EAPDINV, 0 }, + { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, + HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0 }, { HDA_MATCH_ALL, HDA_CODEC_CXVENICE, 0, HDA_QUIRK_FORCESTEREO }, { HDA_MATCH_ALL, HDA_CODEC_STACXXXX, @@ -4096,23 +4106,55 @@ hdac_audio_commit(struct hdac_devinfo *devinfo, uint32_t cfl) cad = devinfo->codec->cad; if (cfl & HDA_COMMIT_GPIO) { - if (sc->pci_subvendor == APPLE_INTEL_MAC) { - uint32_t gdata, gmask, gdir; - - gdata = hdac_command(sc, - HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), - cad); - gmask = hdac_command(sc, - HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), - cad); - gdir = hdac_command(sc, - HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), - cad); - gdata |= 0x03; - gmask |= 0x03; - gdir |= 0x03; + uint32_t gdata, gmask, gdir; + int commitgpio = 0; + + gdata = 0; + gmask = 0; + gdir = 0; + + if (sc->pci_subvendor == APPLE_INTEL_MAC) hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid, 0x7e7, 0), cad); + + if (devinfo->function.audio.quirks & HDA_QUIRK_GPIOFLUSH) + commitgpio = 1; + else { + for (i = 0; i < HDA_GPIO_MAX; i++) { + if (!(devinfo->function.audio.quirks & + (1 << i))) + continue; + if (commitgpio == 0) { + commitgpio = 1; + gdata = hdac_command(sc, + HDA_CMD_GET_GPIO_DATA(cad, + devinfo->nid), cad); + gmask = hdac_command(sc, + HDA_CMD_GET_GPIO_ENABLE_MASK(cad, + devinfo->nid), cad); + gdir = hdac_command(sc, + HDA_CMD_GET_GPIO_DIRECTION(cad, + devinfo->nid), cad); + HDA_BOOTVERBOSE( + device_printf(sc->dev, + "GPIO init: data=0x%08x " + "mask=0x%08x dir=0x%08x\n", + gdata, gmask, gdir); + ); + } + gdata |= 1 << i; + gmask |= 1 << i; + gdir |= 1 << i; + } + } + + if (commitgpio != 0) { + HDA_BOOTVERBOSE( + device_printf(sc->dev, + "GPIO commit: data=0x%08x mask=0x%08x " + "dir=0x%08x\n", + gdata, gmask, gdir); + ); hdac_command(sc, HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid, gmask), cad); @@ -4122,21 +4164,6 @@ hdac_audio_commit(struct hdac_devinfo *devinfo, uint32_t cfl) hdac_command(sc, HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, gdata), cad); - } else { - for (i = 0; i < HDA_GPIO_MAX; i++) { - if (!(devinfo->function.audio.quirks & - (1 << i))) - continue; - hdac_command(sc, - HDA_CMD_SET_GPIO_ENABLE_MASK(cad, - devinfo->nid, i), cad); - hdac_command(sc, - HDA_CMD_SET_GPIO_DIRECTION(cad, - devinfo->nid, i), cad); - hdac_command(sc, - HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid, - i), cad); - } } } |