Bug #2090 ยป hda_automute.patch
sys/dev/sound/pci/hda/hdac.c | ||
---|---|---|
};
|
||
#define HDAC_CODECS_LEN NELEM(hdac_codecs)
|
||
enum {
|
||
HDAC_HP_SWITCH_CTL,
|
||
HDAC_HP_SWITCH_CTRL,
|
||
HDAC_HP_SWITCH_DEBUG
|
||
};
|
||
static const struct {
|
||
uint32_t model;
|
||
uint32_t id;
|
||
int type;
|
||
int inverted;
|
||
int polling;
|
||
int execsense;
|
||
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,
|
||
0, 0, -1, 17, { 16, -1 }, 16 },
|
||
/* { HP_XW4300_SUBVENDOR, HDA_CODEC_ALC260, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 21, { 16, 17, -1 }, -1 } */
|
||
/* { HP_3010_SUBVENDOR, HDA_CODEC_ALC260, HDAC_HP_SWITCH_DEBUG,
|
||
0, 1, 0, 16, { 15, 18, 19, 20, 21, -1 }, -1 }, */
|
||
{ HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 6, { 5, -1 }, 5 },
|
||
{ HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 6, { 5, -1 }, 5 },
|
||
{ HP_NX6325_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 6, { 5, -1 }, 5 },
|
||
/* { HP_DC7700_SUBVENDOR, HDA_CODEC_ALC262, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 21, { 22, 27, -1 }, -1 }, */
|
||
{ TOSHIBA_U200_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 6, { 5, -1 }, -1 },
|
||
{ TOSHIBA_A135_SUBVENDOR, HDA_CODEC_ALC861VD, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 27, { 20, -1 }, -1 },
|
||
{ DELL_D820_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL,
|
||
0, 0, -1, 13, { 14, -1 }, -1 },
|
||
{ DELL_I1300_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL,
|
||
0, 0, -1, 13, { 14, -1 }, -1 },
|
||
{ DELL_OPLX745_SUBVENDOR, HDA_CODEC_AD1983, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 6, { 5, 7, -1 }, -1 },
|
||
{ APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 21, { 20, 22, -1 }, -1 },
|
||
{ APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDAC_HP_SWITCH_CTRL,
|
||
0, 0, -1, 10, { 13, -1 }, -1 },
|
||
{ LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDAC_HP_SWITCH_CTL,
|
||
1, 0, -1, 26, { 27, -1 }, -1 },
|
||
/* { LENOVO_TCA55_SUBVENDOR, HDA_CODEC_AD1986A, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 26, { 27, 28, 29, 30, -1 }, -1 }, */
|
||
{ LG_LW20_SUBVENDOR, HDA_CODEC_ALC880, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 27, { 20, -1 }, -1 },
|
||
{ ACER_A5050_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 20, { 21, -1 }, -1 },
|
||
{ ACER_3681WXM_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 20, { 21, -1 }, -1 },
|
||
{ ACER_A4520_SUBVENDOR, HDA_CODEC_ALC268, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 20, { 21, -1 }, -1 },
|
||
{ UNIWILL_9080_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 20, { 21, -1 }, -1 },
|
||
{ MSI_MS1034_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 20, { 27, -1 }, -1 },
|
||
{ MSI_MS034A_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 20, { 27, -1 }, -1 },
|
||
{ FS_SI1848_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 20, { 21, -1 }, -1 },
|
||
{ FL_S7020D_SUBVENDOR, HDA_CODEC_ALC260, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 20, { 16, -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,
|
||
0, 0, -1, 17, { 16, -1 }, 16 },
|
||
{ HP_ALL_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 6, { 5, -1 }, 5 },
|
||
{ TOSHIBA_ALL_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 6, { 5, -1 }, -1 },
|
||
{ DELL_ALL_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL,
|
||
0, 0, -1, 13, { 14, -1 }, -1 },
|
||
#if 0
|
||
{ LENOVO_ALL_SUBVENDOR, HDA_CODEC_AD1986A, HDAC_HP_SWITCH_CTL,
|
||
1, 0, -1, 26, { 27, -1 }, -1 },
|
||
{ ACER_ALL_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL,
|
||
0, 0, -1, 20, { 21, -1 }, -1 },
|
||
#endif
|
||
};
|
||
#define HDAC_HP_SWITCH_LEN NELEM(hdac_hp_switch)
|
||
static const struct {
|
||
uint32_t model;
|
||
uint32_t id;
|
||
... | ... | |
struct hdac_widget *w;
|
||
struct hdac_audio_ctl *ctl;
|
||
uint32_t val, id, res;
|
||
int i = 0, j, timeout, forcemute;
|
||
nid_t cad;
|
||
int i = 0, timeout, forcemute;
|
||
nid_t cad, hp_nid;
|
||
if (devinfo == NULL || devinfo->codec == NULL ||
|
||
devinfo->codec->sc == NULL)
|
||
... | ... | |
sc = devinfo->codec->sc;
|
||
cad = devinfo->codec->cad;
|
||
id = hdac_codec_id(devinfo);
|
||
for (i = 0; i < HDAC_HP_SWITCH_LEN; i++) {
|
||
if (HDA_DEV_MATCH(hdac_hp_switch[i].model,
|
||
sc->pci_subvendor) &&
|
||
hdac_hp_switch[i].id == id)
|
||
break;
|
||
}
|
||
if (i >= HDAC_HP_SWITCH_LEN)
|
||
return;
|
||
forcemute = 0;
|
||
if (hdac_hp_switch[i].eapdnid != -1) {
|
||
w = hdac_widget_get(devinfo, hdac_hp_switch[i].eapdnid);
|
||
if (w != NULL && w->param.eapdbtl != HDAC_INVALID)
|
||
forcemute = (w->param.eapdbtl &
|
||
HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD) ? 0 : 1;
|
||
}
|
||
if (hdac_hp_switch[i].execsense != -1)
|
||
hdac_command(sc,
|
||
HDA_CMD_SET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid,
|
||
hdac_hp_switch[i].execsense), cad);
|
||
/*For now, only the first headphone jack supports automute. So find
|
||
* that jack*/
|
||
hp_nid = devinfo->startnode;
|
||
for (; hp_nid < devinfo->endnode; hp_nid++) {
|
||
w = hdac_widget_get(devinfo, hp_nid);
|
||
if((w != NULL) &&
|
||
(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) &&
|
||
(HDA_PARAM_PIN_CAP_HEADPHONE_CAP(w->wclass.pin.config))) {
|
||
break;
|
||
}
|
||
}
|
||
timeout = 10000;
|
||
do {
|
||
res = hdac_command(sc,
|
||
HDA_CMD_GET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid),
|
||
HDA_CMD_GET_PIN_SENSE(cad, hp_nid),
|
||
cad);
|
||
if (hdac_hp_switch[i].execsense == -1 || res != 0x7fffffff)
|
||
if (res != 0x7fffffff)
|
||
break;
|
||
DELAY(10);
|
||
} while (--timeout != 0);
|
||
... | ... | |
HDA_BOOTVERBOSE(
|
||
device_printf(sc->dev,
|
||
"HDA_DEBUG: Pin sense: nid=%d timeout=%d res=0x%08x\n",
|
||
hdac_hp_switch[i].hpnid, timeout, res);
|
||
hp_nid, timeout, res);
|
||
);
|
||
res = HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(res);
|
||
res ^= hdac_hp_switch[i].inverted;
|
||
switch (hdac_hp_switch[i].type) {
|
||
case HDAC_HP_SWITCH_CTL:
|
||
ctl = hdac_audio_ctl_amp_get(devinfo,
|
||
hdac_hp_switch[i].hpnid, 0, 1);
|
||
if (ctl != NULL) {
|
||
val = (res != 0 && forcemute == 0) ?
|
||
HDA_AMP_MUTE_NONE : HDA_AMP_MUTE_ALL;
|
||
if (val != ctl->muted) {
|
||
ctl->muted = val;
|
||
hdac_audio_ctl_amp_set(ctl,
|
||
HDA_AMP_MUTE_DEFAULT, ctl->left,
|
||
ctl->right);
|
||
}
|
||
}
|
||
for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) {
|
||
ctl = hdac_audio_ctl_amp_get(devinfo,
|
||
hdac_hp_switch[i].spkrnid[j], 0, 1);
|
||
if (ctl == NULL)
|
||
continue;
|
||
val = (res != 0 || forcemute == 1) ?
|
||
HDA_AMP_MUTE_ALL : HDA_AMP_MUTE_NONE;
|
||
if (val == ctl->muted)
|
||
continue;
|
||
|
||
|
||
ctl = hdac_audio_ctl_amp_get(devinfo,
|
||
hp_nid, 0, 1);
|
||
if (ctl != NULL) {
|
||
val = (res != 0 && forcemute == 0) ?
|
||
HDA_AMP_MUTE_NONE : HDA_AMP_MUTE_ALL;
|
||
if (val != ctl->muted) {
|
||
ctl->muted = val;
|
||
hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_DEFAULT,
|
||
ctl->left, ctl->right);
|
||
hdac_audio_ctl_amp_set(ctl,
|
||
HDA_AMP_MUTE_DEFAULT, ctl->left,
|
||
ctl->right);
|
||
}
|
||
break;
|
||
case HDAC_HP_SWITCH_CTRL:
|
||
if (res != 0) {
|
||
/* HP in */
|
||
w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid);
|
||
if (w != NULL && w->type ==
|
||
HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
|
||
if (forcemute == 0)
|
||
val = w->wclass.pin.ctrl |
|
||
HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
|
||
else
|
||
val = w->wclass.pin.ctrl &
|
||
~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
|
||
if (val != w->wclass.pin.ctrl) {
|
||
w->wclass.pin.ctrl = val;
|
||
hdac_command(sc,
|
||
HDA_CMD_SET_PIN_WIDGET_CTRL(cad,
|
||
w->nid, w->wclass.pin.ctrl), cad);
|
||
}
|
||
}
|
||
for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) {
|
||
w = hdac_widget_get(devinfo,
|
||
hdac_hp_switch[i].spkrnid[j]);
|
||
if (w == NULL || w->type !=
|
||
HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
|
||
continue;
|
||
val = w->wclass.pin.ctrl &
|
||
~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
|
||
if (val == w->wclass.pin.ctrl)
|
||
continue;
|
||
w->wclass.pin.ctrl = val;
|
||
hdac_command(sc, HDA_CMD_SET_PIN_WIDGET_CTRL(
|
||
cad, w->nid, w->wclass.pin.ctrl), cad);
|
||
}
|
||
} else {
|
||
/* HP out */
|
||
w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid);
|
||
if (w != NULL && w->type ==
|
||
HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
|
||
val = w->wclass.pin.ctrl &
|
||
~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
|
||
if (val != w->wclass.pin.ctrl) {
|
||
w->wclass.pin.ctrl = val;
|
||
hdac_command(sc,
|
||
HDA_CMD_SET_PIN_WIDGET_CTRL(cad,
|
||
w->nid, w->wclass.pin.ctrl), cad);
|
||
}
|
||
}
|
||
for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) {
|
||
w = hdac_widget_get(devinfo,
|
||
hdac_hp_switch[i].spkrnid[j]);
|
||
if (w == NULL || w->type !=
|
||
HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
|
||
continue;
|
||
if (forcemute == 0)
|
||
val = w->wclass.pin.ctrl |
|
||
HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
|
||
else
|
||
val = w->wclass.pin.ctrl &
|
||
~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
|
||
if (val == w->wclass.pin.ctrl)
|
||
continue;
|
||
w->wclass.pin.ctrl = val;
|
||
hdac_command(sc, HDA_CMD_SET_PIN_WIDGET_CTRL(
|
||
cad, w->nid, w->wclass.pin.ctrl), cad);
|
||
}
|
||
}
|
||
|
||
for (i = devinfo->startnode; i < devinfo->endnode; i++) {
|
||
|
||
w = hdac_widget_get(devinfo, i);
|
||
if(w == NULL || w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
|
||
continue;
|
||
}
|
||
break;
|
||
case HDAC_HP_SWITCH_DEBUG:
|
||
if (hdac_hp_switch[i].execsense != -1)
|
||
hdac_command(sc,
|
||
HDA_CMD_SET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid,
|
||
hdac_hp_switch[i].execsense), cad);
|
||
res = hdac_command(sc,
|
||
HDA_CMD_GET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid), cad);
|
||
device_printf(sc->dev,
|
||
"[ 0] HDA_DEBUG: Pin sense: nid=%d res=0x%08x\n",
|
||
hdac_hp_switch[i].hpnid, res);
|
||
for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) {
|
||
w = hdac_widget_get(devinfo,
|
||
hdac_hp_switch[i].spkrnid[j]);
|
||
if (w == NULL || w->type !=
|
||
HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
|
||
continue;
|
||
if (hdac_hp_switch[i].execsense != -1)
|
||
hdac_command(sc,
|
||
HDA_CMD_SET_PIN_SENSE(cad, w->nid,
|
||
hdac_hp_switch[i].execsense), cad);
|
||
res = hdac_command(sc,
|
||
HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad);
|
||
device_printf(sc->dev,
|
||
"[%2d] HDA_DEBUG: Pin sense: nid=%d res=0x%08x\n",
|
||
j + 1, w->nid, res);
|
||
|
||
if(((w->wclass.pin.config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) !=
|
||
HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER)) {
|
||
continue;
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
|
||
ctl = hdac_audio_ctl_amp_get(devinfo,
|
||
i, 0, 1);
|
||
if (ctl == NULL)
|
||
continue;
|
||
val = (res != 0 || forcemute == 1) ?
|
||
HDA_AMP_MUTE_ALL : HDA_AMP_MUTE_NONE;
|
||
if (val == ctl->muted)
|
||
continue;
|
||
ctl->muted = val;
|
||
hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_DEFAULT,
|
||
ctl->left, ctl->right);
|
||
}
|
||
}
|
||
... | ... | |
};
|
||
CHANNEL_DECLARE(hdac_channel);
|
||
static void
|
||
hdac_jack_poll_callback(void *arg)
|
||
{
|
||
struct hdac_devinfo *devinfo = arg;
|
||
struct hdac_softc *sc;
|
||
if (devinfo == NULL || devinfo->codec == NULL ||
|
||
devinfo->codec->sc == NULL)
|
||
return;
|
||
sc = devinfo->codec->sc;
|
||
hdac_lock(sc);
|
||
if (sc->poll_ival == 0) {
|
||
hdac_unlock(sc);
|
||
return;
|
||
}
|
||
hdac_hp_switch_handler(devinfo);
|
||
callout_reset(&sc->poll_jack, sc->poll_ival,
|
||
hdac_jack_poll_callback, devinfo);
|
||
hdac_unlock(sc);
|
||
}
|
||
static int
|
||
hdac_audio_ctl_ossmixer_init(struct snd_mixer *m)
|
||
{
|
||
... | ... | |
id = hdac_codec_id(devinfo);
|
||
cad = devinfo->codec->cad;
|
||
for (i = 0; i < HDAC_HP_SWITCH_LEN; i++) {
|
||
if (!(HDA_DEV_MATCH(hdac_hp_switch[i].model,
|
||
sc->pci_subvendor) && hdac_hp_switch[i].id == id))
|
||
|
||
for (i = devinfo->startnode; i < devinfo->endnode; i++) {
|
||
w = hdac_widget_get(devinfo, i);
|
||
if(w == NULL || w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
|
||
continue;
|
||
w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid);
|
||
if (w == NULL || w->enable == 0 || w->type !=
|
||
HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
|
||
}
|
||
if(!HDA_PARAM_PIN_CAP_HEADPHONE_CAP(w->wclass.pin.config)) {
|
||
continue;
|
||
if (hdac_hp_switch[i].polling != 0)
|
||
callout_reset(&sc->poll_jack, 1,
|
||
hdac_jack_poll_callback, devinfo);
|
||
else if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap))
|
||
hdac_command(sc,
|
||
}
|
||
if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) {
|
||
device_printf(sc->dev, "Enabling unsolicited responses for nid %d.", w->nid);
|
||
hdac_command(sc,
|
||
HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, w->nid,
|
||
HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE |
|
||
HDAC_UNSOLTAG_EVENT_HP), cad);
|
||
else
|
||
} else {
|
||
continue;
|
||
}
|
||
hdac_hp_switch_handler(devinfo);
|
||
HDA_BOOTVERBOSE(
|
||
device_printf(sc->dev,
|
||
... | ... | |
"pci_subvendor=0x%08x "
|
||
"codec=0x%08x [%s]\n",
|
||
i, w->nid, sc->pci_subvendor, id,
|
||
(hdac_hp_switch[i].polling != 0) ? "POLL" :
|
||
"UNSOL");
|
||
);
|
||
break;
|
||
}
|
||
for (i = 0; i < HDAC_EAPD_SWITCH_LEN; i++) {
|
||
if (!(HDA_DEV_MATCH(hdac_eapd_switch[i].model,
|
||
... | ... | |
callout_init(&sc->poll_hda);
|
||
callout_init(&sc->poll_hdac);
|
||
callout_init(&sc->poll_jack);
|
||
TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc);
|
||
... | ... | |
sc->poll_ival = 0;
|
||
callout_stop(&sc->poll_hda);
|
||
callout_stop(&sc->poll_hdac);
|
||
callout_stop(&sc->poll_jack);
|
||
hdac_reset(sc);
|
||
hdac_unlock(sc);
|
||
... | ... | |
device_printf(sc->dev,
|
||
"HDA_DEBUG: Enabling controller interrupt...\n");
|
||
);
|
||
if (sc->polling == 0)
|
||
HDAC_WRITE_4(&sc->mem, HDAC_INTCTL,
|
||
HDAC_INTCTL_CIE | HDAC_INTCTL_GIE);
|
||
HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) |
|
||
HDAC_GCTL_UNSOL);
|
||
if (sc->polling == 0) {
|
||
HDAC_WRITE_4(&sc->mem, HDAC_INTCTL,
|
||
HDAC_INTCTL_CIE | HDAC_INTCTL_GIE);
|
||
} else {
|
||
callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc);
|
||
}
|
||
|
||
DELAY(1000);
|
||
sys/dev/sound/pci/hda/hdac_private.h | ||
---|---|---|
int poll_ival;
|
||
struct callout poll_hda;
|
||
struct callout poll_hdac;
|
||
struct callout poll_jack;
|
||
struct task unsolq_task;
|
||