Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-3]: src/sys/dev/pci Pull up revision 1.3 (requested by kent in ti...
details: https://anonhg.NetBSD.org/src/rev/5c42addbb32b
branches: netbsd-3
changeset: 576410:5c42addbb32b
user: tron <tron%NetBSD.org@localhost>
date: Sat Jul 02 16:40:21 2005 +0000
description:
Pull up revision 1.3 (requested by kent in ticket #494):
- add support for headphone-boost mixer controls
- fix a bug of creation of output mute
- unmute all controls by azalia_set_mixer()
- if a bidirectional pin is green, orange, gray, or black, set
it as "output" direction by default.
diffstat:
sys/dev/pci/azalia.c | 171 ++++++++++++++++++++++++++++++++++----------------
1 files changed, 116 insertions(+), 55 deletions(-)
diffs (truncated from 318 to 300 lines):
diff -r 7a6d406e1c35 -r 5c42addbb32b sys/dev/pci/azalia.c
--- a/sys/dev/pci/azalia.c Sat Jul 02 16:40:05 2005 +0000
+++ b/sys/dev/pci/azalia.c Sat Jul 02 16:40:21 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: azalia.c,v 1.7.2.3 2005/07/02 16:40:05 tron Exp $ */
+/* $NetBSD: azalia.c,v 1.7.2.4 2005/07/02 16:40:21 tron Exp $ */
/*-
* Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -40,12 +40,14 @@
* TO DO:
* o recording support
* o mixer value scaling
+ * o Volume Knob widget
* o DAC selection
* o ADC selection
+ * o power hook
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.7.2.3 2005/07/02 16:40:05 tron Exp $");
+__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.7.2.4 2005/07/02 16:40:21 tron Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -246,7 +248,7 @@
#define COP_AWCAP_STRIPE 0x020
#define COP_AWCAP_PROC 0x040
#define COP_AWCAP_UNSOL 0x080
-#define COP_AWCAP_CONLIST 0x100
+#define COP_AWCAP_CONNLIST 0x100
#define COP_AWCAP_DIGITAL 0x200
#define COP_AWCAP_POWER 0x400
#define COP_AWCAP_LRSWAP 0x800
@@ -560,7 +562,8 @@
#define MI_TARGET_INAMP(x) (x)
#define MI_TARGET_OUTAMP 0x100
#define MI_TARGET_CONNLIST 0x101
-#define MI_TARGET_DIR 0x102 /* for bidirectional pin */
+#define MI_TARGET_PINDIR 0x102 /* for bidirectional pin */
+#define MI_TARGET_PINBOOST 0x103 /* for headphone pin */
} mixer_item_t;
typedef struct codec_t {
@@ -708,14 +711,14 @@
static const char *pin_colors[16] = {
"unknown", "black", "gray", "blue",
"green", "red", "orange", "yellow",
- "purple", "pink", "0xa", "0xb",
- "0xc", "0xd", "white", "other"};
+ "purple", "pink", "col0a", "col0b",
+ "col0c", "col0d", "white", "other"};
#ifdef AZALIA_DEBUG
static const char *pin_devices[16] = {
"line-out", AudioNspeaker, AudioNheadphone, AudioNcd,
"SPDIF-out", "digital-out", "modem-line", "modem-handset",
"line-in", AudioNaux, AudioNmicrophone, "telephony",
- "SPDIF-in", "digital-in", "0xe", "other"};
+ "SPDIF-in", "digital-in", "dev0e", "other"};
#endif
/* ================================================================
@@ -1355,10 +1358,6 @@
}
npin++;
}
- for (i = 0; i < npin; i++) {
- this->comresp(this, pindexes[i], CORB_SET_PIN_WIDGET_CONTROL,
- CORB_PWC_OUTPUT | CORB_PWC_VREF_100, &result);
- }
this->ndacindexes = npin;
DPRINTF(("%s: DACs:", __func__));
for (i = 0; i < npin; i++) {
@@ -1413,25 +1412,6 @@
if (err)
return err;
- /* XXX unmute all of amplifiers */
- DPRINTF(("%s: unmute all widgets\n", __func__));
- FOR_EACH_WIDGET(this, i) {
- if (this->w[i].widgetcap & COP_AWCAP_INAMP) {
- for (n = 0; n < this->w[i].nconnections; n++) {
- this->comresp(this, this->w[i].nid,
- CORB_SET_AMPLIFIER_GAIN_MUTE, CORB_AGM_INPUT |
- CORB_AGM_LEFT | CORB_AGM_RIGHT | (n << 8) |
- COP_AMPCAP_OFFSET(this->w[i].inamp_cap), &result);
- }
- }
- if (this->w[i].widgetcap & COP_AWCAP_OUTAMP) {
- this->comresp(this, this->w[i].nid,
- CORB_SET_AMPLIFIER_GAIN_MUTE, CORB_AGM_OUTPUT |
- CORB_AGM_LEFT | CORB_AGM_RIGHT |
- COP_AMPCAP_OFFSET(this->w[i].outamp_cap), &result);
- }
- }
- DPRINTF(("%s: done.\n", __func__));
azalia_mixer_init(this);
return 0;
}
@@ -1602,25 +1582,11 @@
azalia_mixer_init(codec_t *this)
{
/*
- * o pin "color%2.2x"
- * conlist -> outputs.<name>.source
- * inamp -> outputs.<name>.<cname>.mute, outputs.<name>.<cname>
- * outamp -> inputs.<name>.mute, inputs.<name>
- * I/O -> outputs.<name>.dir=input/output
- * XXX usually, green=front, orange=surround, gray=c/lfe,
- * black=side?, blue=line-in pink=mic-in
+ * o pin "<color>%2.2x"
* o audio output "dac%2.2x"
- * outamp -> inputs.<name>.mute, inputs.<name>
* o audio input "adc%2.2x"
- * inamp -> record.<name>.<cname>.mute, record.<name>.<cname>
- * conlist -> record.<name>.source
- * o mixer "mixer%2.2x"
- * outamp -> outputs.<name>.mute, outputs.<name>
- * inamp -> inputs.<name>.<cname>.mute, ...
- * o selector "sel%2.2x"
- * outamp -> outputs.<name>.mute, outputs.<name>
- * inamp -> inputs.<name>.<cname>.mute, inputs.<name>.<cname>
- * conlist -> inputs.<name>.source
+ * o mixer "mixer%2.2x"
+ * o selector "sel%2.2x"
*
* XXX DAC/ADC selection, SPDIF
*/
@@ -1724,7 +1690,7 @@
d->mixer_class = AZ_CLASS_INPUT;
d->next = AUDIO_MIXER_LAST;
d->prev = AUDIO_MIXER_LAST;
- m->target = MI_TARGET_CONNLIST;
+ m->target = MI_TARGET_OUTAMP;
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);
@@ -1821,7 +1787,7 @@
d->mixer_class = AZ_CLASS_OUTPUT;
d->next = AUDIO_MIXER_LAST;
d->prev = AUDIO_MIXER_LAST;
- m->target = MI_TARGET_DIR;
+ m->target = MI_TARGET_PINDIR;
d->un.e.num_mem = 2;
d->un.e.member[0].ord = 0;
strlcpy(d->un.e.member[0].label.name, AudioNinput,
@@ -1831,6 +1797,67 @@
MAX_AUDIO_DEV_LEN);
this->nmixers++;
}
+
+ /* pin headphone-boost */
+ if (w->type == COP_AWTYPE_PIN_COMPLEX &&
+ w->d.pin.cap & COP_PINCAP_HEADPHONE) {
+ MIXER_REG_PROLOG;
+ snprintf(d->label.name, sizeof(d->label.name),
+ "%s.boost", w->name);
+ d->type = AUDIO_MIXER_ENUM;
+ d->mixer_class = AZ_CLASS_OUTPUT;
+ d->next = AUDIO_MIXER_LAST;
+ d->prev = AUDIO_MIXER_LAST;
+ m->target = MI_TARGET_PINBOOST;
+ 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++;
+ }
+ }
+
+ /* unmute all */
+ for (i = 0; i < this->nmixers; i++) {
+ mixer_ctrl_t mc;
+
+ if (!IS_MI_TARGET_INAMP(this->mixers[i].target) &&
+ this->mixers[i].target != MI_TARGET_OUTAMP)
+ continue;
+ if (this->mixers[i].devinfo.type != AUDIO_MIXER_ENUM)
+ continue;
+ mc.dev = i;
+ mc.type = AUDIO_MIXER_ENUM;
+ mc.un.ord = 0;
+ azalia_mixer_set(this, &mc);
+ }
+
+ /*
+ * for bidirectional pins,
+ * green=front, orange=surround, gray=c/lfe, black=size --> output
+ * blue=line-in, pink=mic-in --> input
+ */
+ for (i = 0; i < this->nmixers; i++) {
+ mixer_ctrl_t mc;
+
+ if (this->mixers[i].target != MI_TARGET_PINDIR)
+ continue;
+ mc.dev = i;
+ mc.type = AUDIO_MIXER_ENUM;
+ switch (this->w[this->mixers[i].nid].d.pin.color) {
+ case CORB_CD_GREEN:
+ case CORB_CD_ORANGE:
+ case CORB_CD_GRAY:
+ case CORB_CD_BLACK:
+ mc.un.ord = 1;
+ break;
+ default:
+ mc.un.ord = 0;
+ }
+ azalia_mixer_set(this, &mc);
}
return 0;
@@ -1916,15 +1943,25 @@
}
/* pin I/O */
- else if (m->target == MI_TARGET_DIR) {
+ else if (m->target == MI_TARGET_PINDIR) {
err = this->comresp(this, m->nid,
CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
if (err)
return err;
mc->un.ord = result & CORB_PWC_OUTPUT ? 1 : 0;
+ }
+
+ /* pin headphone-boost */
+ else if (m->target == MI_TARGET_PINBOOST) {
+ err = this->comresp(this, m->nid,
+ CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
+ if (err)
+ return err;
+ mc->un.ord = result & CORB_PWC_HEADPHONE ? 1 : 0;
} else {
- aprint_error("%s: internal error in %s: %x\n", XNAME(this->az), __func__, m->target);
+ aprint_error("%s: internal error in %s: %x\n", XNAME(this->az),
+ __func__, m->target);
return -1;
}
return 0;
@@ -1947,6 +1984,7 @@
/* inamp mute */
if (IS_MI_TARGET_INAMP(m->target) && m->devinfo.type == AUDIO_MIXER_ENUM) {
+ /* We have to set stereo mute separately to keep each gain value. */
err = this->comresp(this, m->nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
CORB_GAGM_INPUT | CORB_GAGM_LEFT | MI_TARGET_INAMP(m->target), &result);
if (err)
@@ -2082,7 +2120,7 @@
}
/* pin I/O */
- else if (m->target == MI_TARGET_DIR) {
+ else if (m->target == MI_TARGET_PINDIR) {
if (mc->un.ord >= 2)
return EINVAL;
err = this->comresp(this, m->nid,
@@ -2098,9 +2136,31 @@
}
err = this->comresp(this, m->nid,
CORB_SET_PIN_WIDGET_CONTROL, result, &result);
+ if (err)
+ return err;
+ }
+
+ /* pin headphone-boost */
+ else if (m->target == MI_TARGET_PINBOOST) {
+ if (mc->un.ord >= 2)
+ return EINVAL;
+ err = this->comresp(this, m->nid,
+ CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
+ if (err)
+ return err;
+ if (mc->un.ord == 0) {
+ result &= ~CORB_PWC_HEADPHONE;
+ } else {
+ result |= CORB_PWC_HEADPHONE;
+ }
+ err = this->comresp(this, m->nid,
+ CORB_SET_PIN_WIDGET_CONTROL, result, &result);
+ if (err)
+ return err;
} else {
- aprint_error("%s: internal error in %s: %x\n", XNAME(this->az), __func__, m->target);
+ aprint_error("%s: internal error in %s: %x\n", XNAME(this->az),
+ __func__, m->target);
return -1;
}
return 0;
@@ -2148,7 +2208,7 @@
this->widgetcap = result;
this->type = COP_AWCAP_TYPE(result);
bitmask_snprintf(this->widgetcap, "\20\014LRSWAP\013POWER\012DIGITAL"
- "\011CONLIST\010UNSOL\07PROC\06STRIPE\05FORMATOV\04AMPOV\03OUTAMP"
+ "\011CONNLIST\010UNSOL\07PROC\06STRIPE\05FORMATOV\04AMPOV\03OUTAMP"
"\02INAMP\01STEREO", flagbuf, FLAGBUFLEN);
DPRINTF(("%s: ", XNAME(codec->az)));
Home |
Main Index |
Thread Index |
Old Index