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.5 (requested by kent in ti...
details: https://anonhg.NetBSD.org/src/rev/4cf45788ed97
branches: netbsd-3
changeset: 576412:4cf45788ed97
user: tron <tron%NetBSD.org@localhost>
date: Sat Jul 02 16:41:07 2005 +0000
description:
Pull up revision 1.5 (requested by kent in ticket #494):
- print the controller name if possible
- make the max values of mixers AUDIO_MAX_GAIN
- reset the stream in trigger_output()
diffstat:
sys/dev/pci/azalia.c | 239 +++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 183 insertions(+), 56 deletions(-)
diffs (truncated from 488 to 300 lines):
diff -r e6b61474fbe0 -r 4cf45788ed97 sys/dev/pci/azalia.c
--- a/sys/dev/pci/azalia.c Sat Jul 02 16:40:44 2005 +0000
+++ b/sys/dev/pci/azalia.c Sat Jul 02 16:41:07 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: azalia.c,v 1.7.2.5 2005/07/02 16:40:44 tron Exp $ */
+/* $NetBSD: azalia.c,v 1.7.2.6 2005/07/02 16:41:07 tron Exp $ */
/*-
* Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -38,16 +38,14 @@
/*
* TO DO:
- * o recording support
- * o mixer value scaling
- * o Volume Knob widget
- * o DAC selection
- * o ADC selection
- * o power hook
+ * - recording support
+ * - Volume Knob widget
+ * - power hook
+ * - detach
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.7.2.5 2005/07/02 16:40:44 tron Exp $");
+__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.7.2.6 2005/07/02 16:41:07 tron Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -482,6 +480,7 @@
#endif
#define PTR_UPPER32(x) ((uint64_t)(uintptr_t)x >> 32)
#define FLAGBUFLEN 256
+#define MAX_VOLUME_255 1
/* internal types */
@@ -636,14 +635,16 @@
static void azalia_attach_intr(struct device *);
static int azalia_init_corb(azalia_t *);
static int azalia_init_rirb(azalia_t *);
-static int azalia_set_command(const azalia_t *, nid_t, int, uint32_t, uint32_t);
+static int azalia_set_command(const azalia_t *, nid_t, int, uint32_t,
+ uint32_t);
static int azalia_get_response(azalia_t *, uint32_t *);
static int azalia_alloc_dmamem(azalia_t *, size_t, size_t, azalia_dma_t *);
static int azalia_free_dmamem(const azalia_t *, azalia_dma_t*);
static int azalia_codec_init(codec_t *);
static int azalia_codec_construct_format(codec_t *);
-static void azalia_codec_add_format(codec_t *, int, int, int, uint32_t, int32_t);
+static void azalia_codec_add_format(codec_t *, int, int, int, uint32_t,
+ int32_t);
static int azalia_codec_find_pin(const codec_t *, int, int, uint32_t);
static int azalia_codec_find_dac(const codec_t *, int, int);
static int azalia_codec_comresp(const codec_t *, nid_t, uint32_t,
@@ -654,6 +655,12 @@
static int azalia_mixer_get(const codec_t *, mixer_ctrl_t *);
static int azalia_mixer_set(codec_t *, const mixer_ctrl_t *);
static int azalia_mixer_ensure_capacity(codec_t *, size_t);
+static u_char azalia_mixer_from_device_value(const codec_t *,
+ const mixer_item_t *, uint32_t );
+static uint32_t azalia_mixer_to_device_value(const codec_t *,
+ const mixer_item_t *, u_char);
+static boolean_t azalia_mixer_validate_value(const codec_t *,
+ const mixer_item_t *, u_char);
static int azalia_widget_init(widget_t *, const codec_t *, int);
static int azalia_widget_init_audio(widget_t *, const codec_t *);
@@ -757,6 +764,7 @@
pcireg_t v;
pci_intr_handle_t ih;
const char *intrrupt_str;
+ const char *name;
sc = (azalia_t*)self;
pa = aux;
@@ -790,6 +798,16 @@
}
aprint_normal("%s: interrupting at %s\n", XNAME(sc), intrrupt_str);
+ name = pci_findproduct(pa->pa_id);
+ if (name != NULL) {
+ aprint_normal("%s: host: %s (rev. %d)\n",
+ XNAME(sc), name, PCI_REVISION(pa->pa_class));
+ } else {
+ aprint_normal("%s: host: 0x%4.4x/0x%4.4x (rev. %d)\n",
+ XNAME(sc), PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id),
+ PCI_REVISION(pa->pa_class));
+ }
+
if (azalia_attach(sc)) {
aprint_error("%s: initialization failure\n", XNAME(sc));
return;
@@ -859,13 +877,13 @@
uint16_t gcap;
uint16_t statests;
- aprint_normal("%s: controller: High Definition Audio rev. %d.%d\n",
+ aprint_normal("%s: host: High Definition Audio rev. %d.%d\n",
XNAME(az), AZ_READ_1(az, VMAJ), AZ_READ_1(az, VMIN));
gcap = AZ_READ_2(az, GCAP);
az->nistreams = HDA_GCAP_ISS(gcap);
az->nostreams = HDA_GCAP_OSS(gcap);
az->nbstreams = HDA_GCAP_BSS(gcap);
- DPRINTF(("%s: %d output, %d input, and %d bidi streams\n",
+ DPRINTF(("%s: host: %d output, %d input, and %d bidi streams\n",
XNAME(az), az->nostreams, az->nistreams, az->nbstreams));
/* 4.2.2 Starting the High Definition Audio Controller */
@@ -1275,11 +1293,11 @@
COP_VENDOR_ID, &result);
if (err)
return err;
- aprint_normal("%s: codec: High Definition Audio rev. %u.%u\n", XNAME(this->az),
- COP_RID_MAJ(rev), COP_RID_MIN(rev));
- aprint_normal("%s: vendor/device = 0x%4.4x/0x%4.4x (rev. %u.%u)\n",
+ aprint_normal("%s: codec: 0x%4.4x/0x%4.4x (rev. %u.%u)\n",
XNAME(this->az), result >> 16, result & 0xffff,
COP_RID_REVISION(rev), COP_RID_STEPPING(rev));
+ aprint_normal("%s: codec: High Definition Audio rev. %u.%u\n",
+ XNAME(this->az), COP_RID_MAJ(rev), COP_RID_MIN(rev));
/* identify function nodes */
err = this->comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
@@ -1766,13 +1784,11 @@
azalia_mixer_init(codec_t *this)
{
/*
- * o pin "<color>%2.2x"
- * o audio output "dac%2.2x"
- * o audio input "adc%2.2x"
- * o mixer "mixer%2.2x"
- * o selector "sel%2.2x"
- *
- * XXX DAC/ADC selection, SPDIF
+ * pin "<color>%2.2x"
+ * audio output "dac%2.2x"
+ * audio input "adc%2.2x"
+ * mixer "mixer%2.2x"
+ * selector "sel%2.2x"
*/
mixer_item_t *m;
int nadcs;
@@ -1905,10 +1921,16 @@
d->next = AUDIO_MIXER_LAST;
d->prev = AUDIO_MIXER_LAST;
m->target = MI_TARGET_OUTAMP;
+ d->un.v.num_channels = w->widgetcap & COP_AWCAP_STEREO ? 2 : 1;
+#ifdef MAX_VOLUME_255
+ d->un.v.units.name[0] = 0;
+ d->un.v.delta = AUDIO_MAX_GAIN /
+ COP_AMPCAP_NUMSTEPS(w->outamp_cap);
+#else
snprintf(d->un.v.units.name, sizeof(d->un.v.units.name),
"0.25x%ddB", COP_AMPCAP_STEPSIZE(w->outamp_cap)+1);
- d->un.v.num_channels = w->widgetcap & COP_AWCAP_STEREO ? 2 : 1;
d->un.v.delta = 1;
+#endif
this->nmixers++;
}
@@ -1957,10 +1979,16 @@
d->next = AUDIO_MIXER_LAST;
d->prev = AUDIO_MIXER_LAST;
m->target = j;
+ d->un.v.num_channels = w->widgetcap & COP_AWCAP_STEREO ? 2 : 1;
+#ifdef MAX_VOLUME_255
+ d->un.v.units.name[0] = 0;
+ d->un.v.delta = AUDIO_MAX_GAIN /
+ COP_AMPCAP_NUMSTEPS(w->inamp_cap);
+#else
snprintf(d->un.v.units.name, sizeof(d->un.v.units.name),
"0.25x%ddB", COP_AMPCAP_STEPSIZE(w->inamp_cap)+1);
- d->un.v.num_channels = w->widgetcap & COP_AWCAP_STEREO ? 2 : 1;
d->un.v.delta = 1;
+#endif
this->nmixers++;
}
}
@@ -2122,13 +2150,16 @@
CORB_GAGM_INPUT | CORB_GAGM_LEFT | MI_TARGET_INAMP(m->target), &result);
if (err)
return err;
- mc->un.value.level[0] = CORB_GAGM_GAIN(result);
+ mc->un.value.level[0] = azalia_mixer_from_device_value(this, m,
+ CORB_GAGM_GAIN(result));
if (this->w[m->nid].widgetcap & COP_AWCAP_STEREO) {
- err = this->comresp(this, m->nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_INPUT | CORB_GAGM_RIGHT | MI_TARGET_INAMP(m->target), &result);
+ err = this->comresp(this, m->nid,
+ CORB_GET_AMPLIFIER_GAIN_MUTE, CORB_GAGM_INPUT |
+ CORB_GAGM_RIGHT | MI_TARGET_INAMP(m->target), &result);
if (err)
return err;
- mc->un.value.level[1] = CORB_GAGM_GAIN(result);
+ mc->un.value.level[1] = azalia_mixer_from_device_value
+ (this, m, CORB_GAGM_GAIN(result));
mc->un.value.num_channels = 2;
} else {
mc->un.value.num_channels = 1;
@@ -2150,13 +2181,16 @@
CORB_GAGM_OUTPUT | CORB_GAGM_LEFT | 0, &result);
if (err)
return err;
- mc->un.value.level[0] = CORB_GAGM_GAIN(result);
+ mc->un.value.level[0] = azalia_mixer_from_device_value(this, m,
+ CORB_GAGM_GAIN(result));
if (this->w[m->nid].widgetcap & COP_AWCAP_STEREO) {
- err = this->comresp(this, m->nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
+ err = this->comresp(this, m->nid,
+ CORB_GET_AMPLIFIER_GAIN_MUTE,
CORB_GAGM_OUTPUT | CORB_GAGM_RIGHT | 0, &result);
if (err)
return err;
- mc->un.value.level[1] = CORB_GAGM_GAIN(result);
+ mc->un.value.level[1] = azalia_mixer_from_device_value
+ (this, m, CORB_GAGM_GAIN(result));
mc->un.value.num_channels = 2;
} else {
mc->un.value.num_channels = 1;
@@ -2227,7 +2261,8 @@
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);
+ CORB_GAGM_INPUT | CORB_GAGM_LEFT |
+ MI_TARGET_INAMP(m->target), &result);
if (err)
return err;
value = CORB_AGM_INPUT | CORB_AGM_LEFT |
@@ -2239,15 +2274,18 @@
if (err)
return err;
if (this->w[m->nid].widgetcap & COP_AWCAP_STEREO) {
- err = this->comresp(this, m->nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_INPUT | CORB_GAGM_RIGHT | MI_TARGET_INAMP(m->target), &result);
+ err = this->comresp(this, m->nid,
+ CORB_GET_AMPLIFIER_GAIN_MUTE, CORB_GAGM_INPUT |
+ CORB_GAGM_RIGHT | MI_TARGET_INAMP(m->target), &result);
if (err)
return err;
value = CORB_AGM_INPUT | CORB_AGM_RIGHT |
- (m->target << CORB_AGM_INDEX_SHIFT) | CORB_GAGM_GAIN(result);
+ (m->target << CORB_AGM_INDEX_SHIFT) |
+ CORB_GAGM_GAIN(result);
if (mc->un.ord)
value |= CORB_AGM_MUTE;
- err = this->comresp(this, m->nid, CORB_SET_AMPLIFIER_GAIN_MUTE, value, &result);
+ err = this->comresp(this, m->nid,
+ CORB_SET_AMPLIFIER_GAIN_MUTE, value, &result);
if (err)
return err;
}
@@ -2257,32 +2295,38 @@
else if (IS_MI_TARGET_INAMP(m->target) && m->devinfo.type == AUDIO_MIXER_VALUE) {
if (mc->un.value.num_channels < 1)
return EINVAL;
- if (mc->un.value.level[0] > COP_AMPCAP_NUMSTEPS(this->w[m->nid].inamp_cap))
+ if (!azalia_mixer_validate_value(this, m, mc->un.value.level[0]))
return EINVAL;
err = this->comresp(this, m->nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_INPUT | CORB_GAGM_LEFT | MI_TARGET_INAMP(m->target), &result);
+ CORB_GAGM_INPUT | CORB_GAGM_LEFT |
+ MI_TARGET_INAMP(m->target), &result);
if (err)
return err;
+ value = azalia_mixer_to_device_value(this, m, mc->un.value.level[0]);
value = CORB_AGM_INPUT | CORB_AGM_LEFT |
(m->target << CORB_AGM_INDEX_SHIFT) |
(result & CORB_GAGM_MUTE ? CORB_AGM_MUTE : 0) |
- (mc->un.value.level[0] & CORB_AGM_GAIN_MASK);
+ (value & CORB_AGM_GAIN_MASK);
err = this->comresp(this, m->nid, CORB_SET_AMPLIFIER_GAIN_MUTE,
value, &result);
if (err)
return err;
if (mc->un.value.num_channels >= 2 &&
this->w[m->nid].widgetcap & COP_AWCAP_STEREO) {
- if (mc->un.value.level[1] > COP_AMPCAP_NUMSTEPS(this->w[m->nid].inamp_cap))
+ if (!azalia_mixer_validate_value(this, m,
+ mc->un.value.level[1]))
return EINVAL;
- err = this->comresp(this, m->nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_INPUT | CORB_GAGM_RIGHT | MI_TARGET_INAMP(m->target), &result);
+ err = this->comresp(this, m->nid,
+ CORB_GET_AMPLIFIER_GAIN_MUTE, CORB_GAGM_INPUT |
+ CORB_GAGM_RIGHT | MI_TARGET_INAMP(m->target), &result);
if (err)
return err;
+ value = azalia_mixer_to_device_value(this, m,
+ mc->un.value.level[1]);
value = CORB_AGM_INPUT | CORB_AGM_RIGHT |
(m->target << CORB_AGM_INDEX_SHIFT) |
(result & CORB_GAGM_MUTE ? CORB_AGM_MUTE : 0) |
- (mc->un.value.level[0] & CORB_AGM_GAIN_MASK);
+ (value & CORB_AGM_GAIN_MASK);
err = this->comresp(this, m->nid,
Home |
Main Index |
Thread Index |
Old Index