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.6 (requested by kent in ti...



details:   https://anonhg.NetBSD.org/src/rev/ec61ed9b80a5
branches:  netbsd-3
changeset: 576413:ec61ed9b80a5
user:      tron <tron%NetBSD.org@localhost>
date:      Sat Jul 02 16:41:27 2005 +0000

description:
Pull up revision 1.6 (requested by kent in ticket #494):
support for recording

diffstat:

 sys/dev/pci/azalia.c |  337 +++++++++++++++++++++++++++++---------------------
 1 files changed, 196 insertions(+), 141 deletions(-)

diffs (truncated from 478 to 300 lines):

diff -r 4cf45788ed97 -r ec61ed9b80a5 sys/dev/pci/azalia.c
--- a/sys/dev/pci/azalia.c      Sat Jul 02 16:41:07 2005 +0000
+++ b/sys/dev/pci/azalia.c      Sat Jul 02 16:41:27 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: azalia.c,v 1.7.2.6 2005/07/02 16:41:07 tron Exp $      */
+/*     $NetBSD: azalia.c,v 1.7.2.7 2005/07/02 16:41:27 tron Exp $      */
 
 /*-
  * Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -38,14 +38,13 @@
 
 /*
  * TO DO:
- *  - recording support
  *  - Volume Knob widget
  *  - power hook
  *  - detach
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.7.2.6 2005/07/02 16:41:07 tron Exp $");
+__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.7.2.7 2005/07/02 16:41:27 tron Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -472,7 +471,7 @@
 #define                ICH_PCI_HDCTL_CLKDETINV         0x02
 #define                ICH_PCI_HDCTL_SIGNALMODE        0x01
 
-/* #define AZALIA_DEBUG */
+/*#define AZALIA_DEBUG*/
 #ifdef AZALIA_DEBUG
 # define DPRINTF(x)    do { printf x; } while (0/*CONSTCOND*/)
 #else
@@ -494,8 +493,10 @@
 #define AZALIA_DMA_DMAADDR(p)  ((p)->map->dm_segs[0].ds_addr)
 
 typedef struct {
+       struct azalia_t *az;
        int regbase;
        int number;
+       int dir;                /* AUMODE_PLAY or AUMODE_RECORD */
        uint32_t intr_bit;
        azalia_dma_t bdlist;
        azalia_dma_t buffer;
@@ -503,18 +504,18 @@
        void *intr_arg;
        bus_addr_t dmaend, dmanext; /* XXX needed? */
 } stream_t;
-#define STR_READ_1(z, s, r)    \
-       bus_space_read_1((z)->iot, (z)->ioh, (s)->regbase + HDA_SD_##r)
-#define STR_READ_2(z, s, r)    \
-       bus_space_read_2((z)->iot, (z)->ioh, (s)->regbase + HDA_SD_##r)
-#define STR_READ_4(z, s, r)    \
-       bus_space_read_4((z)->iot, (z)->ioh, (s)->regbase + HDA_SD_##r)
-#define STR_WRITE_1(z, s, r, v)        \
-       bus_space_write_1((z)->iot, (z)->ioh, (s)->regbase + HDA_SD_##r, v)
-#define STR_WRITE_2(z, s, r, v)        \
-       bus_space_write_2((z)->iot, (z)->ioh, (s)->regbase + HDA_SD_##r, v)
-#define STR_WRITE_4(z, s, r, v)        \
-       bus_space_write_4((z)->iot, (z)->ioh, (s)->regbase + HDA_SD_##r, v)
+#define STR_READ_1(s, r)       \
+       bus_space_read_1((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
+#define STR_READ_2(s, r)       \
+       bus_space_read_2((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
+#define STR_READ_4(s, r)       \
+       bus_space_read_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
+#define STR_WRITE_1(s, r, v)   \
+       bus_space_write_1((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
+#define STR_WRITE_2(s, r, v)   \
+       bus_space_write_2((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
+#define STR_WRITE_4(s, r, v)   \
+       bus_space_write_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
 
 typedef int nid_t;
 
@@ -669,6 +670,13 @@
 static int     azalia_widget_print_pin(const widget_t *);
 static int     azalia_widget_init_connection(widget_t *, const codec_t *);
 
+static int     azalia_stream_init(stream_t *, azalia_t *, int, int, int);
+static int     azalia_stream_reset(stream_t *);
+static int     azalia_stream_start(stream_t *, void *, void *, int,
+       void (*)(void *), void *, uint16_t);
+static int     azalia_stream_halt(stream_t *);
+static int     azalia_stream_intr(stream_t *, uint32_t);
+
 static int     azalia_open(void *, int);
 static void    azalia_close(void *);
 static int     azalia_query_encoding(void *, audio_encoding_t *);
@@ -829,7 +837,6 @@
 azalia_intr(void *v)
 {
        azalia_t *az;
-       stream_t *str;
        int ret;
        uint32_t intsts;
        uint8_t rirbsts;
@@ -842,14 +849,8 @@
        if (intsts == 0)
                return ret;
 
-       str = &az->pstream;
-       if (intsts & str->intr_bit) {
-               STR_WRITE_1(az, str, STS,
-                   HDA_SD_STS_DESE | HDA_SD_STS_FIFOE | HDA_SD_STS_BCIS);
-               //printf("[p]");
-               str->intr(str->intr_arg);
-               ret++;
-       }
+       ret += azalia_stream_intr(&az->pstream, intsts);
+       ret += azalia_stream_intr(&az->rstream, intsts);
 
        rirbsts = AZ_READ_1(az, RIRBSTS);
        if (rirbsts & (HDA_RIRBSTS_RIRBOIS | HDA_RIRBSTS_RINTFL)) {
@@ -960,25 +961,11 @@
                        return;
        }
 
-       az->pstream.regbase = HDA_SD_BASE + (az->nistreams + 0) * HDA_SD_SIZE;
-       az->pstream.intr_bit = 1 << ((az->pstream.regbase - HDA_SD_BASE) / HDA_SD_SIZE);
-       az->pstream.number = 1;
-       az->rstream.regbase = HDA_SD_BASE + 0 * HDA_SD_SIZE;
-       az->rstream.intr_bit = 1 << ((az->rstream.regbase - HDA_SD_BASE) / HDA_SD_SIZE);
-       az->rstream.number = 2;
-       /* setup BDL buffers */
-       err = azalia_alloc_dmamem(az, sizeof(bdlist_entry_t) * HDA_BDL_MAX,
-                                 128, &az->pstream.bdlist);
-       if (err) {
-               aprint_error("%s: can't allocate a BDL buffer\n", XNAME(az));
+       if (azalia_stream_init(&az->pstream, az, az->nistreams + 0,
+           1, AUMODE_PLAY))
                return;
-       }
-       err = azalia_alloc_dmamem(az, sizeof(bdlist_entry_t) * HDA_BDL_MAX,
-                                 128, &az->rstream.bdlist);
-       if (err) {
-               aprint_error("%s: can't allocate a BDL buffer\n", XNAME(az));
+       if (azalia_stream_init(&az->rstream, az, 0, 2, AUMODE_RECORD))
                return;
-       }
 
        az->audiodev = audio_attach_mi(&azalia_hw_if, az, &az->dev);
        return;
@@ -1736,13 +1723,17 @@
        nid_t nid;
        boolean_t flag222;
 
-       /* XXX */
-
        DPRINTF(("%s: fmt=0x%4.4x number=%d\n", __func__, fmt, number));
        err = 0;
        if (dir == AUMODE_RECORD) {
-               printf("%s: not implemented for AUMODE_RECORD\n", __func__);
-               return -1;
+               nid = this->adcs[this->cur_adc];
+               DPRINTF(("%s: record: nid=0x%.2x\n", __func__, nid));
+               err = this->comresp(this, nid, CORB_SET_CONVERTER_FORMAT, fmt, NULL);
+               if (err)
+                       goto exit;
+               err = this->comresp(this, nid, CORB_SET_CONVERTER_STREAM_CHANNEL,
+                                   (number << 4) | 0, NULL);
+               goto exit;
        }
        group = &this->dacgroups[this->cur_dac];
        flag222 = group->nconv >= 3 &&
@@ -2788,6 +2779,147 @@
 }
 
 /* ================================================================
+ * Stream functions
+ * ================================================================ */
+
+static int
+azalia_stream_init(stream_t *this, azalia_t *az, int regindex, int strnum, int dir)
+{
+       int err;
+
+       this->az = az;
+       this->regbase = HDA_SD_BASE + regindex * HDA_SD_SIZE;
+       this->intr_bit = 1 << regindex;
+       this->number = strnum;
+       this->dir = dir;
+
+       /* setup BDL buffers */
+       err = azalia_alloc_dmamem(az, sizeof(bdlist_entry_t) * HDA_BDL_MAX,
+                                 128, &this->bdlist);
+       if (err) {
+               aprint_error("%s: can't allocate a BDL buffer\n", XNAME(az));
+               return err;
+       }
+       return 0;
+}
+
+static int
+azalia_stream_reset(stream_t *this)
+{
+       int i;
+       uint16_t ctl;
+
+       ctl = STR_READ_2(this, CTL);
+       STR_WRITE_2(this, CTL, ctl | HDA_SD_CTL_SRST);
+       for (i = 5000; i >= 0; i--) {
+               DELAY(10);
+               ctl = STR_READ_2(this, CTL);
+               if (ctl & HDA_SD_CTL_SRST)
+                       break;
+       }
+       if (i <= 0) {
+               aprint_error("%s: stream reset failure 1\n", XNAME(this->az));
+               return -1;
+       }
+       STR_WRITE_2(this, CTL, ctl & ~HDA_SD_CTL_SRST);
+       for (i = 5000; i >= 0; i--) {
+               DELAY(10);
+               ctl = STR_READ_2(this, CTL);
+               if ((ctl & HDA_SD_CTL_SRST) == 0)
+                       break;
+       }
+       if (i <= 0) {
+               aprint_error("%s: stream reset failure 2\n", XNAME(this->az));
+               return -1;
+       }
+       return 0;
+}
+
+static int
+azalia_stream_start(stream_t *this, void *start, void *end, int blk,
+    void (*intr)(void *), void *arg, uint16_t fmt)
+{
+       bdlist_entry_t *bdlist;
+       bus_addr_t dmaaddr;
+       int err, index;
+       uint16_t ctl;
+       uint8_t ctl2, intctl;
+
+       this->intr = intr;
+       this->intr_arg = arg;
+
+       err = azalia_stream_reset(this);
+       if (err)
+               return err;
+
+       /* setup BDL */
+       dmaaddr = AZALIA_DMA_DMAADDR(&this->buffer);
+       this->dmaend = dmaaddr + ((caddr_t)end - (caddr_t)start);
+       bdlist = (bdlist_entry_t*)this->bdlist.addr;
+       for (index = 0; index < HDA_BDL_MAX; index++) {
+               bdlist[index].low = dmaaddr;
+               bdlist[index].high = PTR_UPPER32(dmaaddr);
+               bdlist[index].length = blk;
+               bdlist[index].flags = BDLIST_ENTRY_IOC;
+               dmaaddr += blk;
+               if (dmaaddr >= this->dmaend) {
+                       index++;
+                       break;
+               }
+       }
+       /* The BDL covers the whole of the buffer. */
+       this->dmanext = AZALIA_DMA_DMAADDR(&this->buffer);
+
+       dmaaddr = AZALIA_DMA_DMAADDR(&this->bdlist);
+       STR_WRITE_4(this, BDPL, dmaaddr);
+       STR_WRITE_4(this, BDPU, PTR_UPPER32(dmaaddr));
+       STR_WRITE_2(this, LVI, (index - 1) & HDA_SD_LVI_LVI);
+       ctl2 = STR_READ_1(this, CTL2);
+       STR_WRITE_1(this, CTL2,
+           (ctl2 & ~HDA_SD_CTL2_STRM) | (this->number << HDA_SD_CTL2_STRM_SHIFT));
+       STR_WRITE_4(this, CBL, ((caddr_t)end - (caddr_t)start));
+
+       STR_WRITE_2(this, FMT, fmt);
+       /* XXX */
+       err = azalia_codec_connect_stream(&this->az->codecs[0], this->dir,
+           fmt, this->number);
+       if (err)
+               return EINVAL;
+
+       intctl = AZ_READ_1(this->az, INTCTL);
+       intctl |= this->intr_bit;
+       AZ_WRITE_1(this->az, INTCTL, intctl);
+
+       ctl = STR_READ_2(this, CTL);
+       ctl |= ctl | HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE | HDA_SD_CTL_RUN;
+       STR_WRITE_2(this, CTL, ctl);
+       return 0;
+}
+
+static int
+azalia_stream_halt(stream_t *this)
+{
+       uint16_t ctl;
+
+       ctl = STR_READ_2(this, CTL);
+       ctl &= ~(HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE | HDA_SD_CTL_RUN);
+       STR_WRITE_2(this, CTL, ctl);
+       AZ_WRITE_1(this->az, INTCTL, AZ_READ_1(this->az, INTCTL) & ~this->intr_bit);
+       return 0;
+}
+
+static int



Home | Main Index | Thread Index | Old Index