support for EAPD, Balanced I/O, and LR-Swap

This commit is contained in:
kent 2006-07-21 14:40:12 +00:00
parent 9d93195858
commit 21623cc733
2 changed files with 162 additions and 3 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: azalia.h,v 1.13 2006/06/25 13:41:58 kent Exp $ */
/* $NetBSD: azalia.h,v 1.14 2006/07/21 14:40:12 kent Exp $ */
/*-
* Copyright (c) 2005 The NetBSD Foundation, Inc.
@ -356,6 +356,9 @@
#define CORB_PS_RIGHT 0x1
#define CORB_GET_EAPD_BTL_ENABLE 0xf0c
#define CORB_SET_EAPD_BTL_ENABLE 0x70c
#define CORB_EAPD_BTL 0x01
#define CORB_EAPD_EAPD 0x02
#define CORB_EAPD_LRSWAP 0x04
#define CORB_GET_GPI_DATA 0xf10
#define CORB_SET_GPI_DATA 0x710
#define CORB_GET_GPI_WAKE_ENABLE_MASK 0xf11
@ -523,6 +526,9 @@ typedef struct {
#define MI_TARGET_VOLUME 0x106
#define MI_TARGET_SPDIF 0x107
#define MI_TARGET_SPDIF_CC 0x108
#define MI_TARGET_EAPD 0x109
#define MI_TARGET_BALANCE 0x10a
#define MI_TARGET_LRSWAP 0x10b
} mixer_item_t;
#define VALID_WIDGET_NID(nid, codec) (nid == (codec)->audiofunc || \

View File

@ -1,4 +1,4 @@
/* $NetBSD: azalia_codec.c,v 1.22 2006/07/19 02:40:18 kent Exp $ */
/* $NetBSD: azalia_codec.c,v 1.23 2006/07/21 14:40:12 kent Exp $ */
/*-
* Copyright (c) 2005 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: azalia_codec.c,v 1.22 2006/07/19 02:40:18 kent Exp $");
__KERNEL_RCSID(0, "$NetBSD: azalia_codec.c,v 1.23 2006/07/21 14:40:12 kent Exp $");
#include <sys/param.h>
#include <sys/device.h>
@ -694,6 +694,72 @@ generic_mixer_init(codec_t *this)
this->nmixers++;
}
if (w->type == COP_AWTYPE_PIN_COMPLEX &&
w->d.pin.cap & COP_PINCAP_EAPD) {
MIXER_REG_PROLOG;
DPRINTF(("%s: eapd %s\n", __func__, w->name));
snprintf(d->label.name, sizeof(d->label.name),
"%s.eapd", w->name);
d->type = AUDIO_MIXER_ENUM;
d->mixer_class = AZ_CLASS_OUTPUT;
m->target = MI_TARGET_EAPD;
d->un.e.num_mem = 2;
d->un.e.member[0].ord = 0;
strlcpy(d->un.e.member[0].label.name, AudioNoff,
MAX_AUDIO_DEV_LEN);
d->un.e.member[1].ord = 1;
strlcpy(d->un.e.member[1].label.name, AudioNon,
MAX_AUDIO_DEV_LEN);
this->nmixers++;
}
if (w->type == COP_AWTYPE_PIN_COMPLEX &&
w->d.pin.cap & COP_PINCAP_BALANCE) {
MIXER_REG_PROLOG;
DPRINTF(("%s: balance %s\n", __func__, w->name));
snprintf(d->label.name, sizeof(d->label.name),
"%s.balance", w->name);
d->type = AUDIO_MIXER_ENUM;
if (w->type == COP_AWTYPE_PIN_COMPLEX)
d->mixer_class = AZ_CLASS_OUTPUT;
else if (w->type == COP_AWTYPE_AUDIO_INPUT)
d->mixer_class = AZ_CLASS_RECORD;
else
d->mixer_class = AZ_CLASS_INPUT;
m->target = MI_TARGET_BALANCE;
d->un.e.num_mem = 2;
d->un.e.member[0].ord = 0;
strlcpy(d->un.e.member[0].label.name, AudioNoff,
MAX_AUDIO_DEV_LEN);
d->un.e.member[1].ord = 1;
strlcpy(d->un.e.member[1].label.name, AudioNon,
MAX_AUDIO_DEV_LEN);
this->nmixers++;
}
if (w->widgetcap & COP_AWCAP_LRSWAP) {
MIXER_REG_PROLOG;
DPRINTF(("%s: lrswap %s\n", __func__, w->name));
snprintf(d->label.name, sizeof(d->label.name),
"%s.lrswap", w->name);
d->type = AUDIO_MIXER_ENUM;
if (w->type == COP_AWTYPE_PIN_COMPLEX)
d->mixer_class = AZ_CLASS_OUTPUT;
else if (w->type == COP_AWTYPE_AUDIO_INPUT)
d->mixer_class = AZ_CLASS_RECORD;
else
d->mixer_class = AZ_CLASS_INPUT;
m->target = MI_TARGET_LRSWAP;
d->un.e.num_mem = 2;
d->un.e.member[0].ord = 0;
strlcpy(d->un.e.member[0].label.name, AudioNoff,
MAX_AUDIO_DEV_LEN);
d->un.e.member[1].ord = 1;
strlcpy(d->un.e.member[1].label.name, AudioNon,
MAX_AUDIO_DEV_LEN);
this->nmixers++;
}
/* volume knob */
if (w->type == COP_AWTYPE_VOLUME_KNOB &&
w->d.volume.cap & COP_VKCAP_DELTA) {
@ -1048,6 +1114,33 @@ generic_mixer_get(const codec_t *this, nid_t nid, int target, mixer_ctrl_t *mc)
mc->un.value.level[0] = CORB_DCC_CC(result);
}
/* EAPD */
else if (target == MI_TARGET_EAPD) {
err = this->comresp(this, nid,
CORB_GET_EAPD_BTL_ENABLE, 0, &result);
if (err)
return err;
mc->un.ord = result & CORB_EAPD_EAPD ? 1 : 0;
}
/* Balanced I/O */
else if (target == MI_TARGET_BALANCE) {
err = this->comresp(this, nid,
CORB_GET_EAPD_BTL_ENABLE, 0, &result);
if (err)
return err;
mc->un.ord = result & CORB_EAPD_BTL ? 1 : 0;
}
/* LR-Swap */
else if (target == MI_TARGET_LRSWAP) {
err = this->comresp(this, nid,
CORB_GET_EAPD_BTL_ENABLE, 0, &result);
if (err)
return err;
mc->un.ord = result & CORB_EAPD_LRSWAP ? 1 : 0;
}
else {
aprint_error("%s: internal error in %s: target=%x\n",
XNAME(this), __func__, target);
@ -1324,6 +1417,66 @@ generic_mixer_set(codec_t *this, nid_t nid, int target, const mixer_ctrl_t *mc)
return err;
}
/* EAPD */
else if (target == MI_TARGET_EAPD) {
if (mc->un.ord >= 2)
return EINVAL;
err = this->comresp(this, nid,
CORB_GET_EAPD_BTL_ENABLE, 0, &result);
if (err)
return err;
result &= 0xff;
if (mc->un.ord == 0) {
result &= ~CORB_EAPD_EAPD;
} else {
result |= CORB_EAPD_EAPD;
}
err = this->comresp(this, nid,
CORB_SET_EAPD_BTL_ENABLE, result, &result);
if (err)
return err;
}
/* Balanced I/O */
else if (target == MI_TARGET_BALANCE) {
if (mc->un.ord >= 2)
return EINVAL;
err = this->comresp(this, nid,
CORB_GET_EAPD_BTL_ENABLE, 0, &result);
if (err)
return err;
result &= 0xff;
if (mc->un.ord == 0) {
result &= ~CORB_EAPD_BTL;
} else {
result |= CORB_EAPD_BTL;
}
err = this->comresp(this, nid,
CORB_SET_EAPD_BTL_ENABLE, result, &result);
if (err)
return err;
}
/* LR-Swap */
else if (target == MI_TARGET_LRSWAP) {
if (mc->un.ord >= 2)
return EINVAL;
err = this->comresp(this, nid,
CORB_GET_EAPD_BTL_ENABLE, 0, &result);
if (err)
return err;
result &= 0xff;
if (mc->un.ord == 0) {
result &= ~CORB_EAPD_LRSWAP;
} else {
result |= CORB_EAPD_LRSWAP;
}
err = this->comresp(this, nid,
CORB_SET_EAPD_BTL_ENABLE, result, &result);
if (err)
return err;
}
else {
aprint_error("%s: internal error in %s: target=%x\n",
XNAME(this), __func__, target);