summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorariff <ariff@FreeBSD.org>2006-12-09 17:52:54 +0000
committerariff <ariff@FreeBSD.org>2006-12-09 17:52:54 +0000
commit405791020de1e49802172d855e15c85f15592639 (patch)
treec3c28894140fb59ba921398851ab5d6cee18ede6 /sys
parentef305f6c5dabdfee29b5bb238f95bd58aed2ce45 (diff)
downloadFreeBSD-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')
-rw-r--r--sys/dev/sound/pci/hda/hdac.c121
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);
- }
}
}
OpenPOWER on IntegriCloud