Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-5]: src/sys/dev/pci Pull up revisions 1.1-1.4 (new, via patch, ...



details:   https://anonhg.NetBSD.org/src/rev/56f580cfcca7
branches:  netbsd-1-5
changeset: 491655:56f580cfcca7
user:      he <he%NetBSD.org@localhost>
date:      Sun May 06 15:12:08 2001 +0000

description:
Pull up revisions 1.1-1.4 (new, via patch, requested by he):
  Add driver for Cirrus Logic CrystalClear PCI Audio CS4281.

diffstat:

 sys/dev/pci/cs4281.c |  1262 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1262 insertions(+), 0 deletions(-)

diffs (truncated from 1266 to 300 lines):

diff -r d8ca58c23d84 -r 56f580cfcca7 sys/dev/pci/cs4281.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/pci/cs4281.c      Sun May 06 15:12:08 2001 +0000
@@ -0,0 +1,1262 @@
+/*     $NetBSD: cs4281.c,v 1.4.2.2 2001/05/06 15:12:08 he Exp $        */
+
+/*
+ * Copyright (c) 2000 Tatoku Ogaito.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Tatoku Ogaito
+ *     for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Cirrus Logic CS4281 driver.
+ * Data sheets can be found
+ * http://www.cirrus.com/ftp/pub/4281.pdf
+ * ftp://ftp.alsa-project.org/pub/manuals/cirrus/cs4281tm.pdf
+ *
+ * TODO:
+ *   1: midi and FM support
+ *   2: ...
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/fcntl.h>
+#include <sys/device.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <dev/pci/pcidevs.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/cs4281reg.h>
+#include <dev/pci/cs428xreg.h>
+
+#include <sys/audioio.h>
+#include <dev/audio_if.h>
+#include <dev/midi_if.h>
+#include <dev/mulaw.h>
+#include <dev/auconv.h>
+
+#include <dev/ic/ac97reg.h>
+#include <dev/ic/ac97var.h>
+
+#include <dev/pci/cs428x.h>
+
+#include <machine/bus.h>
+
+#if defined(ENABLE_SECONDARY_CODEC)
+#define MAX_CHANNELS  (4)
+#define MAX_FIFO_SIZE 32 /* 128/4channels */
+#else
+#define MAX_CHANNELS  (2)
+#define MAX_FIFO_SIZE 64 /* 128/2channels */
+#endif
+
+/* IF functions for audio driver */
+int    cs4281_match(struct device *, struct cfdata *, void *);
+void   cs4281_attach(struct device *, struct device *, void *);
+int    cs4281_intr(void *);
+int    cs4281_query_encoding(void *, struct audio_encoding *);
+int    cs4281_set_params(void *, int, int, struct audio_params *, struct audio_params *);
+int    cs4281_halt_output(void *);
+int    cs4281_halt_input(void *);
+int    cs4281_getdev(void *, struct audio_device *);
+int    cs4281_trigger_output(void *, void *, void *, int, void (*)(void *),
+                             void *, struct audio_params *);
+int    cs4281_trigger_input(void *, void *, void *, int, void (*)(void *),
+                            void *, struct audio_params *);
+
+void    cs4281_reset_codec(void *);
+
+/* Internal functions */
+u_int8_t cs4281_sr2regval(int);
+void    cs4281_set_dac_rate(struct cs428x_softc *, int);
+void    cs4281_set_adc_rate(struct cs428x_softc *, int);
+int      cs4281_init(struct cs428x_softc *, int);
+
+/* Power Management */
+void cs4281_power(int, void *);
+
+struct audio_hw_if cs4281_hw_if = {
+       cs428x_open,
+       cs428x_close,
+       NULL,
+       cs4281_query_encoding,
+       cs4281_set_params,
+       cs428x_round_blocksize,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       cs4281_halt_output,
+       cs4281_halt_input,
+       NULL,
+       cs4281_getdev,
+       NULL,
+       cs428x_mixer_set_port,
+       cs428x_mixer_get_port,
+       cs428x_query_devinfo,
+       cs428x_malloc,
+       cs428x_free,
+       cs428x_round_buffersize,
+       cs428x_mappage,
+       cs428x_get_props,
+       cs4281_trigger_output,
+       cs4281_trigger_input,
+};
+
+#if NMIDI > 0 && 0
+/* Midi Interface */
+void   cs4281_midi_close(void*);
+void   cs4281_midi_getinfo(void *, struct midi_info *);
+int    cs4281_midi_open(void *, int, void (*)(void *, int),
+                             void (*)(void *), void *);
+int    cs4281_midi_output(void *, int);
+
+struct midi_hw_if cs4281_midi_hw_if = {
+       cs4281_midi_open,
+       cs4281_midi_close,
+       cs4281_midi_output,
+       cs4281_midi_getinfo,
+       0,
+};
+#endif
+
+struct cfattach clct_ca = {
+       sizeof(struct cs428x_softc), cs4281_match, cs4281_attach
+};
+
+struct audio_device cs4281_device = {
+       "CS4281",
+       "",
+       "cs4281"
+};
+
+
+int
+cs4281_match(parent, match, aux) 
+       struct device *parent;
+       struct cfdata *match;
+       void *aux;
+{
+       struct pci_attach_args *pa = (struct pci_attach_args *)aux;
+       
+       if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CIRRUS)
+               return 0;
+       if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CIRRUS_CS4281)
+               return 1;
+       return 0;
+}
+
+void
+cs4281_attach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct cs428x_softc *sc = (struct cs428x_softc *)self;
+       struct pci_attach_args *pa = (struct pci_attach_args *)aux;
+       pci_chipset_tag_t pc = pa->pa_pc;
+       char const *intrstr;
+       pci_intr_handle_t ih;
+       pcireg_t reg;
+       char devinfo[256];
+       int pci_pwrmgmt_cap_reg, pci_pwrmgmt_csr_reg;
+
+       pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
+       printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class));
+
+       /* Map I/O register */
+       if (pci_mapreg_map(pa, PCI_BA0,
+           PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
+           &sc->ba0t, &sc->ba0h, NULL, NULL)) {
+               printf("%s: can't map BA0 space\n", sc->sc_dev.dv_xname);
+               return;
+       }
+       if (pci_mapreg_map(pa, PCI_BA1,
+           PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
+           &sc->ba1t, &sc->ba1h, NULL, NULL)) {
+               printf("%s: can't map BA1 space\n", sc->sc_dev.dv_xname);
+               return;
+       }
+
+       sc->sc_dmatag = pa->pa_dmat;
+
+       /*
+        * Set Power State D0.
+        * Without do this, 0xffffffff is read from all registers after
+        * using Windows.
+        * On my IBM Thinkpad X20, it is set to D3 after using Windows2000.
+        */
+       if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT,
+                              &pci_pwrmgmt_cap_reg, 0)) {
+
+               pci_pwrmgmt_csr_reg = pci_pwrmgmt_cap_reg + 4;
+               reg = pci_conf_read(pa->pa_pc, pa->pa_tag,
+                                   pci_pwrmgmt_csr_reg);
+               if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0) {
+                       pci_conf_write(pc, pa->pa_tag, pci_pwrmgmt_csr_reg,
+                                      (reg & ~PCI_PMCSR_STATE_MASK) |
+                                      PCI_PMCSR_STATE_D0);
+               }
+       }
+
+       /* Enable the device (set bus master flag) */
+       reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
+       pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
+           reg | PCI_COMMAND_MASTER_ENABLE);
+
+#if 0
+       /* LATENCY_TIMER setting */
+       temp1 = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
+       if ( PCI_LATTIMER(temp1) < 32 ) {
+               temp1 &= 0xffff00ff;
+               temp1 |= 0x00002000;
+               pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, temp1);
+       }
+#endif
+       
+       /* Map and establish the interrupt. */
+       if (pci_intr_map(pa, pa->pa_intrtag, pa->pa_intrpin,
+                        pa->pa_intrline, &ih)) { 
+               printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
+               return;
+       }
+       intrstr = pci_intr_string(pc, ih);
+
+       sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, cs4281_intr, sc);
+       if (sc->sc_ih == NULL) {
+               printf("%s: couldn't establish interrupt",sc->sc_dev.dv_xname);
+               if (intrstr != NULL)
+                       printf(" at %s", intrstr);
+               printf("\n");
+               return;
+       }
+       printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
+
+       /*
+        * Sound System start-up
+        */
+       if (cs4281_init(sc,1) != 0)
+               return;
+
+       sc->type = TYPE_CS4281;
+       sc->halt_input  = cs4281_halt_input;
+       sc->halt_output = cs4281_halt_output;
+
+       sc->dma_size     = CS4281_BUFFER_SIZE / MAX_CHANNELS;
+       sc->dma_align    = 0x10;
+       sc->hw_blocksize = sc->dma_size / 2;
+       
+       /* AC 97 attachment */
+       sc->host_if.arg = sc;
+       sc->host_if.attach = cs428x_attach_codec;
+       sc->host_if.read   = cs428x_read_codec;
+       sc->host_if.write  = cs428x_write_codec;
+       sc->host_if.reset  = cs4281_reset_codec;
+       if (ac97_attach(&sc->host_if) != 0) {
+               printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname);
+               return;
+       }
+       audio_attach_mi(&cs4281_hw_if, sc, &sc->sc_dev);
+
+#if NMIDI > 0 && 0
+       midi_attach_mi(&cs4281_midi_hw_if, sc, &sc->sc_dev);
+#endif
+
+       sc->sc_suspend = PWR_RESUME;
+       sc->sc_powerhook = powerhook_establish(cs4281_power, sc);
+}
+



Home | Main Index | Thread Index | Old Index