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.4 (requested by kent in ti...
details: https://anonhg.NetBSD.org/src/rev/e6b61474fbe0
branches: netbsd-3
changeset: 576411:e6b61474fbe0
user: tron <tron%NetBSD.org@localhost>
date: Sat Jul 02 16:40:44 2005 +0000
description:
Pull up revision 1.4 (requested by kent in ticket #494):
- add capabilities to specify a DAC group or an ADC.
- support for 4,6,8 channels playback
diffstat:
sys/dev/pci/azalia.c | 407 +++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 349 insertions(+), 58 deletions(-)
diffs (truncated from 645 to 300 lines):
diff -r 5c42addbb32b -r e6b61474fbe0 sys/dev/pci/azalia.c
--- a/sys/dev/pci/azalia.c Sat Jul 02 16:40:21 2005 +0000
+++ b/sys/dev/pci/azalia.c Sat Jul 02 16:40:44 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: azalia.c,v 1.7.2.4 2005/07/02 16:40:21 tron Exp $ */
+/* $NetBSD: azalia.c,v 1.7.2.5 2005/07/02 16:40:44 tron Exp $ */
/*-
* Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -47,7 +47,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.7.2.4 2005/07/02 16:40:21 tron Exp $");
+__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.7.2.5 2005/07/02 16:40:44 tron Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -481,6 +481,7 @@
# define DPRINTF(x) do {} while (0/*CONSTCOND*/)
#endif
#define PTR_UPPER32(x) ((uint64_t)(uintptr_t)x >> 32)
+#define FLAGBUFLEN 256
/* internal types */
@@ -533,10 +534,6 @@
uint32_t encodings;
uint32_t bits_rates;
} audio;
- struct {
- } mixer;
- struct {
- } selector;
struct { /* for PIN */
uint32_t cap;
uint32_t config;
@@ -545,12 +542,9 @@
int color;
int device;
} pin;
- struct {
- } power;
- struct {
+ struct { /* for VOLUME_KNOB */
+ uint32_t cap;
} volume;
- struct {
- } beep;
} d;
} widget_t;
@@ -564,8 +558,15 @@
#define MI_TARGET_CONNLIST 0x101
#define MI_TARGET_PINDIR 0x102 /* for bidirectional pin */
#define MI_TARGET_PINBOOST 0x103 /* for headphone pin */
+#define MI_TARGET_DAC 0x104
+#define MI_TARGET_ADC 0x105
} mixer_item_t;
+typedef struct {
+ int nconv;
+ nid_t conv[HDA_MAX_CHANNELS];
+} convgroup_t;
+
typedef struct codec_t {
int (*comresp)(const struct codec_t *, nid_t, uint32_t, uint32_t, uint32_t *);
struct azalia_t *az;
@@ -577,8 +578,13 @@
widget_t *w; /* widgets in the audio function.
* w[0] to w[wstart-1] are unused. */
#define FOR_EACH_WIDGET(this, i) for (i = (this)->wstart; i < (this)->wend; i++)
- int ndacindexes;
- int dacindexes[HDA_MAX_CHANNELS];
+
+ int ndacgroups;
+ convgroup_t dacgroups[32];
+ int cur_dac; /* currently selected DAC group index */
+ int nadcs;
+ nid_t adcs[32];
+ int cur_adc; /* currently selected ADC index */
int nmixers, maxmixers;
mixer_item_t *mixers;
@@ -609,6 +615,8 @@
int nistreams, nostreams, nbstreams;
stream_t pstream;
stream_t rstream;
+
+ int running;
} azalia_t;
#define XNAME(sc) ((sc)->dev.dv_xname)
#define AZ_READ_1(z, r) bus_space_read_1((z)->iot, (z)->ioh, HDA_##r)
@@ -634,8 +642,9 @@
static int azalia_free_dmamem(const azalia_t *, azalia_dma_t*);
static int azalia_codec_init(codec_t *);
-static void azalia_codec_add_format(codec_t *, int, int, int, uint32_t);
-static int azalia_codec_find_pin(const codec_t *, uint32_t, int, int);
+static int azalia_codec_construct_format(codec_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,
uint32_t, uint32_t *);
@@ -643,7 +652,7 @@
static int azalia_mixer_init(codec_t *);
static int azalia_mixer_get(const codec_t *, mixer_ctrl_t *);
-static int azalia_mixer_set(const codec_t *, const 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 int azalia_widget_init(widget_t *, const codec_t *, int);
@@ -653,6 +662,8 @@
static int azalia_widget_print_pin(const widget_t *);
static int azalia_widget_init_connection(widget_t *, const codec_t *);
+static int azalia_open(void *, int);
+static void azalia_close(void *);
static int azalia_query_encoding(void *, audio_encoding_t *);
static int azalia_set_params(void *, int, int, audio_params_t *,
audio_params_t *, stream_filter_list_t *, stream_filter_list_t *);
@@ -679,8 +690,8 @@
azalia_pci_match, azalia_pci_attach, azalia_pci_detach, NULL);
static const struct audio_hw_if azalia_hw_if = {
- NULL, /* open */
- NULL, /* close */
+ azalia_open,
+ azalia_close,
NULL, /* drain */
azalia_query_encoding,
azalia_set_params,
@@ -1246,10 +1257,9 @@
static int
azalia_codec_init(codec_t *this)
{
- uint32_t rev, result, bits_rates;
- int err, addr, n, i;
- int assoc, npin, dac, chan, seq, nbits;
- int pindexes[HDA_MAX_CHANNELS];
+ uint32_t rev, result, digital;
+ int err, addr, n, i, j;
+ int assoc, dac, seq, group;
this->comresp = azalia_codec_comresp;
@@ -1328,6 +1338,92 @@
return err;
}
+ /*
+ * grouping DACs
+ * [0] the lowest assoc DACs
+ * [1] the lowest assoc digital outputs
+ * [2] the 2nd assoc DACs
+ * :
+ */
+ group = 0;
+ for (assoc = 0; assoc < CORB_CD_ASSOCIATION_MAX; assoc++) {
+ for (digital = 0; digital <= COP_AWCAP_DIGITAL; digital += COP_AWCAP_DIGITAL) {
+ n = 0;
+ for (seq = 0 ; seq < CORB_CD_SEQUENCE_MAX; seq++) {
+ i = azalia_codec_find_pin(this, assoc, seq, digital);
+ if (i < 0)
+ continue;
+ dac = azalia_codec_find_dac(this, i, 0);
+ if (dac < 0)
+ continue;
+ /* duplication check */
+ for (j = 0; j < n; j++) {
+ if (this->dacgroups[group].conv[j] == dac)
+ break;
+ }
+ if (j < n)
+ continue;
+ this->dacgroups[group].conv[n++] = dac;
+ DPRINTF(("%s: assoc=%d seq=%d ==> g=%d n=%d\n",
+ __func__, assoc, seq, group, n-1));
+ }
+ if (n > 0) {
+ this->dacgroups[group].nconv = n;
+ /* check if the same combination is already
+ * registered */
+ for (i = 0; i < group; i++) {
+ if (n != this->dacgroups[i].nconv)
+ continue;
+ for (j = 0; j < n; j++) {
+ if (this->dacgroups[group].conv[j] != this->dacgroups[i].conv[j])
+ break;
+ }
+ if (j >= n) /* matched */
+ break;
+ }
+ if (i >= group) /* not found */
+ group++;
+ }
+ }
+ }
+ this->ndacgroups = group;
+
+ /* find DACs which do not connect with any pins by default */
+ DPRINTF(("%s: find non-connected DACs\n", __func__));
+ FOR_EACH_WIDGET(this, i) {
+ boolean_t found;
+
+ if (this->w[i].type != COP_AWTYPE_AUDIO_OUTPUT)
+ continue;
+ found = FALSE;
+ for (group = 0; group < this->ndacgroups; group++) {
+ for (j = 0; j < this->dacgroups[group].nconv; j++) {
+ if (i == this->dacgroups[group].conv[j]) {
+ found = TRUE;
+ group = this->ndacgroups;
+ break;
+ }
+ }
+ }
+ if (found)
+ continue;
+ if (this->ndacgroups >= 32)
+ break;
+ this->dacgroups[this->ndacgroups].nconv = 1;
+ this->dacgroups[this->ndacgroups].conv[0] = i;
+ this->ndacgroups++;
+ }
+#ifdef AZALIA_DEBUG
+ for (group = 0; group < this->ndacgroups; group++) {
+ DPRINTF(("%s: dacgroup[%d]:", __func__, group));
+ for (j = 0; j < this->dacgroups[group].nconv; j++) {
+ DPRINTF((" %2.2x", this->dacgroups[group].conv[j]));
+ }
+ DPRINTF(("\n"));
+ }
+#endif
+ this->cur_dac = 0;
+#if 0
/* search pins for the lowest association */
assoc = INT_MAX;
FOR_EACH_WIDGET(this, i) {
@@ -1364,10 +1460,42 @@
DPRINTF((" 0x%x", this->dacindexes[i]));
}
DPRINTF(("\n"));
+#endif
- /* construct audio_format */
- azalia_widget_print_audio(&this->w[this->dacindexes[0]], XNAME(this->az));
- bits_rates = this->w[this->dacindexes[0]].d.audio.bits_rates;
+ /* enumerate ADCs */
+ this->nadcs = 0;
+ FOR_EACH_WIDGET(this, i) {
+ if (this->w[i].type != COP_AWTYPE_AUDIO_INPUT)
+ continue;
+ this->adcs[this->nadcs++] = i;
+ if (this->nadcs >= 32)
+ break;
+ }
+ this->cur_adc = 0;
+
+ err = azalia_codec_construct_format(this);
+ if (err)
+ return err;
+ azalia_mixer_init(this);
+ return 0;
+}
+
+static int
+azalia_codec_construct_format(codec_t *this)
+{
+ char flagbuf[FLAGBUFLEN];
+ const convgroup_t *group;
+ uint32_t bits_rates;
+ int pvariation, rvariation;
+ int nbits, dac, chan, i, err;
+
+ group = &this->dacgroups[this->cur_dac];
+ snprintf(flagbuf, FLAGBUFLEN, "%s: playback", XNAME(this->az));
+ azalia_widget_print_audio(&this->w[group->conv[0]], flagbuf);
+ snprintf(flagbuf, FLAGBUFLEN, "%s: record", XNAME(this->az));
+ azalia_widget_print_audio(&this->w[this->adcs[this->cur_adc]], flagbuf);
+
+ bits_rates = this->w[group->conv[0]].d.audio.bits_rates;
nbits = 0;
if (bits_rates & COP_PCM_B8)
nbits++;
@@ -1384,45 +1512,83 @@
XNAME(this->az), bits_rates);
return -1;
}
- this->formats = malloc(sizeof(struct audio_format) * npin * nbits,
- M_DEVBUF, M_ZERO | M_NOWAIT);
+ pvariation = group->nconv * nbits;
+
+ bits_rates = this->w[this->adcs[this->cur_adc]].d.audio.bits_rates;
+ nbits = 0;
+ if (bits_rates & COP_PCM_B8)
+ nbits++;
+ if (bits_rates & COP_PCM_B16)
Home |
Main Index |
Thread Index |
Old Index