diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2010-02-19 15:00:16 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2010-02-19 15:00:16 +0000 |
commit | af889771a40d2b7dd2767d0d2b78c67f00d4ebd6 (patch) | |
tree | 80e532cc7482314645e73bd69a0ab7947594cb8d /sys/arch/i386 | |
parent | cb97f6aa937afa9830485c4fb0232321a9caf80f (diff) |
Move auglx(4) from i386-only land to MI land.
(auglx.c is not modified in this commit yet, only moved around)
Diffstat (limited to 'sys/arch/i386')
-rw-r--r-- | sys/arch/i386/conf/files.i386 | 7 | ||||
-rw-r--r-- | sys/arch/i386/pci/auglx.c | 1380 |
2 files changed, 1 insertions, 1386 deletions
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386 index e9005bc24e7..157b160180e 100644 --- a/sys/arch/i386/conf/files.i386 +++ b/sys/arch/i386/conf/files.i386 @@ -1,4 +1,4 @@ -# $OpenBSD: files.i386,v 1.194 2009/11/26 21:15:48 deraadt Exp $ +# $OpenBSD: files.i386,v 1.195 2010/02/19 15:00:12 miod Exp $ # # new style config file for i386 architecture # @@ -150,11 +150,6 @@ device amdmsr attach amdmsr at mainbus file arch/i386/i386/amdmsr.c amdmsr needs-flag -# AMD Geode CS5536 Audio -device auglx: audio -attach auglx at pci -file arch/i386/pci/auglx.c auglx - # PCI-ISA bridge chipsets device pcib: isabus attach pcib at pci diff --git a/sys/arch/i386/pci/auglx.c b/sys/arch/i386/pci/auglx.c deleted file mode 100644 index 6dbe9e0388b..00000000000 --- a/sys/arch/i386/pci/auglx.c +++ /dev/null @@ -1,1380 +0,0 @@ -/* $OpenBSD: auglx.c,v 1.4 2009/01/13 19:44:20 grange Exp $ */ - -/* - * Copyright (c) 2008 Marc Balmer <mbalmer@openbsd.org> - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * AMD CS5536 series AC'97 audio driver. - * - * The following datasheets were helpful in the development of this - * driver: - * - * AMD Geode LX Processors Data Book - * http://www.amd.com/files/connectivitysolutions/geode/geode_lx/\ - * 33234F_LX_databook.pdf - * - * AMD Geode CS5536 Companion Device Data Book - * http://www.amd.com/files/connectivitysolutions/geode/geode_lx/\ - * 33238G_cs5536_db.pdf - * - * Realtek ALC203 Two-Channel AC'97 2.3 Audio Codec - * ftp://202.65.194.211/pc/audio/ALC203_DataSheet_1.6.pdf - * - * This driver is inspired by the auich(4) and auixp(4) drivers, some - * of the hardware-independent functionality has been derived from them - * (e.g. memory allocation for the upper level, parameter setting). - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/malloc.h> -#include <sys/sysctl.h> -#include <sys/audioio.h> - -#include <machine/bus.h> -#include <machine/cpufunc.h> - -#include <dev/pci/pcireg.h> -#include <dev/pci/pcivar.h> -#include <dev/pci/pcidevs.h> -#include <dev/audio_if.h> -#include <dev/mulaw.h> -#include <dev/auconv.h> - -#include <dev/ic/ac97.h> - -#define AUGLX_ACC_BAR 0x10 - -/* Standard GeodeLink Device (GLD) MSRs */ -#define ACC_GLD_MSR_CAP 0x51500000 /* Capabilities */ -#define ACC_GLD_MSR_CONFIG 0x51500001 /* Master configuration */ -#define ACC_GLD_MSR_SMI 0x51500002 -#define ACC_GLD_MSR_ERROR 0x51500003 -#define ACC_GLD_MSR_PM 0x51500004 /* Power management */ -#define ACC_GLD_MSR_DIAG 0x51500005 /* Diagnostics */ - -/* ACC_GLD_MSR_SMI Bit Definitions */ -#define IRQ_SSMI_FLAG 0x0000000100000000 -#define IRQ_SSMI_EN 0x0000000000000001 - -/* ACC_GLD_MSR_ERROR Bit Definitions */ -#define UNEXP_TYPE_ERR_FLAG 0x0000000100000000 -#define UNEXP_TYPE_ERR_EN 0x0000000000000001 - -/* ACC Native Registers */ -#define ACC_GPIO_STATUS 0x00 -#define ACC_GPIO_CNTL 0x04 -#define ACC_CODEC_STATUS 0x08 -#define ACC_CODEC_CNTL 0x0c -#define ACC_IRQ_STATUS 0x12 -#define ACC_ENGINE_CNTL 0x14 -#define ACC_BM0_CMD 0x20 /* Bus Master 0 Command */ -#define ACC_BM0_STATUS 0x21 /* Bus Master 0 IRQ Status */ -#define ACC_BM0_PRD 0x24 /* BM0 PRD Table Address */ -#define ACC_BM1_CMD 0x28 /* Bus Master 1 Command */ -#define ACC_BM1_STATUS 0x29 /* Bus Master 1 IRQ Status */ -#define ACC_BM1_PRD 0x2c /* BM1 PRD Table Address */ -#define ACC_BM2_CMD 0x30 /* Bus Master 2 Command */ -#define ACC_BM2_STATUS 0x31 /* Bus Master 2 IRQ Status */ -#define ACC_BM2_PRD 0x34 /* BM2 PRD Table Address */ -#define ACC_BM3_CMD 0x38 /* Bus Master 3 Command */ -#define ACC_BM3_STATUS 0x39 /* Bus Master 3 IRQ Status */ -#define ACC_BM3_PRD 0x3c /* BM3 PRD Table Address */ -#define ACC_BM4_CMD 0x40 /* Bus Master 4 Command */ -#define ACC_BM4_STATUS 0x41 /* Bus Master 4 IRQ Status */ -#define ACC_BM4_PRD 0x44 /* BM4 PRD Table Address */ -#define ACC_BM5_CMD 0x48 /* Bus Master 5 Command */ -#define ACC_BM5_STATUS 0x49 /* Bus Master 5 IRQ Status */ -#define ACC_BM5_PRD 0x4c /* BM5 PRD Table Address */ -#define ACC_BM6_CMD 0x50 /* Bus Master 6 Command */ -#define ACC_BM6_STATUS 0x51 /* Bus Master 6 IRQ Status */ -#define ACC_BM6_PRD 0x54 /* BM6 PRD Table Address */ -#define ACC_BM7_CMD 0x58 /* Bus Master 7 Command */ -#define ACC_BM7_STATUS 0x59 /* Bus Master 7 IRQ Status */ -#define ACC_BM7_PRD 0x5c /* BM7 PRD Table Address */ -#define ACC_BM0_PNTR 0x60 /* Bus Master 0 DMA Pointer */ -#define ACC_BM1_PNTR 0x64 /* Bus Master 1 DMA Pointer */ -#define ACC_BM2_PNTR 0x68 /* Bus Master 2 DMA Pointer */ -#define ACC_BM3_PNTR 0x6c /* Bus Master 3 DMA Pointer */ -#define ACC_BM4_PNTR 0x70 /* Bus Master 4 DMA Pointer */ -#define ACC_BM5_PNTR 0x74 /* Bus Master 5 DMA Pointer */ -#define ACC_BM6_PNTR 0x78 /* Bus Master 6 DMA Pointer */ -#define ACC_BM7_PNTR 0x7c /* Bus Master 7 DMA Pointer */ - -/* ACC_IRQ_STATUS Bit Definitions */ -#define BM7_IRQ_STS 0x0200 /* Audio Bus Master 7 IRQ Status */ -#define BM6_IRQ_STS 0x0100 /* Audio Bus Master 6 IRQ Status */ -#define BM5_IRQ_STS 0x0080 /* Audio Bus Master 5 IRQ Status */ -#define BM4_IRQ_STS 0x0040 /* Audio Bus Master 4 IRQ Status */ -#define BM3_IRQ_STS 0x0020 /* Audio Bus Master 3 IRQ Status */ -#define BM2_IRQ_STS 0x0010 /* Audio Bus Master 2 IRQ Status */ -#define BM1_IRQ_STS 0x0008 /* Audio Bus Master 1 IRQ Status */ -#define BM0_IRQ_STS 0x0004 /* Audio Bus Master 0 IRQ Status */ -#define WU_IRQ_STS 0x0002 /* Codec GPIO Wakeup IRQ Status */ -#define IRQ_STS 0x0001 /* Codec GPIO IRQ Status */ - -/* ACC_ENGINE_CNTL Bit Definitions */ -#define SSND_MODE 0x00000001 /* Surround Sound (5.1) Sync. Mode */ - -/* ACC_BM[x]_CMD Bit Descriptions */ -#define BMx_CMD_RW 0x08 /* 0: Mem to codec, 1: codec to mem */ -#define BMx_CMD_BYTE_ORD 0x04 /* 0: Little Endian, 1: Big Endian */ -#define BMx_CMD_BM_CTL_DIS 0x00 /* Disable bus master */ -#define BMx_CMD_BM_CTL_EN 0x01 /* Enable bus master */ -#define BMx_CMD_BM_CTL_PAUSE 0x03 /* Pause bus master */ - -/* ACC_BM[x]_STATUS Bit Definitions */ -#define BMx_BM_EOP_ERR 0x02 /* Bus master error */ -#define BMx_BM_EOP 0x01 /* End of page */ - -/* ACC_CODEC_CNTL Bit Definitions */ -#define RW_CMD 0x80000000 -#define PD_PRIM 0x00200000 -#define PD_SEC 0x00100000 -#define LNK_SHTDOWN 0x00040000 -#define LNK_WRM_RST 0x00020000 -#define CMD_NEW 0x00010000 - -/* ACC_CODEC_STATUS Bit Definitions */ -#define PRM_RDY_STS 0x00800000 -#define SEC_RDY_STS 0x00400000 -#define SDATAIN2_EN 0x00200000 -#define BM5_SEL 0x00100000 -#define BM4_SEL 0x00080000 -#define STS_NEW 0x00020000 - -#define AUGLX_TOUT 1000 /* uSec */ - -#define AUGLX_DMALIST_MAX 1 -#define AUGLX_DMASEG_MAX 65536 - -struct auglx_prd { - u_int32_t base; - u_int32_t size; -#define AUGLX_PRD_EOT 0x80000000 -#define AUGLX_PRD_EOP 0x40000000 -#define AUGLX_PRD_JMP 0x20000000 -}; - -#define AUGLX_FIXED_RATE 48000 - -struct auglx_dma { - bus_dmamap_t map; - caddr_t addr; - bus_dma_segment_t segs[AUGLX_DMALIST_MAX]; - int nsegs; - size_t size; - struct auglx_dma *next; -}; - -struct auglx_softc { - struct device sc_dev; - void *sc_ih; - - audio_device_t sc_audev; - - bus_space_tag_t sc_iot; - bus_space_handle_t sc_ioh; - bus_dma_tag_t sc_dmat; - - /* - * The CS5536 ACC has eight bus masters to support 5.1 audio. - * This driver, however, only supports main playback and recording - * since I only have a Realtek ALC203 codec available for testing. - */ - struct auglx_ring { - bus_dmamap_t sc_prd; - struct auglx_prd *sc_vprd; - int sc_nprd; - - size_t sc_size; - int nsegs; - bus_dma_segment_t seg; - - void (*intr)(void *); - void *arg; - } bm0, bm1; /* bm0: output, bm1: input */ - - struct auglx_dma *sc_dmas; - - struct ac97_codec_if *codec_if; - struct ac97_host_if host_if; - - /* power mgmt */ - void *sc_powerhook; - int sc_suspend; - u_int16_t sc_ext_ctrl; - - int sc_dmamap_flags; -}; - -#ifdef AUGLX_DEBUG -#define DPRINTF(l,x) do { if (auglx_debug & (l)) printf x; } while(0) -int auglx_debug = 0; -#define AUGLX_DBG_ACC 0x0001 -#define AUGLX_DBG_DMA 0x0002 -#define AUGLX_DBG_IRQ 0x0004 -#else -#define DPRINTF(x,y) /* nothing */ -#endif - -struct cfdriver auglx_cd = { - NULL, "auglx", DV_DULL -}; - -int auglx_open(void *, int); -void auglx_close(void *); -int auglx_query_encoding(void *, struct audio_encoding *); -int auglx_set_params(void *, int, int, struct audio_params *, - struct audio_params *); -int auglx_round_blocksize(void *, int); -int auglx_halt_output(void *); -int auglx_halt_input(void *); -int auglx_getdev(void *, struct audio_device *); -int auglx_set_port(void *, mixer_ctrl_t *); -int auglx_get_port(void *, mixer_ctrl_t *); -int auglx_query_devinfo(void *, mixer_devinfo_t *); -void *auglx_allocm(void *, int, size_t, int, int); -void auglx_freem(void *, void *, int); -size_t auglx_round_buffersize(void *, int, size_t); -paddr_t auglx_mappage(void *, void *, off_t, int); -int auglx_get_props(void *); -int auglx_trigger_output(void *, void *, void *, int, void (*)(void *), - void *, struct audio_params *); -int auglx_trigger_input(void *, void *, void *, int, void (*)(void *), - void *, struct audio_params *); -int auglx_alloc_cdata(struct auglx_softc *); -int auglx_alloc_prd(struct auglx_softc *, size_t, struct auglx_ring *); -void auglx_free_prd(struct auglx_softc *sc, struct auglx_ring *bm); -int auglx_allocmem(struct auglx_softc *, size_t, size_t, struct auglx_dma *); -void auglx_freemem(struct auglx_softc *, struct auglx_dma *); -void auglx_get_default_params(void *, int, struct audio_params *); -void auglx_powerhook(int, void *); - -struct audio_hw_if auglx_hw_if = { - auglx_open, - auglx_close, - NULL, /* drain */ - auglx_query_encoding, - auglx_set_params, - auglx_round_blocksize, - NULL, /* commit_setting */ - NULL, /* init_output */ - NULL, /* init_input */ - NULL, /* start_output */ - NULL, /* start_input */ - auglx_halt_output, - auglx_halt_input, - NULL, /* speaker_ctl */ - auglx_getdev, - NULL, /* getfd */ - auglx_set_port, - auglx_get_port, - auglx_query_devinfo, - auglx_allocm, - auglx_freem, - auglx_round_buffersize, - auglx_mappage, - auglx_get_props, - auglx_trigger_output, - auglx_trigger_input, - auglx_get_default_params -}; - -int auglx_match(struct device *, void *, void *); -void auglx_attach(struct device *, struct device *, void *); -int auglx_intr(void *); - -int auglx_attach_codec(void *, struct ac97_codec_if *); -int auglx_read_codec(void *, u_int8_t, u_int16_t *); -int auglx_write_codec(void *, u_int8_t, u_int16_t); -void auglx_reset_codec(void *); -enum ac97_host_flags auglx_flags_codec(void *); - -struct cfattach auglx_ca = { - sizeof(struct auglx_softc), auglx_match, auglx_attach -}; - -const struct pci_matchid auglx_devices[] = { - { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_AUDIO } -}; - -int -auglx_match(struct device *parent, void *match, void *aux) -{ - return (pci_matchbyid((struct pci_attach_args *)aux, auglx_devices, - sizeof(auglx_devices) / sizeof(auglx_devices[0]))); -} - -void -auglx_attach(struct device *parent, struct device *self, void *aux) -{ - struct auglx_softc *sc = (struct auglx_softc *)self; - struct pci_attach_args *pa = aux; - bus_size_t bar_size; - pci_intr_handle_t ih; - const char *intrstr; - - if (pci_mapreg_map(pa, AUGLX_ACC_BAR, PCI_MAPREG_TYPE_IO, 0, - &sc->sc_iot, &sc->sc_ioh, NULL, &bar_size, 0)) { - printf(": can't map ACC I/O space\n"); - return; - } - - sc->sc_dmat = pa->pa_dmat; - - if (pci_intr_map(pa, &ih)) { - printf(": can't map interrupt"); - bus_space_unmap(sc->sc_iot, sc->sc_ioh, bar_size); - return; - } - intrstr = pci_intr_string(pa->pa_pc, ih); - sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, auglx_intr, - sc, sc->sc_dev.dv_xname); - if (!sc->sc_ih) { - printf(": can't establish interrupt"); - if (intrstr) - printf(" at %s", intrstr); - printf("\n"); - bus_space_unmap(sc->sc_iot, sc->sc_ioh, bar_size); - return; - } - - strlcpy(sc->sc_audev.name, "CS5536 AC97", sizeof sc->sc_audev.name); - snprintf(sc->sc_audev.version, sizeof sc->sc_audev.version, "0x%02x", - PCI_REVISION(pa->pa_class)); - strlcpy(sc->sc_audev.config, sc->sc_dev.dv_xname, - sizeof sc->sc_audev.config); - - printf(": %s, %s\n", intrstr, sc->sc_audev.name); - - sc->host_if.arg = sc; - sc->host_if.attach = auglx_attach_codec; - sc->host_if.read = auglx_read_codec; - sc->host_if.write = auglx_write_codec; - sc->host_if.reset = auglx_reset_codec; - sc->host_if.flags = auglx_flags_codec; - - if (ac97_attach(&sc->host_if) != 0) { - bus_space_unmap(sc->sc_iot, sc->sc_ioh, bar_size); - return; - } - audio_attach_mi(&auglx_hw_if, sc, &sc->sc_dev); - - /* Watch for power changes */ - sc->sc_suspend = PWR_RESUME; - sc->sc_powerhook = powerhook_establish(auglx_powerhook, sc); - -} - -/* Functions to communicate with the AC97 Codec via the ACC */ -int -auglx_read_codec(void *v, u_int8_t reg, u_int16_t *val) -{ - struct auglx_softc *sc = v; - u_int32_t codec_cntl, codec_status; - int i; - - codec_cntl = RW_CMD | ((u_int32_t)reg << 24) | CMD_NEW; - bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL, codec_cntl); - - for (i = AUGLX_TOUT; i; i--) { - codec_cntl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, - ACC_CODEC_CNTL); - if (!(codec_cntl & CMD_NEW)) - break; - delay(1); - } - if (codec_cntl & CMD_NEW) { - printf("%s: codec read timeout after write\n", - sc->sc_dev.dv_xname); - return -1; - } - - for (i = AUGLX_TOUT; i; i--) { - codec_status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, - ACC_CODEC_STATUS); - if ((codec_status & STS_NEW) && (codec_status >> 24 == reg)) - break; - delay(10); - } - if (i == 0) { - printf("%s: codec status read timeout, 0x%08x\n", - sc->sc_dev.dv_xname, codec_status); - return -1; - } - - *val = codec_status & 0xffff; - DPRINTF(AUGLX_DBG_ACC, ("%s: read codec register 0x%02x: 0x%04x\n", - sc->sc_dev.dv_xname, reg, *val)); - return 0; -} - -int -auglx_write_codec(void *v, u_int8_t reg, u_int16_t val) -{ - struct auglx_softc *sc = v; - u_int32_t codec_cntl; - int i; - - DPRINTF(AUGLX_DBG_ACC, ("%s: write codec register 0x%02x: 0x%04x\n", - sc->sc_dev.dv_xname, reg, val)); - - - codec_cntl = ((u_int32_t)reg << 24) | CMD_NEW | val; - bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL, codec_cntl); - - for (i = AUGLX_TOUT; i; i--) { - codec_cntl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, - ACC_CODEC_CNTL); - if (!(codec_cntl & CMD_NEW)) - break; - delay(1); - } - if (codec_cntl & CMD_NEW) { - printf("%s: codec write timeout\n", sc->sc_dev.dv_xname); - return -1; - } - - return 0; -} - -int -auglx_attach_codec(void *v, struct ac97_codec_if *cif) -{ - struct auglx_softc *sc = v; - - sc->codec_if = cif; - return 0; -} - -void -auglx_reset_codec(void *v) -{ - struct auglx_softc *sc = v; - u_int32_t codec_cntl; - int i; - - codec_cntl = LNK_WRM_RST | CMD_NEW; - bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL, codec_cntl); - - for (i = AUGLX_TOUT; i; i--) { - codec_cntl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, - ACC_CODEC_CNTL); - if (!(codec_cntl & CMD_NEW)) - continue; - delay(1); - } - if (codec_cntl & CMD_NEW) - printf("%s: codec reset timeout\n", sc->sc_dev.dv_xname); -} - -enum ac97_host_flags -auglx_flags_codec(void *v) -{ - return 0; -} - -/* - * Audio functions - */ -int -auglx_open(void *v, int flags) -{ - return 0; -} - -void -auglx_close(void *v) -{ -} - - -int -auglx_query_encoding(void *v, struct audio_encoding *aep) -{ - switch (aep->index) { - case 0: - strlcpy(aep->name, AudioEulinear, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_ULINEAR; - aep->precision = 8; - aep->flags = AUDIO_ENCODINGFLAG_EMULATED; - return 0; - case 1: - strlcpy(aep->name, AudioEmulaw, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_ULAW; - aep->precision = 8; - aep->flags = AUDIO_ENCODINGFLAG_EMULATED; - return 0; - case 2: - strlcpy(aep->name, AudioEalaw, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_ALAW; - aep->precision = 8; - aep->flags = AUDIO_ENCODINGFLAG_EMULATED; - return 0; - case 3: - strlcpy(aep->name, AudioEslinear, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_SLINEAR; - aep->precision = 8; - aep->flags = AUDIO_ENCODINGFLAG_EMULATED; - return 0; - case 4: - strlcpy(aep->name, AudioEslinear_le, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_SLINEAR_LE; - aep->precision = 16; - aep->flags = 0; - return 0; - case 5: - strlcpy(aep->name, AudioEulinear_le, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_ULINEAR_LE; - aep->precision = 16; - aep->flags = AUDIO_ENCODINGFLAG_EMULATED; - return 0; - case 6: - strlcpy(aep->name, AudioEslinear_be, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_SLINEAR_BE; - aep->precision = 16; - aep->flags = AUDIO_ENCODINGFLAG_EMULATED; - return 0; - case 7: - strlcpy(aep->name, AudioEulinear_be, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_ULINEAR_BE; - aep->precision = 16; - aep->flags = AUDIO_ENCODINGFLAG_EMULATED; - return 0; - default: - return EINVAL; - } -} - - -int -auglx_set_params(void *v, int setmode, int usemode, struct audio_params *play, - struct audio_params *rec) -{ - struct auglx_softc *sc = v; - int error; - u_int orate; - u_int adj_rate; - - if (setmode & AUMODE_PLAY) { - play->factor = 1; - play->sw_code = NULL; - if (play->precision > 16) - play->precision = 16; - if (play->channels > 2) - play->channels = 2; - switch(play->encoding) { - case AUDIO_ENCODING_ULAW: - switch (play->channels) { - case 1: - play->factor = 4; - play->sw_code = mulaw_to_slinear16_le_mts; - break; - case 2: - play->factor = 2; - play->sw_code = mulaw_to_slinear16_le; - break; - default: - return EINVAL; - } - break; - case AUDIO_ENCODING_SLINEAR_LE: - switch (play->precision) { - case 8: - switch (play->channels) { - case 1: - play->factor = 4; - play->sw_code = linear8_to_linear16_le_mts; - break; - case 2: - play->factor = 2; - play->sw_code = linear8_to_linear16_le; - break; - default: - return EINVAL; - } - break; - case 16: - switch (play->channels) { - case 1: - play->factor = 2; - play->sw_code = noswap_bytes_mts; - break; - case 2: - break; - default: - return EINVAL; - } - break; - default: - return (EINVAL); - } - break; - case AUDIO_ENCODING_ULINEAR_LE: - switch (play->precision) { - case 8: - switch (play->channels) { - case 1: - play->factor = 4; - play->sw_code = ulinear8_to_linear16_le_mts; - break; - case 2: - play->factor = 2; - play->sw_code = ulinear8_to_linear16_le; - break; - default: - return EINVAL; - } - break; - case 16: - switch (play->channels) { - case 1: - play->factor = 2; - play->sw_code = change_sign16_le_mts; - break; - case 2: - play->sw_code = change_sign16_le; - break; - default: - return EINVAL; - } - break; - default: - return EINVAL; - } - break; - case AUDIO_ENCODING_ALAW: - switch (play->channels) { - case 1: - play->factor = 4; - play->sw_code = alaw_to_slinear16_le_mts; - break; - case 2: - play->factor = 2; - play->sw_code = alaw_to_slinear16_le; - break; - default: - return EINVAL; - } - break; - case AUDIO_ENCODING_SLINEAR_BE: - switch (play->precision) { - case 8: - switch (play->channels) { - case 1: - play->factor = 4; - play->sw_code = linear8_to_linear16_le_mts; - break; - case 2: - play->factor = 2; - play->sw_code = linear8_to_linear16_le; - break; - default: - return EINVAL; - } - break; - case 16: - switch (play->channels) { - case 1: - play->factor = 2; - play->sw_code = swap_bytes_mts; - break; - case 2: - play->sw_code = swap_bytes; - break; - default: - return EINVAL; - } - break; - default: - return EINVAL; - } - break; - case AUDIO_ENCODING_ULINEAR_BE: - switch (play->precision) { - case 8: - switch (play->channels) { - case 1: - play->factor = 4; - play->sw_code = ulinear8_to_linear16_le_mts; - break; - case 2: - play->factor = 2; - play->sw_code = ulinear8_to_linear16_le; - break; - default: - return EINVAL; - } - break; - case 16: - switch (play->channels) { - case 1: - play->factor = 2; - play->sw_code = swap_bytes_change_sign16_le_mts; - break; - case 2: - play->sw_code = swap_bytes_change_sign16_le; - break; - default: - return EINVAL; - } - break; - default: - return EINVAL; - } - break; - default: - return EINVAL; - } - - orate = adj_rate = play->sample_rate; - - play->sample_rate = adj_rate; - error = ac97_set_rate(sc->codec_if, - AC97_REG_PCM_LFE_DAC_RATE, &play->sample_rate); - if (error) - return error; - - play->sample_rate = adj_rate; - error = ac97_set_rate(sc->codec_if, - AC97_REG_PCM_SURR_DAC_RATE, &play->sample_rate); - if (error) - return error; - - play->sample_rate = adj_rate; - error = ac97_set_rate(sc->codec_if, - AC97_REG_PCM_FRONT_DAC_RATE, &play->sample_rate); - if (error) - return error; - - if (play->sample_rate == adj_rate) - play->sample_rate = orate; - } - - if (setmode & AUMODE_RECORD) { - rec->factor = 1; - rec->sw_code = 0; - if (rec->precision > 16) - rec->precision = 16; - if (rec->channels > 2) - rec->channels = 2; - switch(rec->encoding) { - case AUDIO_ENCODING_ULAW: - switch (rec->channels) { - case 1: - rec->sw_code = slinear16_to_mulaw_le_stm; - rec->factor = 4; - break; - case 2: - rec->sw_code = slinear16_to_mulaw_le; - rec->factor = 2; - break; - } - break; - case AUDIO_ENCODING_ALAW: - switch (rec->channels) { - case 1: - rec->sw_code = slinear16_to_alaw_le_stm; - rec->factor = 4; - break; - case 2: - rec->sw_code = slinear16_to_alaw_le; - rec->factor = 2; - break; - } - break; - case AUDIO_ENCODING_SLINEAR_LE: - switch (rec->precision) { - case 8: - switch (rec->channels) { - case 1: - rec->sw_code = linear16_to_linear8_le_stm; - rec->factor = 4; - break; - case 2: - rec->sw_code = linear16_to_linear8_le; - rec->factor = 2; - break; - } - break; - case 16: - switch (rec->channels) { - case 1: - rec->sw_code = linear16_decimator; - rec->factor = 2; - break; - case 2: - break; - } - break; - default: - return EINVAL; - } - break; - case AUDIO_ENCODING_ULINEAR_LE: - switch (rec->precision) { - case 8: - switch (rec->channels) { - case 1: - rec->sw_code = linear16_to_ulinear8_le_stm; - rec->factor = 4; - break; - case 2: - rec->sw_code = linear16_to_ulinear8_le; - rec->factor = 2; - break; - } - break; - case 16: - switch (rec->channels) { - case 1: - rec->sw_code = change_sign16_le_stm; - rec->factor = 2; - break; - case 2: - rec->sw_code = change_sign16_le; - break; - } - break; - default: - return EINVAL; - } - break; - case AUDIO_ENCODING_SLINEAR_BE: - switch (rec->precision) { - case 8: - switch (rec->channels) { - case 1: - rec->sw_code = linear16_to_linear8_le_stm; - rec->factor = 4; - break; - case 2: - rec->sw_code = linear16_to_linear8_le; - rec->factor = 2; - break; - } - break; - case 16: - switch (rec->channels) { - case 1: - rec->sw_code = swap_bytes_stm; - rec->factor = 2; - break; - case 2: - rec->sw_code = swap_bytes; - break; - } - break; - default: - return EINVAL; - } - break; - case AUDIO_ENCODING_ULINEAR_BE: - switch (rec->precision) { - case 8: - switch (rec->channels) { - case 1: - rec->sw_code = linear16_to_ulinear8_le_stm; - rec->factor = 4; - break; - case 2: - rec->sw_code = linear16_to_ulinear8_le; - rec->factor = 2; - break; - } - break; - case 16: - switch (rec->channels) { - case 1: - rec->sw_code = change_sign16_swap_bytes_le_stm; - rec->factor = 2; - break; - case 2: - rec->sw_code = change_sign16_swap_bytes_le; - break; - } - break; - default: - return EINVAL; - } - break; - default: - return EINVAL; - } - - orate = rec->sample_rate; - error = ac97_set_rate(sc->codec_if, AC97_REG_PCM_LR_ADC_RATE, - &rec->sample_rate); - if (error) - return error; - rec->sample_rate = orate; - } - - return 0; -} - -int -auglx_round_blocksize(void *v, int blk) -{ - return (blk + 0x3f) & ~0x3f; -} - -int -auglx_halt_output(void *v) -{ - struct auglx_softc *sc = v; - - DPRINTF(AUGLX_DBG_DMA, ("%s: halt_output\n", sc->sc_dev.dv_xname)); - - bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD, 0x00); - sc->bm0.intr = NULL; - return 0; -} - -int -auglx_halt_input(void *v) -{ - struct auglx_softc *sc = v; - - DPRINTF(AUGLX_DBG_DMA, - ("%s: halt_input\n", sc->sc_dev.dv_xname)); - - bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM1_CMD, 0x00); - sc->bm1.intr = NULL; - return 0; -} - -int -auglx_getdev(void *v, struct audio_device *adp) -{ - struct auglx_softc *sc = v; - *adp = sc->sc_audev; - return 0; -} - -int -auglx_set_port(void *v, mixer_ctrl_t *cp) -{ - struct auglx_softc *sc = v; - return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp); -} - -int -auglx_get_port(void *v, mixer_ctrl_t *cp) -{ - struct auglx_softc *sc = v; - return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp); -} - -int -auglx_query_devinfo(void *v, mixer_devinfo_t *dp) -{ - struct auglx_softc *sc = v; - return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dp); -} - -void * -auglx_allocm(void *v, int direction, size_t size, int pool, int flags) -{ - struct auglx_softc *sc = v; - struct auglx_dma *p; - int error; - - DPRINTF(AUGLX_DBG_DMA, ("%s: request buffer of size %ld, dir %d\n", - sc->sc_dev.dv_xname, size, direction)); - - /* can only use 1 segment */ - if (size > AUGLX_DMASEG_MAX) { - DPRINTF(AUGLX_DBG_DMA, - ("%s: requested buffer size too large: %d", \ - sc->sc_dev.dv_xname, size)); - return NULL; - } - - p = malloc(sizeof(*p), pool, flags | M_ZERO); - if (!p) - return NULL; - - error = auglx_allocmem(sc, size, PAGE_SIZE, p); - if (error) { - free(p, pool); - return NULL; - } - - p->next = sc->sc_dmas; - sc->sc_dmas = p; - - return p->addr; -} - -void -auglx_freem(void *v, void *ptr, int pool) -{ - struct auglx_softc *sc; - struct auglx_dma *p, **pp; - - sc = v; - for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) { - if (p->addr == ptr) { - auglx_freemem(sc, p); - *pp = p->next; - free(p, pool); - return; - } - } -} - - -size_t -auglx_round_buffersize(void *v, int direction, size_t size) -{ - if (size > AUGLX_DMASEG_MAX) - size = AUGLX_DMASEG_MAX; - - return size; -} - -paddr_t -auglx_mappage(void *v, void *mem, off_t off, int prot) -{ - struct auglx_softc *sc = v; - struct auglx_dma *p; - - if (off < 0) - return -1; - - for (p = sc->sc_dmas; p && p->addr != mem; p = p->next); - if (!p) - return -1; - - return bus_dmamem_mmap(sc->sc_dmat, p->segs, p->nsegs, - off, prot, BUS_DMA_WAITOK); -} - -int -auglx_get_props(void *v) -{ - return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; -} - -int -auglx_intr(void *v) -{ - struct auglx_softc *sc = v; - u_int16_t irq_sts; - u_int8_t bm_sts; - - irq_sts = bus_space_read_2(sc->sc_iot, sc->sc_ioh, ACC_IRQ_STATUS); - if (irq_sts == 0) - return 0; - - if (irq_sts & BM0_IRQ_STS) { - bm_sts = bus_space_read_1(sc->sc_iot, sc->sc_ioh, - ACC_BM0_STATUS); - if (sc->bm0.intr) { - sc->bm0.intr(sc->bm0.arg); - bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD, - BMx_CMD_BM_CTL_EN); - } - } else if (irq_sts & BM1_IRQ_STS) { - bm_sts = bus_space_read_1(sc->sc_iot, sc->sc_ioh, - ACC_BM1_STATUS); - if (sc->bm1.intr) { - sc->bm1.intr(sc->bm1.arg); - bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM1_CMD, - BMx_CMD_RW | BMx_CMD_BM_CTL_EN); - } - } else { - DPRINTF(AUGLX_DBG_IRQ, ("%s: stray intr, status = 0x%04x\n", - sc->sc_dev.dv_xname, irq_sts)); - return -1; - } - return 1; -} - -int -auglx_trigger_output(void *v, void *start, void *end, int blksize, - void (*intr)(void *), void *arg, struct audio_params *param) -{ - struct auglx_softc *sc = v; - struct auglx_dma *p; - size_t size; - u_int32_t addr; - int i, nprd; - - size = (size_t)((caddr_t)end - (caddr_t)start); - DPRINTF(AUGLX_DBG_DMA, ("%s: trigger_output, %p 0x%08x bytes, " - "blksize 0x%04x\n", sc->sc_dev.dv_xname, start, size, blksize)); - - for (p = sc->sc_dmas; p && p->addr != start; p = p->next); - if (!p) { - DPRINTF(AUGLX_DBG_DMA, ("%s dma reg not found\n", - sc->sc_dev.dv_xname)); - return -1; - } - - /* set up the PRDs */ - nprd = size / blksize; - if (sc->bm0.sc_nprd != nprd + 1) { - if (sc->bm0.sc_nprd > 0) - auglx_free_prd(sc, &sc->bm0); - sc->bm0.sc_nprd = nprd + 1; - auglx_alloc_prd(sc, - sc->bm0.sc_nprd * sizeof(struct auglx_prd), &sc->bm0); - } - DPRINTF(AUGLX_DBG_DMA, ("%s: nprd = %d\n", sc->sc_dev.dv_xname, - nprd)); - addr = p->segs->ds_addr; - for (i = 0; i < nprd; i++) { - sc->bm0.sc_vprd[i].base = addr; - sc->bm0.sc_vprd[i].size = blksize | AUGLX_PRD_EOP; - addr += blksize; - } - sc->bm0.sc_vprd[i].base = sc->bm0.sc_prd->dm_segs[0].ds_addr; - sc->bm0.sc_vprd[i].size = AUGLX_PRD_JMP; - -#ifdef AUGLX_DEBUG - for (i = 0; i < sc->bm0.sc_nprd; i++) - DPRINTF(AUGLX_DBG_DMA, ("%s: PRD[%d].base = %p, size %p\n", - sc->sc_dev.dv_xname, i, sc->bm0.sc_vprd[i].base, - sc->bm0.sc_vprd[i].size)); -#endif - sc->bm0.intr = intr; - sc->bm0.arg = arg; - - /* Program the BM0 PRD register */ - bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_PRD, - sc->bm0.sc_prd->dm_segs[0].ds_addr); - /* Start Audio Bus Master 0 */ - bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD, - BMx_CMD_BM_CTL_EN); - return 0; -} - -int -auglx_trigger_input(void *v, void *start, void *end, int blksize, - void (*intr)(void *), void * arg, struct audio_params *param) -{ - struct auglx_softc *sc = v; - struct auglx_dma *p; - size_t size; - u_int32_t addr; - int i, nprd; - - size = (size_t)((caddr_t)end - (caddr_t)start); - DPRINTF(AUGLX_DBG_DMA, ("%s: trigger_input, %p 0x%08x bytes, " - "blksize 0x%04x\n", sc->sc_dev.dv_xname, start, size, blksize)); - - for (p = sc->sc_dmas; p && p->addr != start; p = p->next); - if (!p) { - DPRINTF(AUGLX_DBG_DMA, ("%s dma reg not found\n", - sc->sc_dev.dv_xname)); - return -1; - } - - /* set up the PRDs */ - nprd = size / blksize; - if (sc->bm1.sc_nprd != nprd + 1) { - if (sc->bm1.sc_nprd > 0) - auglx_free_prd(sc, &sc->bm1); - sc->bm1.sc_nprd = nprd + 1; - auglx_alloc_prd(sc, - sc->bm1.sc_nprd * sizeof(struct auglx_prd), &sc->bm1); - } - DPRINTF(AUGLX_DBG_DMA, ("%s: nprd = %d\n", sc->sc_dev.dv_xname, - nprd)); - addr = p->segs->ds_addr; - for (i = 0; i < nprd; i++) { - sc->bm1.sc_vprd[i].base = addr; - sc->bm1.sc_vprd[i].size = blksize | AUGLX_PRD_EOP; - addr += blksize; - } - sc->bm1.sc_vprd[i].base = sc->bm1.sc_prd->dm_segs[0].ds_addr; - sc->bm1.sc_vprd[i].size = AUGLX_PRD_JMP; - -#ifdef AUGLX_DEBUG - for (i = 0; i < sc->bm1.sc_nprd; i++) - DPRINTF(AUGLX_DBG_DMA, ("%s: PRD[%d].base = %p, size %p\n", - sc->sc_dev.dv_xname, i, sc->bm1.sc_vprd[i].base, - sc->bm1.sc_vprd[i].size)); -#endif - sc->bm1.intr = intr; - sc->bm1.arg = arg; - - /* Program the BM1 PRD register */ - bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM1_PRD, - sc->bm1.sc_prd->dm_segs[0].ds_addr); - /* Start Audio Bus Master 0 */ - bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM1_CMD, - BMx_CMD_RW | BMx_CMD_BM_CTL_EN); - return 0; -} - -int -auglx_allocmem(struct auglx_softc *sc, size_t size, size_t align, - struct auglx_dma *p) -{ - int error; - - p->size = size; - error = bus_dmamem_alloc(sc->sc_dmat, p->size, align, 0, p->segs, 1, - &p->nsegs, BUS_DMA_NOWAIT); - if (error) { - DPRINTF(AUGLX_DBG_DMA, - ("%s: bus_dmamem_alloc failed: error %d\n", - sc->sc_dev.dv_xname, error)); - return error; - } - - error = bus_dmamem_map(sc->sc_dmat, p->segs, 1, p->size, &p->addr, - BUS_DMA_NOWAIT | sc->sc_dmamap_flags); - if (error) { - DPRINTF(AUGLX_DBG_DMA, - ("%s: bus_dmamem_map failed: error %d\n", - sc->sc_dev.dv_xname, error)); - goto free; - } - - error = bus_dmamap_create(sc->sc_dmat, p->size, 1, p->size, 0, - BUS_DMA_NOWAIT, &p->map); - if (error) { - DPRINTF(AUGLX_DBG_DMA, - ("%s: bus_dmamap_create failed: error %d\n", - sc->sc_dev.dv_xname, error)); - goto unmap; - } - - error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, p->size, NULL, - BUS_DMA_NOWAIT); - if (error) { - DPRINTF(AUGLX_DBG_DMA, - ("%s: bus_dmamap_load failed: error %d\n", - sc->sc_dev.dv_xname, error)); - goto destroy; - } - return 0; - - destroy: - bus_dmamap_destroy(sc->sc_dmat, p->map); - unmap: - bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size); - free: - bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs); - return error; -} - -void -auglx_freemem(struct auglx_softc *sc, struct auglx_dma *p) -{ - bus_dmamap_unload(sc->sc_dmat, p->map); - bus_dmamap_destroy(sc->sc_dmat, p->map); - bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size); - bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs); -} - -void -auglx_get_default_params(void *addr, int mode, struct audio_params *params) -{ - ac97_get_default_params(params); -} - -int -auglx_alloc_prd(struct auglx_softc *sc, size_t size, struct auglx_ring *bm) -{ - int error, rseg; - - /* - * Allocate PRD table structure, and create and load the - * DMA map for it. - */ - if ((error = bus_dmamem_alloc(sc->sc_dmat, size, - PAGE_SIZE, 0, &bm->seg, 1, &rseg, 0)) != 0) { - printf("%s: unable to allocate PRD, error = %d\n", - sc->sc_dev.dv_xname, error); - goto fail_0; - } - - if ((error = bus_dmamem_map(sc->sc_dmat, &bm->seg, rseg, - size, (caddr_t *)&bm->sc_vprd, - sc->sc_dmamap_flags)) != 0) { - printf("%s: unable to map PRD, error = %d\n", - sc->sc_dev.dv_xname, error); - goto fail_1; - } - - if ((error = bus_dmamap_create(sc->sc_dmat, size, - 1, size, 0, 0, &bm->sc_prd)) != 0) { - printf("%s: unable to create PRD DMA map, " - "error = %d\n", sc->sc_dev.dv_xname, error); - goto fail_2; - } - - if ((error = bus_dmamap_load(sc->sc_dmat, bm->sc_prd, bm->sc_vprd, - size, NULL, 0)) != 0) { - printf("%s: unable tp load control data DMA map, " - "error = %d\n", sc->sc_dev.dv_xname, error); - goto fail_3; - } - - return 0; - - fail_3: - bus_dmamap_destroy(sc->sc_dmat, bm->sc_prd); - fail_2: - bus_dmamem_unmap(sc->sc_dmat, (caddr_t)bm->sc_vprd, - sizeof(struct auglx_prd)); - fail_1: - bus_dmamem_free(sc->sc_dmat, &bm->seg, rseg); - fail_0: - return error; -} - -void -auglx_free_prd(struct auglx_softc *sc, struct auglx_ring *bm) -{ - bus_dmamap_unload(sc->sc_dmat, bm->sc_prd); - bus_dmamap_destroy(sc->sc_dmat, bm->sc_prd); - bus_dmamem_unmap(sc->sc_dmat, (caddr_t)bm->sc_vprd, bm->sc_size); - bus_dmamem_free(sc->sc_dmat, &bm->seg, bm->nsegs); -} - -void -auglx_powerhook(int why, void *self) -{ - struct auglx_softc *sc = self; - - if (why != PWR_RESUME) { - /* Power down */ - sc->sc_suspend = why; - auglx_read_codec(sc, AC97_REG_EXT_AUDIO_CTRL, &sc->sc_ext_ctrl); - } else { - /* Wake up */ - if (sc->sc_suspend == PWR_RESUME) { - printf("%s: resume without suspend?\n", - sc->sc_dev.dv_xname); - sc->sc_suspend = why; - return; - } - sc->sc_suspend = why; - auglx_reset_codec(sc); - delay(1000); - (sc->codec_if->vtbl->restore_ports)(sc->codec_if); - auglx_write_codec(sc, AC97_REG_EXT_AUDIO_CTRL, sc->sc_ext_ctrl); - } -} |