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